You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

498 lines
16 KiB

  1. /* global plupload, pluploadL10n, ajaxurl, post_id, wpUploaderInit, deleteUserSetting, setUserSetting, getUserSetting, shortform */
  2. var topWin = window.dialogArguments || opener || parent || top, uploader, uploader_init;
  3. // progress and success handlers for media multi uploads
  4. function fileQueued(fileObj) {
  5. // Get rid of unused form
  6. jQuery('.media-blank').remove();
  7. var items = jQuery('#media-items').children(), postid = post_id || 0;
  8. // Collapse a single item
  9. if ( items.length == 1 ) {
  10. items.removeClass('open').find('.slidetoggle').slideUp(200);
  11. }
  12. // Create a progress bar containing the filename
  13. jQuery('<div class="media-item">')
  14. .attr( 'id', 'media-item-' + fileObj.id )
  15. .addClass('child-of-' + postid)
  16. .append('<div class="progress"><div class="percent">0%</div><div class="bar"></div></div>',
  17. jQuery('<div class="filename original">').text( ' ' + fileObj.name ))
  18. .appendTo( jQuery('#media-items' ) );
  19. // Disable submit
  20. jQuery('#insert-gallery').prop('disabled', true);
  21. }
  22. function uploadStart() {
  23. try {
  24. if ( typeof topWin.tb_remove != 'undefined' )
  25. topWin.jQuery('#TB_overlay').unbind('click', topWin.tb_remove);
  26. } catch(e){}
  27. return true;
  28. }
  29. function uploadProgress(up, file) {
  30. var item = jQuery('#media-item-' + file.id);
  31. jQuery('.bar', item).width( (200 * file.loaded) / file.size );
  32. jQuery('.percent', item).html( file.percent + '%' );
  33. }
  34. // check to see if a large file failed to upload
  35. function fileUploading( up, file ) {
  36. var hundredmb = 100 * 1024 * 1024,
  37. max = parseInt( up.settings.max_file_size, 10 );
  38. if ( max > hundredmb && file.size > hundredmb ) {
  39. setTimeout( function() {
  40. if ( file.status < 3 && file.loaded === 0 ) { // not uploading
  41. wpFileError( file, pluploadL10n.big_upload_failed.replace( '%1$s', '<a class="uploader-html" href="#">' ).replace( '%2$s', '</a>' ) );
  42. up.stop(); // stops the whole queue
  43. up.removeFile( file );
  44. up.start(); // restart the queue
  45. }
  46. }, 10000 ); // wait for 10 sec. for the file to start uploading
  47. }
  48. }
  49. function updateMediaForm() {
  50. var items = jQuery('#media-items').children();
  51. // Just one file, no need for collapsible part
  52. if ( items.length == 1 ) {
  53. items.addClass('open').find('.slidetoggle').show();
  54. jQuery('.insert-gallery').hide();
  55. } else if ( items.length > 1 ) {
  56. items.removeClass('open');
  57. // Only show Gallery/Playlist buttons when there are at least two files.
  58. jQuery('.insert-gallery').show();
  59. }
  60. // Only show Save buttons when there is at least one file.
  61. if ( items.not('.media-blank').length > 0 )
  62. jQuery('.savebutton').show();
  63. else
  64. jQuery('.savebutton').hide();
  65. }
  66. function uploadSuccess(fileObj, serverData) {
  67. var item = jQuery('#media-item-' + fileObj.id);
  68. // on success serverData should be numeric, fix bug in html4 runtime returning the serverData wrapped in a <pre> tag
  69. serverData = serverData.replace(/^<pre>(\d+)<\/pre>$/, '$1');
  70. // if async-upload returned an error message, place it in the media item div and return
  71. if ( serverData.match(/media-upload-error|error-div/) ) {
  72. item.html(serverData);
  73. return;
  74. } else {
  75. jQuery('.percent', item).html( pluploadL10n.crunching );
  76. }
  77. prepareMediaItem(fileObj, serverData);
  78. updateMediaForm();
  79. // Increment the counter.
  80. if ( post_id && item.hasClass('child-of-' + post_id) )
  81. jQuery('#attachments-count').text(1 * jQuery('#attachments-count').text() + 1);
  82. }
  83. function setResize( arg ) {
  84. if ( arg ) {
  85. if ( window.resize_width && window.resize_height ) {
  86. uploader.settings.resize = {
  87. enabled: true,
  88. width: window.resize_width,
  89. height: window.resize_height,
  90. quality: 100
  91. };
  92. } else {
  93. uploader.settings.multipart_params.image_resize = true;
  94. }
  95. } else {
  96. delete( uploader.settings.multipart_params.image_resize );
  97. }
  98. }
  99. function prepareMediaItem(fileObj, serverData) {
  100. var f = ( typeof shortform == 'undefined' ) ? 1 : 2, item = jQuery('#media-item-' + fileObj.id);
  101. if ( f == 2 && shortform > 2 )
  102. f = shortform;
  103. try {
  104. if ( typeof topWin.tb_remove != 'undefined' )
  105. topWin.jQuery('#TB_overlay').click(topWin.tb_remove);
  106. } catch(e){}
  107. if ( isNaN(serverData) || !serverData ) { // Old style: Append the HTML returned by the server -- thumbnail and form inputs
  108. item.append(serverData);
  109. prepareMediaItemInit(fileObj);
  110. } else { // New style: server data is just the attachment ID, fetch the thumbnail and form html from the server
  111. item.load('async-upload.php', {attachment_id:serverData, fetch:f}, function(){prepareMediaItemInit(fileObj);updateMediaForm();});
  112. }
  113. }
  114. function prepareMediaItemInit(fileObj) {
  115. var item = jQuery('#media-item-' + fileObj.id);
  116. // Clone the thumbnail as a "pinkynail" -- a tiny image to the left of the filename
  117. jQuery('.thumbnail', item).clone().attr('class', 'pinkynail toggle').prependTo(item);
  118. // Replace the original filename with the new (unique) one assigned during upload
  119. jQuery('.filename.original', item).replaceWith( jQuery('.filename.new', item) );
  120. // Bind AJAX to the new Delete button
  121. jQuery('a.delete', item).click(function(){
  122. // Tell the server to delete it. TODO: handle exceptions
  123. jQuery.ajax({
  124. url: ajaxurl,
  125. type: 'post',
  126. success: deleteSuccess,
  127. error: deleteError,
  128. id: fileObj.id,
  129. data: {
  130. id : this.id.replace(/[^0-9]/g, ''),
  131. action : 'trash-post',
  132. _ajax_nonce : this.href.replace(/^.*wpnonce=/,'')
  133. }
  134. });
  135. return false;
  136. });
  137. // Bind AJAX to the new Undo button
  138. jQuery('a.undo', item).click(function(){
  139. // Tell the server to untrash it. TODO: handle exceptions
  140. jQuery.ajax({
  141. url: ajaxurl,
  142. type: 'post',
  143. id: fileObj.id,
  144. data: {
  145. id : this.id.replace(/[^0-9]/g,''),
  146. action: 'untrash-post',
  147. _ajax_nonce: this.href.replace(/^.*wpnonce=/,'')
  148. },
  149. success: function( ){
  150. var type,
  151. item = jQuery('#media-item-' + fileObj.id);
  152. if ( type = jQuery('#type-of-' + fileObj.id).val() )
  153. jQuery('#' + type + '-counter').text(jQuery('#' + type + '-counter').text()-0+1);
  154. if ( post_id && item.hasClass('child-of-'+post_id) )
  155. jQuery('#attachments-count').text(jQuery('#attachments-count').text()-0+1);
  156. jQuery('.filename .trashnotice', item).remove();
  157. jQuery('.filename .title', item).css('font-weight','normal');
  158. jQuery('a.undo', item).addClass('hidden');
  159. jQuery('.menu_order_input', item).show();
  160. item.css( {backgroundColor:'#ceb'} ).animate( {backgroundColor: '#fff'}, { queue: false, duration: 500, complete: function(){ jQuery(this).css({backgroundColor:''}); } }).removeClass('undo');
  161. }
  162. });
  163. return false;
  164. });
  165. // Open this item if it says to start open (e.g. to display an error)
  166. jQuery('#media-item-' + fileObj.id + '.startopen').removeClass('startopen').addClass('open').find('slidetoggle').fadeIn();
  167. }
  168. // generic error message
  169. function wpQueueError(message) {
  170. jQuery('#media-upload-error').show().html( '<div class="error"><p>' + message + '</p></div>' );
  171. }
  172. // file-specific error messages
  173. function wpFileError(fileObj, message) {
  174. itemAjaxError(fileObj.id, message);
  175. }
  176. function itemAjaxError(id, message) {
  177. var item = jQuery('#media-item-' + id), filename = item.find('.filename').text(), last_err = item.data('last-err');
  178. if ( last_err == id ) // prevent firing an error for the same file twice
  179. return;
  180. item.html('<div class="error-div">' +
  181. '<a class="dismiss" href="#">' + pluploadL10n.dismiss + '</a>' +
  182. '<strong>' + pluploadL10n.error_uploading.replace('%s', jQuery.trim(filename)) + '</strong> ' +
  183. message +
  184. '</div>').data('last-err', id);
  185. }
  186. function deleteSuccess(data) {
  187. var type, id, item;
  188. if ( data == '-1' )
  189. return itemAjaxError(this.id, 'You do not have permission. Has your session expired?');
  190. if ( data == '0' )
  191. return itemAjaxError(this.id, 'Could not be deleted. Has it been deleted already?');
  192. id = this.id;
  193. item = jQuery('#media-item-' + id);
  194. // Decrement the counters.
  195. if ( type = jQuery('#type-of-' + id).val() )
  196. jQuery('#' + type + '-counter').text( jQuery('#' + type + '-counter').text() - 1 );
  197. if ( post_id && item.hasClass('child-of-'+post_id) )
  198. jQuery('#attachments-count').text( jQuery('#attachments-count').text() - 1 );
  199. if ( jQuery('form.type-form #media-items').children().length == 1 && jQuery('.hidden', '#media-items').length > 0 ) {
  200. jQuery('.toggle').toggle();
  201. jQuery('.slidetoggle').slideUp(200).siblings().removeClass('hidden');
  202. }
  203. // Vanish it.
  204. jQuery('.toggle', item).toggle();
  205. jQuery('.slidetoggle', item).slideUp(200).siblings().removeClass('hidden');
  206. item.css( {backgroundColor:'#faa'} ).animate( {backgroundColor:'#f4f4f4'}, {queue:false, duration:500} ).addClass('undo');
  207. jQuery('.filename:empty', item).remove();
  208. jQuery('.filename .title', item).css('font-weight','bold');
  209. jQuery('.filename', item).append('<span class="trashnotice"> ' + pluploadL10n.deleted + ' </span>').siblings('a.toggle').hide();
  210. jQuery('.filename', item).append( jQuery('a.undo', item).removeClass('hidden') );
  211. jQuery('.menu_order_input', item).hide();
  212. return;
  213. }
  214. function deleteError() {
  215. // TODO
  216. }
  217. function uploadComplete() {
  218. jQuery('#insert-gallery').prop('disabled', false);
  219. }
  220. function switchUploader(s) {
  221. if ( s ) {
  222. deleteUserSetting('uploader');
  223. jQuery('.media-upload-form').removeClass('html-uploader');
  224. if ( typeof(uploader) == 'object' )
  225. uploader.refresh();
  226. } else {
  227. setUserSetting('uploader', '1'); // 1 == html uploader
  228. jQuery('.media-upload-form').addClass('html-uploader');
  229. }
  230. }
  231. function uploadError(fileObj, errorCode, message, uploader) {
  232. var hundredmb = 100 * 1024 * 1024, max;
  233. switch (errorCode) {
  234. case plupload.FAILED:
  235. wpFileError(fileObj, pluploadL10n.upload_failed);
  236. break;
  237. case plupload.FILE_EXTENSION_ERROR:
  238. wpFileExtensionError( uploader, fileObj, pluploadL10n.invalid_filetype );
  239. break;
  240. case plupload.FILE_SIZE_ERROR:
  241. uploadSizeError(uploader, fileObj);
  242. break;
  243. case plupload.IMAGE_FORMAT_ERROR:
  244. wpFileError(fileObj, pluploadL10n.not_an_image);
  245. break;
  246. case plupload.IMAGE_MEMORY_ERROR:
  247. wpFileError(fileObj, pluploadL10n.image_memory_exceeded);
  248. break;
  249. case plupload.IMAGE_DIMENSIONS_ERROR:
  250. wpFileError(fileObj, pluploadL10n.image_dimensions_exceeded);
  251. break;
  252. case plupload.GENERIC_ERROR:
  253. wpQueueError(pluploadL10n.upload_failed);
  254. break;
  255. case plupload.IO_ERROR:
  256. max = parseInt( uploader.settings.filters.max_file_size, 10 );
  257. if ( max > hundredmb && fileObj.size > hundredmb )
  258. wpFileError( fileObj, pluploadL10n.big_upload_failed.replace('%1$s', '<a class="uploader-html" href="#">').replace('%2$s', '</a>') );
  259. else
  260. wpQueueError(pluploadL10n.io_error);
  261. break;
  262. case plupload.HTTP_ERROR:
  263. wpQueueError(pluploadL10n.http_error);
  264. break;
  265. case plupload.INIT_ERROR:
  266. jQuery('.media-upload-form').addClass('html-uploader');
  267. break;
  268. case plupload.SECURITY_ERROR:
  269. wpQueueError(pluploadL10n.security_error);
  270. break;
  271. /* case plupload.UPLOAD_ERROR.UPLOAD_STOPPED:
  272. case plupload.UPLOAD_ERROR.FILE_CANCELLED:
  273. jQuery('#media-item-' + fileObj.id).remove();
  274. break;*/
  275. default:
  276. wpFileError(fileObj, pluploadL10n.default_error);
  277. }
  278. }
  279. function uploadSizeError( up, file, over100mb ) {
  280. var message;
  281. if ( over100mb )
  282. message = pluploadL10n.big_upload_queued.replace('%s', file.name) + ' ' + pluploadL10n.big_upload_failed.replace('%1$s', '<a class="uploader-html" href="#">').replace('%2$s', '</a>');
  283. else
  284. message = pluploadL10n.file_exceeds_size_limit.replace('%s', file.name);
  285. jQuery('#media-items').append('<div id="media-item-' + file.id + '" class="media-item error"><p>' + message + '</p></div>');
  286. up.removeFile(file);
  287. }
  288. function wpFileExtensionError( up, file, message ) {
  289. jQuery('#media-items').append('<div id="media-item-' + file.id + '" class="media-item error"><p>' + message + '</p></div>');
  290. up.removeFile(file);
  291. }
  292. jQuery(document).ready(function($){
  293. $('.media-upload-form').bind('click.uploader', function(e) {
  294. var target = $(e.target), tr, c;
  295. if ( target.is('input[type="radio"]') ) { // remember the last used image size and alignment
  296. tr = target.closest('tr');
  297. if ( tr.hasClass('align') )
  298. setUserSetting('align', target.val());
  299. else if ( tr.hasClass('image-size') )
  300. setUserSetting('imgsize', target.val());
  301. } else if ( target.is('button.button') ) { // remember the last used image link url
  302. c = e.target.className || '';
  303. c = c.match(/url([^ '"]+)/);
  304. if ( c && c[1] ) {
  305. setUserSetting('urlbutton', c[1]);
  306. target.siblings('.urlfield').val( target.data('link-url') );
  307. }
  308. } else if ( target.is('a.dismiss') ) {
  309. target.parents('.media-item').fadeOut(200, function(){
  310. $(this).remove();
  311. });
  312. } else if ( target.is('.upload-flash-bypass a') || target.is('a.uploader-html') ) { // switch uploader to html4
  313. $('#media-items, p.submit, span.big-file-warning').css('display', 'none');
  314. switchUploader(0);
  315. e.preventDefault();
  316. } else if ( target.is('.upload-html-bypass a') ) { // switch uploader to multi-file
  317. $('#media-items, p.submit, span.big-file-warning').css('display', '');
  318. switchUploader(1);
  319. e.preventDefault();
  320. } else if ( target.is('a.describe-toggle-on') ) { // Show
  321. target.parent().addClass('open');
  322. target.siblings('.slidetoggle').fadeIn(250, function(){
  323. var S = $(window).scrollTop(), H = $(window).height(), top = $(this).offset().top, h = $(this).height(), b, B;
  324. if ( H && top && h ) {
  325. b = top + h;
  326. B = S + H;
  327. if ( b > B ) {
  328. if ( b - B < top - S )
  329. window.scrollBy(0, (b - B) + 10);
  330. else
  331. window.scrollBy(0, top - S - 40);
  332. }
  333. }
  334. });
  335. e.preventDefault();
  336. } else if ( target.is('a.describe-toggle-off') ) { // Hide
  337. target.siblings('.slidetoggle').fadeOut(250, function(){
  338. target.parent().removeClass('open');
  339. });
  340. e.preventDefault();
  341. }
  342. });
  343. // init and set the uploader
  344. uploader_init = function() {
  345. var isIE = navigator.userAgent.indexOf('Trident/') != -1 || navigator.userAgent.indexOf('MSIE ') != -1;
  346. // Make sure flash sends cookies (seems in IE it does whitout switching to urlstream mode)
  347. if ( ! isIE && 'flash' === plupload.predictRuntime( wpUploaderInit ) &&
  348. ( ! wpUploaderInit.required_features || ! wpUploaderInit.required_features.hasOwnProperty( 'send_binary_string' ) ) ) {
  349. wpUploaderInit.required_features = wpUploaderInit.required_features || {};
  350. wpUploaderInit.required_features.send_binary_string = true;
  351. }
  352. uploader = new plupload.Uploader(wpUploaderInit);
  353. $('#image_resize').bind('change', function() {
  354. var arg = $(this).prop('checked');
  355. setResize( arg );
  356. if ( arg )
  357. setUserSetting('upload_resize', '1');
  358. else
  359. deleteUserSetting('upload_resize');
  360. });
  361. uploader.bind('Init', function(up) {
  362. var uploaddiv = $('#plupload-upload-ui');
  363. setResize( getUserSetting('upload_resize', false) );
  364. if ( up.features.dragdrop && ! $(document.body).hasClass('mobile') ) {
  365. uploaddiv.addClass('drag-drop');
  366. $('#drag-drop-area').on('dragover.wp-uploader', function(){ // dragenter doesn't fire right :(
  367. uploaddiv.addClass('drag-over');
  368. }).on('dragleave.wp-uploader, drop.wp-uploader', function(){
  369. uploaddiv.removeClass('drag-over');
  370. });
  371. } else {
  372. uploaddiv.removeClass('drag-drop');
  373. $('#drag-drop-area').off('.wp-uploader');
  374. }
  375. if ( up.runtime === 'html4' ) {
  376. $('.upload-flash-bypass').hide();
  377. }
  378. });
  379. uploader.bind( 'postinit', function( up ) {
  380. up.refresh();
  381. });
  382. uploader.init();
  383. uploader.bind('FilesAdded', function( up, files ) {
  384. $('#media-upload-error').empty();
  385. uploadStart();
  386. plupload.each( files, function( file ) {
  387. fileQueued( file );
  388. });
  389. up.refresh();
  390. up.start();
  391. });
  392. uploader.bind('UploadFile', function(up, file) {
  393. fileUploading(up, file);
  394. });
  395. uploader.bind('UploadProgress', function(up, file) {
  396. uploadProgress(up, file);
  397. });
  398. uploader.bind('Error', function(up, err) {
  399. uploadError(err.file, err.code, err.message, up);
  400. up.refresh();
  401. });
  402. uploader.bind('FileUploaded', function(up, file, response) {
  403. uploadSuccess(file, response.response);
  404. });
  405. uploader.bind('UploadComplete', function() {
  406. uploadComplete();
  407. });
  408. };
  409. if ( typeof(wpUploaderInit) == 'object' ) {
  410. uploader_init();
  411. }
  412. });