забыл angular.isArrayLikeObject:
(function() { 'use strict'; angular.extend( angular, { isArrayLikeObject: isArrayLikeObject }); /** * Проверяет, является ли переданное значение массивоподобным объектом * @param item {*} * @returns {boolean} */ function isArrayLikeObject( item ) { if ( angular.isObject( item ) ) { return 'length' in item; } else { return false; } } }()); |
Клево! Тоже написал директиву для загрузки, которая работает с ресурсами. Одна проблема, которую пока не смог победить — отмена загрузки. Т.е. при удалении элемента, связанного с загружаемым файлом должна отменяться загрузка (функцией abort). К сожалению, отдельно эту функцию из xhr не перетащить в scope (не будет работать), а при копировании всего объекта xhr в scope постоянно появляются ошибки.
Как разберусь — тоже выложу) |
Если интересно, переписал код (но еще не закончил) http://learn.javascript.ru/play/7VhTcc
упразднил все сервисы, кроме $fileUploader p.s.: работает из песочницы (без сервера) |
У меня всё проще. Существует всего одна директива ui-file, которая накладывается на любой тег, после чего на область в теге становится сразу возможным перетаскивать файлы. Если этим тегом является инпут с типом file, то загружать можно еще и стандартным способом. В будущем можно сделать, чтобы такой невидимый инпут генерировался бы автоматически, если директива будет применена к ссылке или кнопке.
Директива: http://plnkr.co/edit/5Ke7tELWHkSgoCU7IpHm?p=preview Пример надо еще допиливать Стараюсь делать как можно меньше общих функций между директивой и областью видимости. По сути, должна быть только одна createItem, а прогресс, имя файла и т.п. уже в модель записывать. |
Цитата:
Мои вопросы и комментарии: 1. Для чего эта проверка? var ok = e.dataTransfer && e.dataTransfer.types && e.dataTransfer.types.indexOf('Files') >= 0 в моей реализации есть такая штука var dataTransfer = event.dataTransfer ? event.dataTransfer : event.originalEvent.dataTransfer; // jQuery fix; фиксит подключении жуквери (т.е., если подключаешь жуквери, то получаешь ошибку без этого фикса) в моей реализации .directive( 'ngFileDrop', function( $fileUploader ) { return { // don't use drag-n-drop files in IE9, because not File API support link: !window.File ? angular.noop : function( $scope, $element ) { // code } }; }) обрати внимание на строку линковки. В IE9 есть событие сброса, но нету файлов :) Будь осторожен ) 2. Почему на мой взгляд не удобно одной директивой Если она висит на инпуте, то и сброс файла необходимо производить в инпут (что удобно далеко не всегда, проще бросать на документ, например) В моей реализации можно: - загружать файлы с дран-н-дропом и с помощью инпута - либо только дран-н-дропом - либо только инпутом В моей реализации ловящих областей может быть много, также как и инпутов. 3. Не понял, можно ли в твоей реализации "загружать по кнопке", т.е. сбросили файлы, а затем нажали кнопку загрузить (у меня для этого есть очередь) 4. валидаторы и генерацию превьюшек я бы вынес из директивы... и я вынес :D 5. благодаря паттерну "наблюдатель" в моей реализации, за событиями загрузки и добавления в очередь могут следить сразу несколько контроллеров |
Цитата:
P.S. У меня с jQuery не глючит, кстати. Цитата:
Цитата:
Цитата:
Цитата:
Пока основной кейс, в котором тестирую, такой: http://tamtakoe.ru/photoalbum/. Включает в себя практически все ситуации (кроме общего прогресса). Еще хочу уйти от функций в области видимости и вынести createItem() в настройку директивы... |
В первом приближении... Вот демка http://tamtakoe.ru/uploader/
А тут демка, где можно с фронтендом пограть (в последних браузерах): http://plnkr.co/edit/HKbvgle4zqfqCKcpLJDi?p=preview. Ключевой файл file.js Апи примерно устаканилось. Осталось сделать отмену загрузки и подтягивать кроссбраузерность |
Shitbox2, молодец ) Ковер и гендольф (или как его там) заслуживают отдельного упоминания :D
у меня пока такая штука получилась http://www.screencapture.ru/file/1190575A Что есть: Директивы: - ngFileSelect - вешается на <input type="file" /> - ngFileDrop - вешается на DOM элемент, кот. будет ловить файлы (как правило, это весь документ) - ngFileOver - вешается на элемент, кот. будет реагировать (добавляться класс), когда файлы находятся над drop элементом. По умолчанию добавляется класс "ng-file-over". Другой класс можно задать в параметре атрибута ng-file-over="className" (в этом плане ничего не менял) Один сервис: - $fileUploader - управление очередью и загрузка файлов $fileUploader свойства: - url: общий для всех файлов. Можно индивидуализировать для каждого файла, после добавления файла в хранилище - alias - псевдоним, под которым сервер увидит файл. Общий для всех файлов. Можно индивидуализировать для каждого файла, после добавления файла в хранилище - autoUpload - автозагрузка (true/false) - removeAfterUpload - удалить из очереди после загрузки (true/false) - filters - фильтры, применяемые к файлам перед добавлением в очередь. По умолчанию присутствует simple filer : ) - queue - очередь методы: - bind - пожалуй, один из наиболее важных. Регистрирует коллбеки. Позволяет повесить на одно событие сколько угодно (в пределах разумного :)) обработчиков. - addToQueue - добавляет файлы в очередь загрузки - removeFromQueue - удаляет файл из очереди по индексу - clearQueue - очищает очередь - uploadItem - загружает файл по индексу - uploadAll - загружает все файлы в очереди коллбеки: - afteraddingfile - после добавления файла в очередь - afteraddingall - после добавления всех файлов в очередь - beforeupload - перед загрузкой - progress - индикация загрузки файла - success - успешная загрузка - error - ошибка при загрузке - complete - загрузка завершена Чтобы было проще понять, приведу кусок кода: app.controller( 'MainController', function( $scope, $fileUploader ) { $scope.model = {}; // пользовательские фильтры $scope.filter1 = function( item ) { console.log( 'filter1' ); return true; }; // их может быть много, главное их добавить (push) $scope.filter2 = function( item ) { console.log( 'filter2' ); return true; }; // коллбек "после добавления файла в очередь" $scope.afterAddingFile = function( item ) { console.log( item ); }; // коллбек "после добавления всех файлов в очередь" $scope.afterAddingAll = function( items ) { $scope.model.items = $fileUploader.queue; $scope.$apply(); }; // коллбек "перед загрузкой" $scope.beforeUpload = function( item ) { console.log( item ); }; // коллбек "progress для файла" $scope.progress = function( progress ) { console.log( 'Progress: ' + progress ); $scope.$apply(); }; // коллбек "success для файла" $scope.success = function( xhr ) { console.log( 'Success: ' + xhr.response ); }; // коллбек "complete для файла" $scope.complete = function( xhr ) { console.log( 'Complete: ' + xhr.response ); $scope.$apply(); }; // управление очередью $scope.uploadAll = function() { $fileUploader.uploadAll(); }; // управление очередью $scope.removeAll = function() { $fileUploader.clearQueue(); }; $fileUploader.url = '/upload.php'; // добавление фильтров $fileUploader.filters.push( $scope.filter1 ); $fileUploader.filters.push( $scope.filter2 ); // регистрация наблюдателей $fileUploader.bind( 'afteraddingfile', $scope.afterAddingFile ); $fileUploader.bind( 'afteraddingall', $scope.afterAddingAll ); $fileUploader.bind( 'beforeupload', $scope.beforeUpload ); $fileUploader.bind( 'progress', $scope.progress ); $fileUploader.bind( 'success', $scope.success ); $fileUploader.bind( 'complete', $scope.complete ); }); т.о. на любое событие может подписаться произвольное количество раз любой контроллер (или несколько контроллеров) код http://learn.javascript.ru/play/DUtgpc Насчет абортов. Говорят, это плохо :D Хочу сделать Progress, Success(may be) и Complete для всей очереди, после чего приступлю к генерации превьюшек. Скорее всего у меня будет для этого отдельный сервис. Как то так :) |
|
Клёво) У меня все руки не доходят свой на Гитхаб выложить. А нужен ли observer? Я делаю проще. Подключаю $rootScope где надо и просто подписываюсь $rootScope.$on('myAction', fn). В любом случае все события до корневой области дойдут)
|
Часовой пояс GMT +3, время: 13:05. |