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