]> scripts.mit.edu Git - autoinstalls/wordpress.git/blob - wp-admin/js/image-edit.js
WordPress 3.8
[autoinstalls/wordpress.git] / wp-admin / js / image-edit.js
1 /* global imageEditL10n, ajaxurl, confirm */
2
3 (function($) {
4 var imageEdit = window.imageEdit = {
5         iasapi : {},
6         hold : {},
7         postid : '',
8
9         intval : function(f) {
10                 return f | 0;
11         },
12
13         setDisabled : function(el, s) {
14                 if ( s ) {
15                         el.removeClass('disabled');
16                         $('input', el).removeAttr('disabled');
17                 } else {
18                         el.addClass('disabled');
19                         $('input', el).prop('disabled', true);
20                 }
21         },
22
23         init : function(postid) {
24                 var t = this, old = $('#image-editor-' + t.postid),
25                         x = t.intval( $('#imgedit-x-' + postid).val() ),
26                         y = t.intval( $('#imgedit-y-' + postid).val() );
27
28                 if ( t.postid !== postid && old.length ) {
29                         t.close(t.postid);
30                 }
31
32                 t.hold.w = t.hold.ow = x;
33                 t.hold.h = t.hold.oh = y;
34                 t.hold.xy_ratio = x / y;
35                 t.hold.sizer = parseFloat( $('#imgedit-sizer-' + postid).val() );
36                 t.postid = postid;
37                 $('#imgedit-response-' + postid).empty();
38
39                 $('input[type="text"]', '#imgedit-panel-' + postid).keypress(function(e) {
40                         var k = e.keyCode;
41
42                         if ( 36 < k && k < 41 ) {
43                                 $(this).blur();
44                         }
45
46                         if ( 13 === k ) {
47                                 e.preventDefault();
48                                 e.stopPropagation();
49                                 return false;
50                         }
51                 });
52         },
53
54         toggleEditor : function(postid, toggle) {
55                 var wait = $('#imgedit-wait-' + postid);
56
57                 if ( toggle ) {
58                         wait.height( $('#imgedit-panel-' + postid).height() ).fadeIn('fast');
59                 } else {
60                         wait.fadeOut('fast');
61                 }
62         },
63
64         toggleHelp : function(el) {
65                 $(el).siblings('.imgedit-help').slideToggle('fast');
66                 return false;
67         },
68
69         getTarget : function(postid) {
70                 return $('input[name="imgedit-target-' + postid + '"]:checked', '#imgedit-save-target-' + postid).val() || 'full';
71         },
72
73         scaleChanged : function(postid, x) {
74                 var w = $('#imgedit-scale-width-' + postid), h = $('#imgedit-scale-height-' + postid),
75                 warn = $('#imgedit-scale-warn-' + postid), w1 = '', h1 = '';
76
77                 if ( x ) {
78                         h1 = ( w.val() !== '' ) ? Math.round( w.val() / this.hold.xy_ratio ) : '';
79                         h.val( h1 );
80                 } else {
81                         w1 = ( h.val() !== '' ) ? Math.round( h.val() * this.hold.xy_ratio ) : '';
82                         w.val( w1 );
83                 }
84
85                 if ( ( h1 && h1 > this.hold.oh ) || ( w1 && w1 > this.hold.ow ) ) {
86                         warn.css('visibility', 'visible');
87                 } else {
88                         warn.css('visibility', 'hidden');
89                 }
90         },
91
92         getSelRatio : function(postid) {
93                 var x = this.hold.w, y = this.hold.h,
94                         X = this.intval( $('#imgedit-crop-width-' + postid).val() ),
95                         Y = this.intval( $('#imgedit-crop-height-' + postid).val() );
96
97                 if ( X && Y ) {
98                         return X + ':' + Y;
99                 }
100
101                 if ( x && y ) {
102                         return x + ':' + y;
103                 }
104
105                 return '1:1';
106         },
107
108         filterHistory : function(postid, setSize) {
109                 // apply undo state to history
110                 var history = $('#imgedit-history-' + postid).val(), pop, n, o, i, op = [];
111
112                 if ( history !== '' ) {
113                         history = JSON.parse(history);
114                         pop = this.intval( $('#imgedit-undone-' + postid).val() );
115                         if ( pop > 0 ) {
116                                 while ( pop > 0 ) {
117                                         history.pop();
118                                         pop--;
119                                 }
120                         }
121
122                         if ( setSize ) {
123                                 if ( !history.length ) {
124                                         this.hold.w = this.hold.ow;
125                                         this.hold.h = this.hold.oh;
126                                         return '';
127                                 }
128
129                                 // restore
130                                 o = history[history.length - 1];
131                                 o = o.c || o.r || o.f || false;
132
133                                 if ( o ) {
134                                         this.hold.w = o.fw;
135                                         this.hold.h = o.fh;
136                                 }
137                         }
138
139                         // filter the values
140                         for ( n in history ) {
141                                 i = history[n];
142                                 if ( i.hasOwnProperty('c') ) {
143                                         op[n] = { 'c': { 'x': i.c.x, 'y': i.c.y, 'w': i.c.w, 'h': i.c.h } };
144                                 } else if ( i.hasOwnProperty('r') ) {
145                                         op[n] = { 'r': i.r.r };
146                                 } else if ( i.hasOwnProperty('f') ) {
147                                         op[n] = { 'f': i.f.f };
148                                 }
149                         }
150                         return JSON.stringify(op);
151                 }
152                 return '';
153         },
154
155         refreshEditor : function(postid, nonce, callback) {
156                 var t = this, data, img;
157
158                 t.toggleEditor(postid, 1);
159                 data = {
160                         'action': 'imgedit-preview',
161                         '_ajax_nonce': nonce,
162                         'postid': postid,
163                         'history': t.filterHistory(postid, 1),
164                         'rand': t.intval(Math.random() * 1000000)
165                 };
166
167                 img = $('<img id="image-preview-' + postid + '" />')
168                         .on('load', function() {
169                                 var max1, max2, parent = $('#imgedit-crop-' + postid), t = imageEdit;
170
171                                 parent.empty().append(img);
172
173                                 // w, h are the new full size dims
174                                 max1 = Math.max( t.hold.w, t.hold.h );
175                                 max2 = Math.max( $(img).width(), $(img).height() );
176                                 t.hold.sizer = max1 > max2 ? max2 / max1 : 1;
177
178                                 t.initCrop(postid, img, parent);
179                                 t.setCropSelection(postid, 0);
180
181                                 if ( (typeof callback !== 'undefined') && callback !== null ) {
182                                         callback();
183                                 }
184
185                                 if ( $('#imgedit-history-' + postid).val() && $('#imgedit-undone-' + postid).val() === '0' ) {
186                                         $('input.imgedit-submit-btn', '#imgedit-panel-' + postid).removeAttr('disabled');
187                                 } else {
188                                         $('input.imgedit-submit-btn', '#imgedit-panel-' + postid).prop('disabled', true);
189                                 }
190
191                                 t.toggleEditor(postid, 0);
192                         })
193                         .on('error', function() {
194                                 $('#imgedit-crop-' + postid).empty().append('<div class="error"><p>' + imageEditL10n.error + '</p></div>');
195                                 t.toggleEditor(postid, 0);
196                         })
197                         .attr('src', ajaxurl + '?' + $.param(data));
198         },
199
200         action : function(postid, nonce, action) {
201                 var t = this, data, w, h, fw, fh;
202
203                 if ( t.notsaved(postid) ) {
204                         return false;
205                 }
206
207                 data = {
208                         'action': 'image-editor',
209                         '_ajax_nonce': nonce,
210                         'postid': postid
211                 };
212
213                 if ( 'scale' === action ) {
214                         w = $('#imgedit-scale-width-' + postid),
215                         h = $('#imgedit-scale-height-' + postid),
216                         fw = t.intval(w.val()),
217                         fh = t.intval(h.val());
218
219                         if ( fw < 1 ) {
220                                 w.focus();
221                                 return false;
222                         } else if ( fh < 1 ) {
223                                 h.focus();
224                                 return false;
225                         }
226
227                         if ( fw === t.hold.ow || fh === t.hold.oh ) {
228                                 return false;
229                         }
230
231                         data['do'] = 'scale';
232                         data.fwidth = fw;
233                         data.fheight = fh;
234                 } else if ( 'restore' === action ) {
235                         data['do'] = 'restore';
236                 } else {
237                         return false;
238                 }
239
240                 t.toggleEditor(postid, 1);
241                 $.post(ajaxurl, data, function(r) {
242                         $('#image-editor-' + postid).empty().append(r);
243                         t.toggleEditor(postid, 0);
244                 });
245         },
246
247         save : function(postid, nonce) {
248                 var data, target = this.getTarget(postid), history = this.filterHistory(postid, 0);
249
250                 if ( '' === history ) {
251                         return false;
252                 }
253
254                 this.toggleEditor(postid, 1);
255                 data = {
256                         'action': 'image-editor',
257                         '_ajax_nonce': nonce,
258                         'postid': postid,
259                         'history': history,
260                         'target': target,
261                         'context': $('#image-edit-context').length ? $('#image-edit-context').val() : null,
262                         'do': 'save'
263                 };
264
265                 $.post(ajaxurl, data, function(r) {
266                         var ret = JSON.parse(r);
267
268                         if ( ret.error ) {
269                                 $('#imgedit-response-' + postid).html('<div class="error"><p>' + ret.error + '</p><div>');
270                                 imageEdit.close(postid);
271                                 return;
272                         }
273
274                         if ( ret.fw && ret.fh ) {
275                                 $('#media-dims-' + postid).html( ret.fw + ' &times; ' + ret.fh );
276                         }
277
278                         if ( ret.thumbnail ) {
279                                 $('.thumbnail', '#thumbnail-head-' + postid).attr('src', ''+ret.thumbnail);
280                         }
281
282                         if ( ret.msg ) {
283                                 $('#imgedit-response-' + postid).html('<div class="updated"><p>' + ret.msg + '</p></div>');
284                         }
285
286                         imageEdit.close(postid);
287                 });
288         },
289
290         open : function(postid, nonce) {
291                 var data, elem = $('#image-editor-' + postid), head = $('#media-head-' + postid),
292                         btn = $('#imgedit-open-btn-' + postid), spin = btn.siblings('.spinner');
293
294                 btn.prop('disabled', true);
295                 spin.show();
296
297                 data = {
298                         'action': 'image-editor',
299                         '_ajax_nonce': nonce,
300                         'postid': postid,
301                         'do': 'open'
302                 };
303
304                 elem.load(ajaxurl, data, function() {
305                         elem.fadeIn('fast');
306                         head.fadeOut('fast', function(){
307                                 btn.removeAttr('disabled');
308                                 spin.hide();
309                         });
310                 });
311         },
312
313         imgLoaded : function(postid) {
314                 var img = $('#image-preview-' + postid), parent = $('#imgedit-crop-' + postid);
315
316                 this.initCrop(postid, img, parent);
317                 this.setCropSelection(postid, 0);
318                 this.toggleEditor(postid, 0);
319         },
320
321         initCrop : function(postid, image, parent) {
322                 var t = this, selW = $('#imgedit-sel-width-' + postid),
323                         selH = $('#imgedit-sel-height-' + postid);
324
325                 t.iasapi = $(image).imgAreaSelect({
326                         parent: parent,
327                         instance: true,
328                         handles: true,
329                         keys: true,
330                         minWidth: 3,
331                         minHeight: 3,
332
333                         onInit: function() {
334                                 parent.children().mousedown(function(e){
335                                         var ratio = false, sel, defRatio;
336
337                                         if ( e.shiftKey ) {
338                                                 sel = t.iasapi.getSelection();
339                                                 defRatio = t.getSelRatio(postid);
340                                                 ratio = ( sel && sel.width && sel.height ) ? sel.width + ':' + sel.height : defRatio;
341                                         }
342
343                                         t.iasapi.setOptions({
344                                                 aspectRatio: ratio
345                                         });
346                                 });
347                         },
348
349                         onSelectStart: function() {
350                                 imageEdit.setDisabled($('#imgedit-crop-sel-' + postid), 1);
351                         },
352
353                         onSelectEnd: function(img, c) {
354                                 imageEdit.setCropSelection(postid, c);
355                         },
356
357                         onSelectChange: function(img, c) {
358                                 var sizer = imageEdit.hold.sizer;
359                                 selW.val( imageEdit.round(c.width / sizer) );
360                                 selH.val( imageEdit.round(c.height / sizer) );
361                         }
362                 });
363         },
364
365         setCropSelection : function(postid, c) {
366                 var sel, min = $('#imgedit-minthumb-' + postid).val() || '128:128',
367                         sizer = this.hold.sizer;
368                         min = min.split(':');
369                         c = c || 0;
370
371                 if ( !c || ( c.width < 3 && c.height < 3 ) ) {
372                         this.setDisabled($('.imgedit-crop', '#imgedit-panel-' + postid), 0);
373                         this.setDisabled($('#imgedit-crop-sel-' + postid), 0);
374                         $('#imgedit-sel-width-' + postid).val('');
375                         $('#imgedit-sel-height-' + postid).val('');
376                         $('#imgedit-selection-' + postid).val('');
377                         return false;
378                 }
379
380                 if ( c.width < (min[0] * sizer) && c.height < (min[1] * sizer) ) {
381                         this.setDisabled($('.imgedit-crop', '#imgedit-panel-' + postid), 0);
382                         $('#imgedit-selection-' + postid).val('');
383                         return false;
384                 }
385
386                 sel = { 'x': c.x1, 'y': c.y1, 'w': c.width, 'h': c.height };
387                 this.setDisabled($('.imgedit-crop', '#imgedit-panel-' + postid), 1);
388                 $('#imgedit-selection-' + postid).val( JSON.stringify(sel) );
389         },
390
391         close : function(postid, warn) {
392                 warn = warn || false;
393
394                 if ( warn && this.notsaved(postid) ) {
395                         return false;
396                 }
397
398                 this.iasapi = {};
399                 this.hold = {};
400                 $('#image-editor-' + postid).fadeOut('fast', function() {
401                         $('#media-head-' + postid).fadeIn('fast');
402                         $(this).empty();
403                 });
404         },
405
406         notsaved : function(postid) {
407                 var h = $('#imgedit-history-' + postid).val(),
408                         history = ( h !== '' ) ? JSON.parse(h) : [],
409                         pop = this.intval( $('#imgedit-undone-' + postid).val() );
410
411                 if ( pop < history.length ) {
412                         if ( confirm( $('#imgedit-leaving-' + postid).html() ) ) {
413                                 return false;
414                         }
415                         return true;
416                 }
417                 return false;
418         },
419
420         addStep : function(op, postid, nonce) {
421                 var t = this, elem = $('#imgedit-history-' + postid),
422                 history = ( elem.val() !== '' ) ? JSON.parse( elem.val() ) : [],
423                 undone = $('#imgedit-undone-' + postid),
424                 pop = t.intval(undone.val());
425
426                 while ( pop > 0 ) {
427                         history.pop();
428                         pop--;
429                 }
430                 undone.val(0); // reset
431
432                 history.push(op);
433                 elem.val( JSON.stringify(history) );
434
435                 t.refreshEditor(postid, nonce, function() {
436                         t.setDisabled($('#image-undo-' + postid), true);
437                         t.setDisabled($('#image-redo-' + postid), false);
438                 });
439         },
440
441         rotate : function(angle, postid, nonce, t) {
442                 if ( $(t).hasClass('disabled') ) {
443                         return false;
444                 }
445
446                 this.addStep({ 'r': { 'r': angle, 'fw': this.hold.h, 'fh': this.hold.w }}, postid, nonce);
447         },
448
449         flip : function (axis, postid, nonce, t) {
450                 if ( $(t).hasClass('disabled') ) {
451                         return false;
452                 }
453
454                 this.addStep({ 'f': { 'f': axis, 'fw': this.hold.w, 'fh': this.hold.h }}, postid, nonce);
455         },
456
457         crop : function (postid, nonce, t) {
458                 var sel = $('#imgedit-selection-' + postid).val(),
459                         w = this.intval( $('#imgedit-sel-width-' + postid).val() ),
460                         h = this.intval( $('#imgedit-sel-height-' + postid).val() );
461
462                 if ( $(t).hasClass('disabled') || sel === '' ) {
463                         return false;
464                 }
465
466                 sel = JSON.parse(sel);
467                 if ( sel.w > 0 && sel.h > 0 && w > 0 && h > 0 ) {
468                         sel.fw = w;
469                         sel.fh = h;
470                         this.addStep({ 'c': sel }, postid, nonce);
471                 }
472         },
473
474         undo : function (postid, nonce) {
475                 var t = this, button = $('#image-undo-' + postid), elem = $('#imgedit-undone-' + postid),
476                         pop = t.intval( elem.val() ) + 1;
477
478                 if ( button.hasClass('disabled') ) {
479                         return;
480                 }
481
482                 elem.val(pop);
483                 t.refreshEditor(postid, nonce, function() {
484                         var elem = $('#imgedit-history-' + postid),
485                         history = ( elem.val() !== '' ) ? JSON.parse( elem.val() ) : [];
486
487                         t.setDisabled($('#image-redo-' + postid), true);
488                         t.setDisabled(button, pop < history.length);
489                 });
490         },
491
492         redo : function(postid, nonce) {
493                 var t = this, button = $('#image-redo-' + postid), elem = $('#imgedit-undone-' + postid),
494                         pop = t.intval( elem.val() ) - 1;
495
496                 if ( button.hasClass('disabled') ) {
497                         return;
498                 }
499
500                 elem.val(pop);
501                 t.refreshEditor(postid, nonce, function() {
502                         t.setDisabled($('#image-undo-' + postid), true);
503                         t.setDisabled(button, pop > 0);
504                 });
505         },
506
507         setNumSelection : function(postid) {
508                 var sel, elX = $('#imgedit-sel-width-' + postid), elY = $('#imgedit-sel-height-' + postid),
509                         x = this.intval( elX.val() ), y = this.intval( elY.val() ),
510                         img = $('#image-preview-' + postid), imgh = img.height(), imgw = img.width(),
511                         sizer = this.hold.sizer, x1, y1, x2, y2, ias = this.iasapi;
512
513                 if ( x < 1 ) {
514                         elX.val('');
515                         return false;
516                 }
517
518                 if ( y < 1 ) {
519                         elY.val('');
520                         return false;
521                 }
522
523                 if ( x && y && ( sel = ias.getSelection() ) ) {
524                         x2 = sel.x1 + Math.round( x * sizer );
525                         y2 = sel.y1 + Math.round( y * sizer );
526                         x1 = sel.x1;
527                         y1 = sel.y1;
528
529                         if ( x2 > imgw ) {
530                                 x1 = 0;
531                                 x2 = imgw;
532                                 elX.val( Math.round( x2 / sizer ) );
533                         }
534
535                         if ( y2 > imgh ) {
536                                 y1 = 0;
537                                 y2 = imgh;
538                                 elY.val( Math.round( y2 / sizer ) );
539                         }
540
541                         ias.setSelection( x1, y1, x2, y2 );
542                         ias.update();
543                         this.setCropSelection(postid, ias.getSelection());
544                 }
545         },
546
547         round : function(num) {
548                 var s;
549                 num = Math.round(num);
550
551                 if ( this.hold.sizer > 0.6 ) {
552                         return num;
553                 }
554
555                 s = num.toString().slice(-1);
556
557                 if ( '1' === s ) {
558                         return num - 1;
559                 } else if ( '9' === s ) {
560                         return num + 1;
561                 }
562
563                 return num;
564         },
565
566         setRatioSelection : function(postid, n, el) {
567                 var sel, r, x = this.intval( $('#imgedit-crop-width-' + postid).val() ),
568                         y = this.intval( $('#imgedit-crop-height-' + postid).val() ),
569                         h = $('#image-preview-' + postid).height();
570
571                 if ( !this.intval( $(el).val() ) ) {
572                         $(el).val('');
573                         return;
574                 }
575
576                 if ( x && y ) {
577                         this.iasapi.setOptions({
578                                 aspectRatio: x + ':' + y
579                         });
580
581                         if ( sel = this.iasapi.getSelection(true) ) {
582                                 r = Math.ceil( sel.y1 + ( ( sel.x2 - sel.x1 ) / ( x / y ) ) );
583
584                                 if ( r > h ) {
585                                         r = h;
586                                         if ( n ) {
587                                                 $('#imgedit-crop-height-' + postid).val('');
588                                         } else {
589                                                 $('#imgedit-crop-width-' + postid).val('');
590                                         }
591                                 }
592
593                                 this.iasapi.setSelection( sel.x1, sel.y1, sel.x2, r );
594                                 this.iasapi.update();
595                         }
596                 }
597         }
598 };
599 })(jQuery);