[ Index ] |
WordPress Cross Reference |
[Summary view] [Print] [Text view]
1 /* global pluploadL10n, plupload, _wpPluploadSettings */ 2 3 window.wp = window.wp || {}; 4 5 (function( exports, $ ) { 6 var Uploader; 7 8 if ( typeof _wpPluploadSettings === 'undefined' ) 9 return; 10 11 /** 12 * An object that helps create a WordPress uploader using plupload. 13 * 14 * @param options - object - The options passed to the new plupload instance. 15 * Accepts the following parameters: 16 * - container - The id of uploader container. 17 * - browser - The id of button to trigger the file select. 18 * - dropzone - The id of file drop target. 19 * - plupload - An object of parameters to pass to the plupload instance. 20 * - params - An object of parameters to pass to $_POST when uploading the file. 21 * Extends this.plupload.multipart_params under the hood. 22 * 23 * @param attributes - object - Attributes and methods for this specific instance. 24 */ 25 Uploader = function( options ) { 26 var self = this, 27 elements = { 28 container: 'container', 29 browser: 'browse_button', 30 dropzone: 'drop_element' 31 }, 32 key, error; 33 34 this.supports = { 35 upload: Uploader.browser.supported 36 }; 37 38 this.supported = this.supports.upload; 39 40 if ( ! this.supported ) 41 return; 42 43 // Use deep extend to ensure that multipart_params and other objects are cloned. 44 this.plupload = $.extend( true, { multipart_params: {} }, Uploader.defaults ); 45 this.container = document.body; // Set default container. 46 47 // Extend the instance with options 48 // 49 // Use deep extend to allow options.plupload to override individual 50 // default plupload keys. 51 $.extend( true, this, options ); 52 53 // Proxy all methods so this always refers to the current instance. 54 for ( key in this ) { 55 if ( $.isFunction( this[ key ] ) ) 56 this[ key ] = $.proxy( this[ key ], this ); 57 } 58 59 // Ensure all elements are jQuery elements and have id attributes 60 // Then set the proper plupload arguments to the ids. 61 for ( key in elements ) { 62 if ( ! this[ key ] ) 63 continue; 64 65 this[ key ] = $( this[ key ] ).first(); 66 67 if ( ! this[ key ].length ) { 68 delete this[ key ]; 69 continue; 70 } 71 72 if ( ! this[ key ].prop('id') ) 73 this[ key ].prop( 'id', '__wp-uploader-id-' + Uploader.uuid++ ); 74 this.plupload[ elements[ key ] ] = this[ key ].prop('id'); 75 } 76 77 // If the uploader has neither a browse button nor a dropzone, bail. 78 if ( ! ( this.browser && this.browser.length ) && ! ( this.dropzone && this.dropzone.length ) ) 79 return; 80 81 this.uploader = new plupload.Uploader( this.plupload ); 82 delete this.plupload; 83 84 // Set default params and remove this.params alias. 85 this.param( this.params || {} ); 86 delete this.params; 87 88 error = function( message, data, file ) { 89 if ( file.attachment ) 90 file.attachment.destroy(); 91 92 Uploader.errors.unshift({ 93 message: message || pluploadL10n.default_error, 94 data: data, 95 file: file 96 }); 97 98 self.error( message, data, file ); 99 }; 100 101 this.uploader.init(); 102 103 this.supports.dragdrop = this.uploader.features.dragdrop && ! Uploader.browser.mobile; 104 105 // Generate drag/drop helper classes. 106 (function( dropzone, supported ) { 107 var timer, active; 108 109 if ( ! dropzone ) 110 return; 111 112 dropzone.toggleClass( 'supports-drag-drop', !! supported ); 113 114 if ( ! supported ) 115 return dropzone.unbind('.wp-uploader'); 116 117 // 'dragenter' doesn't fire correctly, 118 // simulate it with a limited 'dragover' 119 dropzone.bind( 'dragover.wp-uploader', function(){ 120 if ( timer ) 121 clearTimeout( timer ); 122 123 if ( active ) 124 return; 125 126 dropzone.trigger('dropzone:enter').addClass('drag-over'); 127 active = true; 128 }); 129 130 dropzone.bind('dragleave.wp-uploader, drop.wp-uploader', function(){ 131 // Using an instant timer prevents the drag-over class from 132 // being quickly removed and re-added when elements inside the 133 // dropzone are repositioned. 134 // 135 // See http://core.trac.wordpress.org/ticket/21705 136 timer = setTimeout( function() { 137 active = false; 138 dropzone.trigger('dropzone:leave').removeClass('drag-over'); 139 }, 0 ); 140 }); 141 }( this.dropzone, this.supports.dragdrop )); 142 143 if ( this.browser ) { 144 this.browser.on( 'mouseenter', this.refresh ); 145 } else { 146 this.uploader.disableBrowse( true ); 147 // If HTML5 mode, hide the auto-created file container. 148 $('#' + this.uploader.id + '_html5_container').hide(); 149 } 150 151 this.uploader.bind( 'FilesAdded', function( up, files ) { 152 _.each( files, function( file ) { 153 var attributes, image; 154 155 // Ignore failed uploads. 156 if ( plupload.FAILED === file.status ) 157 return; 158 159 // Generate attributes for a new `Attachment` model. 160 attributes = _.extend({ 161 file: file, 162 uploading: true, 163 date: new Date(), 164 filename: file.name, 165 menuOrder: 0, 166 uploadedTo: wp.media.model.settings.post.id 167 }, _.pick( file, 'loaded', 'size', 'percent' ) ); 168 169 // Handle early mime type scanning for images. 170 image = /(?:jpe?g|png|gif)$/i.exec( file.name ); 171 172 // Did we find an image? 173 if ( image ) { 174 attributes.type = 'image'; 175 176 // `jpeg`, `png` and `gif` are valid subtypes. 177 // `jpg` is not, so map it to `jpeg`. 178 attributes.subtype = ( 'jpg' === image[0] ) ? 'jpeg' : image[0]; 179 } 180 181 // Create the `Attachment`. 182 file.attachment = wp.media.model.Attachment.create( attributes ); 183 184 Uploader.queue.add( file.attachment ); 185 186 self.added( file.attachment ); 187 }); 188 189 up.refresh(); 190 up.start(); 191 }); 192 193 this.uploader.bind( 'UploadProgress', function( up, file ) { 194 file.attachment.set( _.pick( file, 'loaded', 'percent' ) ); 195 self.progress( file.attachment ); 196 }); 197 198 this.uploader.bind( 'FileUploaded', function( up, file, response ) { 199 var complete; 200 201 try { 202 response = JSON.parse( response.response ); 203 } catch ( e ) { 204 return error( pluploadL10n.default_error, e, file ); 205 } 206 207 if ( ! _.isObject( response ) || _.isUndefined( response.success ) ) 208 return error( pluploadL10n.default_error, null, file ); 209 else if ( ! response.success ) 210 return error( response.data && response.data.message, response.data, file ); 211 212 _.each(['file','loaded','size','percent'], function( key ) { 213 file.attachment.unset( key ); 214 }); 215 216 file.attachment.set( _.extend( response.data, { uploading: false }) ); 217 wp.media.model.Attachment.get( response.data.id, file.attachment ); 218 219 complete = Uploader.queue.all( function( attachment ) { 220 return ! attachment.get('uploading'); 221 }); 222 223 if ( complete ) 224 Uploader.queue.reset(); 225 226 self.success( file.attachment ); 227 }); 228 229 this.uploader.bind( 'Error', function( up, pluploadError ) { 230 var message = pluploadL10n.default_error, 231 key; 232 233 // Check for plupload errors. 234 for ( key in Uploader.errorMap ) { 235 if ( pluploadError.code === plupload[ key ] ) { 236 message = Uploader.errorMap[ key ]; 237 if ( _.isFunction( message ) ) 238 message = message( pluploadError.file, pluploadError ); 239 break; 240 } 241 } 242 243 error( message, pluploadError, pluploadError.file ); 244 up.refresh(); 245 }); 246 247 this.init(); 248 }; 249 250 // Adds the 'defaults' and 'browser' properties. 251 $.extend( Uploader, _wpPluploadSettings ); 252 253 Uploader.uuid = 0; 254 255 Uploader.errorMap = { 256 'FAILED': pluploadL10n.upload_failed, 257 'FILE_EXTENSION_ERROR': pluploadL10n.invalid_filetype, 258 'IMAGE_FORMAT_ERROR': pluploadL10n.not_an_image, 259 'IMAGE_MEMORY_ERROR': pluploadL10n.image_memory_exceeded, 260 'IMAGE_DIMENSIONS_ERROR': pluploadL10n.image_dimensions_exceeded, 261 'GENERIC_ERROR': pluploadL10n.upload_failed, 262 'IO_ERROR': pluploadL10n.io_error, 263 'HTTP_ERROR': pluploadL10n.http_error, 264 'SECURITY_ERROR': pluploadL10n.security_error, 265 266 'FILE_SIZE_ERROR': function( file ) { 267 return pluploadL10n.file_exceeds_size_limit.replace('%s', file.name); 268 } 269 }; 270 271 $.extend( Uploader.prototype, { 272 /** 273 * Acts as a shortcut to extending the uploader's multipart_params object. 274 * 275 * param( key ) 276 * Returns the value of the key. 277 * 278 * param( key, value ) 279 * Sets the value of a key. 280 * 281 * param( map ) 282 * Sets values for a map of data. 283 */ 284 param: function( key, value ) { 285 if ( arguments.length === 1 && typeof key === 'string' ) 286 return this.uploader.settings.multipart_params[ key ]; 287 288 if ( arguments.length > 1 ) { 289 this.uploader.settings.multipart_params[ key ] = value; 290 } else { 291 $.extend( this.uploader.settings.multipart_params, key ); 292 } 293 }, 294 295 init: function() {}, 296 error: function() {}, 297 success: function() {}, 298 added: function() {}, 299 progress: function() {}, 300 complete: function() {}, 301 refresh: function() { 302 var node, attached, container, id; 303 304 if ( this.browser ) { 305 node = this.browser[0]; 306 307 // Check if the browser node is in the DOM. 308 while ( node ) { 309 if ( node === document.body ) { 310 attached = true; 311 break; 312 } 313 node = node.parentNode; 314 } 315 316 // If the browser node is not attached to the DOM, use a 317 // temporary container to house it, as the browser button 318 // shims require the button to exist in the DOM at all times. 319 if ( ! attached ) { 320 id = 'wp-uploader-browser-' + this.uploader.id; 321 322 container = $( '#' + id ); 323 if ( ! container.length ) { 324 container = $('<div class="wp-uploader-browser" />').css({ 325 position: 'fixed', 326 top: '-1000px', 327 left: '-1000px', 328 height: 0, 329 width: 0 330 }).attr( 'id', 'wp-uploader-browser-' + this.uploader.id ).appendTo('body'); 331 } 332 333 container.append( this.browser ); 334 } 335 } 336 337 this.uploader.refresh(); 338 } 339 }); 340 341 Uploader.queue = new wp.media.model.Attachments( [], { query: false }); 342 Uploader.errors = new Backbone.Collection(); 343 344 exports.Uploader = Uploader; 345 })( wp, jQuery );
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue Mar 25 01:41:18 2014 | WordPress honlapkészítés: online1.hu |