admin.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. /* GENERATE RETINA IMAGES ACTION */
  2. var current;
  3. var maxPhpSize = wr2x_admin_server.maxFileSize;
  4. var ids = [];
  5. var errors = 0;
  6. var ajax_action = "generate"; // generate | delete
  7. function wr2x_display_please_refresh() {
  8. wr2x_refresh_progress_status();
  9. jQuery('#wr2x_progression').html(jQuery('#wr2x_progression').html() + " - " + wr2x_admin_server.i18n.Refresh);
  10. }
  11. function wr2x_refresh_progress_status() {
  12. var errortext = "";
  13. if ( errors > 0 ) {
  14. errortext = ' - ' + errors + ' error(s)';
  15. }
  16. jQuery('#wr2x_progression').text(current + "/" + ids.length +
  17. " (" + Math.round(current / ids.length * 100) + "%)" + errortext);
  18. }
  19. function wr2x_do_next () {
  20. var data = { action: 'wr2x_' + ajax_action, attachmentId: ids[current - 1] };
  21. data.nonce = wr2x_admin_server.nonce[data.action];
  22. wr2x_refresh_progress_status();
  23. jQuery.post(ajaxurl, data, function (response) {
  24. try {
  25. reply = jQuery.parseJSON(response);
  26. }
  27. catch (e) {
  28. reply = null;
  29. }
  30. if ( !reply || !reply.success )
  31. errors++;
  32. else {
  33. wr2x_refresh_media_sizes(reply.results);
  34. if (reply.results_full)
  35. wr2x_refresh_full(reply.results_full);
  36. }
  37. if (++current <= ids.length)
  38. wr2x_do_next();
  39. else {
  40. current--;
  41. wr2x_display_please_refresh();
  42. }
  43. }).fail(function () {
  44. errors++;
  45. if (++current <= ids.length)
  46. wr2x_do_next();
  47. else {
  48. current--;
  49. wr2x_display_please_refresh();
  50. }
  51. });
  52. }
  53. function wr2x_do_all () {
  54. current = 1;
  55. ids = [];
  56. errors = 0;
  57. var data = { action: 'wr2x_list_all', issuesOnly: 0 };
  58. data.nonce = wr2x_admin_server.nonce[data.action];
  59. jQuery('#wr2x_progression').text(wr2x_admin_server.i18n.Wait);
  60. jQuery.post(ajaxurl, data, function (response) {
  61. reply = jQuery.parseJSON(response);
  62. if (reply.success = false) {
  63. alert('Error: ' + reply.message);
  64. return;
  65. }
  66. if (reply.total == 0) {
  67. jQuery('#wr2x_progression').html(wr2x_admin_server.i18n.Nothing_to_do);
  68. return;
  69. }
  70. ids = reply.ids;
  71. jQuery('#wr2x_progression').text(current + "/" + ids.length + " (" + Math.round(current / ids.length * 100) + "%)");
  72. wr2x_do_next();
  73. });
  74. }
  75. function wr2x_delete_all () {
  76. ajax_action = 'delete';
  77. wr2x_do_all();
  78. }
  79. function wr2x_generate_all () {
  80. ajax_action = 'generate';
  81. wr2x_do_all();
  82. }
  83. // Refresh the dashboard retina full with the results from the Ajax operation (Upload)
  84. function wr2x_refresh_full (results) {
  85. jQuery.each(results, function (id, html) {
  86. jQuery('#wr2x-info-full-' + id).html(html);
  87. jQuery('#wr2x-info-full-' + id + ' img').attr('src', jQuery('#wr2x-info-full-' + id + ' img').attr('src')+'?'+ Math.random());
  88. jQuery('#wr2x-info-full-' + id + ' img').on('click', function (evt) {
  89. wr2x_delete_full( jQuery(evt.target).parents('.wr2x-file-row').attr('postid') );
  90. });
  91. });
  92. }
  93. // Refresh the dashboard media sizes with the results from the Ajax operation (Replace or Generate)
  94. function wr2x_refresh_media_sizes (results) {
  95. jQuery.each(results, function (id, html) {
  96. jQuery('#wr2x-info-' + id).html(html);
  97. });
  98. }
  99. function wr2x_generate (attachmentId, retinaDashboard) {
  100. var data = { action: 'wr2x_generate', attachmentId: attachmentId };
  101. data.nonce = wr2x_admin_server.nonce[data.action];
  102. jQuery('#wr2x_generate_button_' + attachmentId).text(wr2x_admin_server.i18n.Wait);
  103. jQuery.post(ajaxurl, data, function (response) {
  104. var reply = jQuery.parseJSON(response);
  105. if (!reply.success) {
  106. alert(reply.message);
  107. return;
  108. }
  109. jQuery('#wr2x_generate_button_' + attachmentId).html(wr2x_admin_server.i18n.Generate);
  110. wr2x_refresh_media_sizes(reply.results);
  111. });
  112. }
  113. /* REPLACE FUNCTION */
  114. function wr2x_stop_propagation(evt) {
  115. evt.stopPropagation();
  116. evt.preventDefault();
  117. }
  118. function wr2x_delete_full(attachmentId) {
  119. var data = {
  120. action: 'wr2x_delete_full',
  121. isAjax: true,
  122. attachmentId: attachmentId
  123. };
  124. data.nonce = wr2x_admin_server.nonce[data.action];
  125. jQuery.post(ajaxurl, data, function (response) {
  126. var data = jQuery.parseJSON(response);
  127. if (data.success === false) {
  128. alert(data.message);
  129. }
  130. else {
  131. wr2x_refresh_full(data.results);
  132. wr2x_display_please_refresh();
  133. }
  134. });
  135. }
  136. function wr2x_load_details(attachmentId) {
  137. var data = {
  138. action: 'wr2x_retina_details',
  139. isAjax: true,
  140. attachmentId: attachmentId
  141. };
  142. data.nonce = wr2x_admin_server.nonce[data.action];
  143. jQuery.post(ajaxurl, data, function (response) {
  144. var data = jQuery.parseJSON(response);
  145. if (data.success === false) {
  146. alert(data.message);
  147. }
  148. else {
  149. jQuery('#meow-modal-info .loading').css('display', 'none');
  150. jQuery('#meow-modal-info .content').html(data.result);
  151. }
  152. });
  153. }
  154. function wr2x_filedropped (evt) {
  155. wr2x_stop_propagation(evt);
  156. var files = evt.dataTransfer.files;
  157. var count = files.length;
  158. if (count < 0) {
  159. return;
  160. }
  161. var wr2x_replace = jQuery(evt.target).parent().hasClass('wr2x-fullsize-replace');
  162. var wr2x_upload = jQuery(evt.target).parent().hasClass('wr2x-fullsize-retina-upload');
  163. function wr2x_handleprogress(prg) {
  164. console.debug("Upload of " + prg.srcElement.filename + ": " + prg.loaded / prg.total * 100 + "%");
  165. }
  166. function wr2x_uploadFile(file, attachmentId, filename) {
  167. var action = "";
  168. if (wr2x_replace) {
  169. action = 'wr2x_replace';
  170. }
  171. else if (wr2x_upload) {
  172. action = 'wr2x_upload';
  173. }
  174. else {
  175. alert("Unknown command. Contact the developer.");
  176. }
  177. var data = new FormData();
  178. data.append('file', file);
  179. data.append('action', action);
  180. data.append('attachmentId', attachmentId);
  181. data.append('isAjax', true);
  182. data.append('filename', filename);
  183. data.append('nonce', wr2x_admin_server.nonce[action]);
  184. // var data = {
  185. // action: action,
  186. // isAjax: true,
  187. // filename: evt.target.filename,
  188. // data: form_data,
  189. // attachmentId: attachmentId
  190. // };
  191. jQuery.ajax({
  192. type: 'POST',
  193. url: ajaxurl,
  194. contentType: false,
  195. processData: false,
  196. data: data,
  197. success: function (response) {
  198. jQuery('[postid=' + attachmentId + '] td').removeClass('wr2x-loading-file');
  199. jQuery('[postid=' + attachmentId + '] .wr2x-dragdrop').removeClass('wr2x-hover-drop');
  200. try {
  201. var data = jQuery.parseJSON(response);
  202. }
  203. catch (e) {
  204. alert("The server-side returned an abnormal response. Check your PHP error logs and also your browser console (WP Retina 2x will try to display it there).");
  205. console.debug(response);
  206. return;
  207. }
  208. if (wr2x_replace) {
  209. var imgSelector = '[postid=' + attachmentId + '] .wr2x-info-thumbnail img';
  210. jQuery(imgSelector).attr('src', jQuery(imgSelector).attr('src')+'?'+ Math.random());
  211. }
  212. if (wr2x_upload) {
  213. var imgSelector = '[postid=' + attachmentId + '] .wr2x-info-full img';
  214. jQuery(imgSelector).attr('src', jQuery(imgSelector).attr('src')+'?'+ Math.random());
  215. }
  216. if (data.success === false) {
  217. alert(data.message);
  218. }
  219. else {
  220. if ( wr2x_replace ) {
  221. wr2x_refresh_media_sizes(data.results);
  222. }
  223. else if ( wr2x_upload ) {
  224. wr2x_refresh_full(data.results);
  225. }
  226. }
  227. },
  228. error: function(XMLHttpRequest, textStatus, errorThrown) {
  229. jQuery('[postid=' + attachmentId + '] td').removeClass('wr2x-loading-file');
  230. jQuery('[postid=' + attachmentId + '] .wr2x-dragdrop').removeClass('wr2x-hover-drop');
  231. alert("An error occurred on the server-side. Please check your PHP error logs.");
  232. }
  233. });
  234. }
  235. var file = files[0];
  236. if (file.size > maxPhpSize) {
  237. jQuery(this).removeClass('wr2x-hover-drop');
  238. alert( "Your PHP configuration only allows file upload of a maximum of " + (maxPhpSize / 1000000) + "MB." );
  239. return;
  240. }
  241. var postId = jQuery(evt.target).parents('.wr2x-file-row').attr('postid');
  242. jQuery(evt.target).parents('td').addClass('wr2x-loading-file');
  243. wr2x_uploadFile(file, postId, file.name);
  244. }
  245. jQuery(document).ready(function () {
  246. jQuery('.wr2x-dragdrop').on('dragenter', function (evt) {
  247. wr2x_stop_propagation(evt);
  248. jQuery(this).addClass('wr2x-hover-drop');
  249. });
  250. jQuery('.wr2x-dragdrop').on('dragover', function (evt) {
  251. wr2x_stop_propagation(evt);
  252. jQuery(this).addClass('wr2x-hover-drop');
  253. });
  254. jQuery('.wr2x-dragdrop').on('dragleave', function (evt) {
  255. wr2x_stop_propagation(evt);
  256. jQuery(this).removeClass('wr2x-hover-drop');
  257. });
  258. jQuery('.wr2x-dragdrop').on('dragexit', wr2x_stop_propagation);
  259. jQuery('.wr2x-dragdrop').each(function (index, elem) {
  260. this.addEventListener('drop', wr2x_filedropped);
  261. });
  262. jQuery('.wr2x-info, .wr2x-button-view').on('click', function (evt) {
  263. jQuery('#meow-modal-info-backdrop').css('display', 'block');
  264. jQuery('#meow-modal-info .content').html("");
  265. jQuery('#meow-modal-info .loading').css('display', 'block');
  266. jQuery('#meow-modal-info').css('display', 'block');
  267. jQuery('#meow-modal-info').focus();
  268. var postid = jQuery(evt.target).parents('.wr2x-info').attr('postid');
  269. if (!postid)
  270. postid = jQuery(evt.target).parents('.wr2x-file-row').attr('postid');
  271. wr2x_load_details(postid);
  272. });
  273. jQuery('#meow-modal-info .close, #meow-modal-info-backdrop').on('click', function (evt) {
  274. jQuery('#meow-modal-info').css('display', 'none');
  275. jQuery('#meow-modal-info-backdrop').css('display', 'none');
  276. });
  277. jQuery('.wr2x-info-full img').on('click', function (evt) {
  278. wr2x_delete_full( jQuery(evt.target).parents('.wr2x-file-row').attr('postid') );
  279. });
  280. jQuery('#meow-modal-info').bind('keydown', function (evt) {
  281. if (evt.keyCode === 27) {
  282. jQuery('#meow-modal-info').css('display', 'none');
  283. jQuery('#meow-modal-info-backdrop').css('display', 'none');
  284. }
  285. });
  286. /**
  287. * Retina Uploader
  288. */
  289. (function ($) {
  290. /**
  291. * @constructor
  292. */
  293. function Upload(File) {
  294. if (!this.validate(File)) return; // Invalid file
  295. this.file = File;
  296. this.loaded = 0;
  297. this.total = 0;
  298. this.doms = {
  299. wrap: null,
  300. filename: null,
  301. progress: null,
  302. percent: null,
  303. bar: null
  304. };
  305. this.request();
  306. }
  307. Upload.prototype.getProgress = function (Mul = 1) {
  308. if (!this.total) return 0;
  309. var r = (this.loaded / this.total) * Mul;
  310. return Math.round(r * 10) / 10;
  311. }
  312. Upload.prototype.validate = function (File) {
  313. var err;
  314. if (!'type' in File || !File.type)
  315. err = 'Unknown File Type';
  316. else if (!File.type.match(/^image\//)) // Not image
  317. err = 'Unsupported File Type';
  318. if (err) {
  319. console.error(err);
  320. alert(err);
  321. return false;
  322. }
  323. return true;
  324. }
  325. Upload.prototype.request = function () {
  326. var self = this;
  327. var action = 'wr2x_retina_upload';
  328. var data = new FormData();
  329. data.append('action', action);
  330. data.append('isAjax', true);
  331. data.append('nonce', wr2x_admin_server.nonce[action]);
  332. data.append('file', this.file);
  333. data.append('filename', this.file.name);
  334. this.show();
  335. $.ajax({
  336. type: 'POST',
  337. url: ajaxurl,
  338. contentType: false,
  339. processData: false,
  340. data: data,
  341. // Custom XHR
  342. xhr: function () {
  343. var xhr = new XMLHttpRequest();
  344. // Watch upload progress
  345. xhr.upload.addEventListener('progress', function (ev) {
  346. if (!ev.lengthComputable) return xhr;
  347. self.loaded = ev.loaded;
  348. self.total = ev.total;
  349. self.update();
  350. }, false);
  351. return xhr;
  352. }
  353. }).done(function (response) {
  354. try {
  355. response = $.parseJSON(response);
  356. } catch (e) { // Malformed Response
  357. self.abort();
  358. console.error(e);
  359. alert('Invalid Response');
  360. return;
  361. }
  362. if (!response.success) { // App Error
  363. self.abort();
  364. var msg = 'message' in response ?
  365. response.message : 'Error';
  366. console.error(msg);
  367. alert(msg);
  368. return;
  369. }
  370. // Remove the progress indicator
  371. self.doms.progress.remove();
  372. // Edit Link
  373. $('<a class="edit-attachment">')
  374. .attr('href', response.media.edit_url)
  375. .attr('target', '_blank')
  376. .text('Edit')
  377. .prependTo(self.doms.wrap);
  378. // Show the thumbnail
  379. $('<img class="pinkynail">')
  380. .attr('src', response.media.src[0])
  381. .prependTo(self.doms.wrap);
  382. // Just mocking the built-in behavior
  383. self.doms.filename
  384. .removeClass('original')
  385. .addClass('new');
  386. }).fail(function (e) { // HTTP Error
  387. self.abort();
  388. var msg = e.status + ' ' + e.statusText;
  389. console.error(msg);
  390. alert(msg + '\n' + 'An error occurred on the server-side. Please check your PHP error logs.');
  391. });
  392. }
  393. Upload.prototype.show = function () {
  394. // Ideal HTML:
  395. // <div class="media-item child-of-0" id="media-item">
  396. // <div class="progress">
  397. // <div class="percent">100%</div>
  398. // <div class="bar" style="width: 200px;"></div>
  399. // </div>
  400. // <div class="filename original">image.jpg</div>
  401. // </div>
  402. this.doms.wrap = $('<div class="media-item wr2x-retina-uploaded">');
  403. this.doms.filename = $('<div class="filename original">')
  404. .text(this.file.name)
  405. .appendTo(this.doms.wrap);
  406. this.doms.wrap.appendTo('#media-items'); // First Appearance
  407. }
  408. Upload.prototype.update = function () {
  409. if (!this.doms.progress) { // Initialize the progress bar
  410. this.doms.progress = $('<div class="progress">').prependTo(this.doms.wrap);
  411. this.doms.percent = $('<div class="percent">').appendTo(this.doms.progress);
  412. this.doms.bar = $('<div class="bar">').appendTo(this.doms.progress);
  413. }
  414. this.doms.percent.text(this.getProgress(100) + '%');
  415. this.doms.bar.css('width', this.getProgress(200) + 'px');
  416. }
  417. Upload.prototype.abort = function () {
  418. this.doms.wrap.remove();
  419. }
  420. /** Initialize DOMs **/
  421. // Drag & Drop Area
  422. var dnd = $('#wr2x_drag-drop-area')
  423. dnd.on('dragenter dragover', function (ev) {
  424. wr2x_stop_propagation(ev);
  425. $(this).addClass('wr2x-hover-drop');
  426. }).on('dragleave dragexit', function (ev) {
  427. wr2x_stop_propagation(ev);
  428. $(this).removeClass('wr2x-hover-drop');
  429. }).on('drop', function (ev) {
  430. wr2x_stop_propagation(ev);
  431. $(this).removeClass('wr2x-hover-drop');
  432. var _ev = ev.originalEvent;
  433. var files = _ev.dataTransfer.files;
  434. for (var i = 0; i < files.length; i++) new Upload(files[i]);
  435. });
  436. // File Selector
  437. var selector = $('#wr2x_file-selector');
  438. selector.on('change', function (ev) {
  439. var files = ev.target.files;
  440. for (var i = 0; i < files.length; i++) new Upload(files[i]);
  441. });
  442. var btn = $('#wr2x_file-select-button');
  443. btn.on('click', function (ev) {
  444. selector.trigger('click');
  445. });
  446. })(jQuery);
  447. });