]> scripts.mit.edu Git - autoinstalls/wordpress.git/blob - wp-includes/js/tinymce/plugins/image/plugin.js
WordPress 3.9-scripts
[autoinstalls/wordpress.git] / wp-includes / js / tinymce / plugins / image / plugin.js
1 /**
2  * plugin.js
3  *
4  * Copyright, Moxiecode Systems AB
5  * Released under LGPL License.
6  *
7  * License: http://www.tinymce.com/license
8  * Contributing: http://www.tinymce.com/contributing
9  */
10
11 /*global tinymce:true */
12
13 tinymce.PluginManager.add('image', function(editor) {
14         function getImageSize(url, callback) {
15                 var img = document.createElement('img');
16
17                 function done(width, height) {
18                         if (img.parentNode) {
19                                 img.parentNode.removeChild(img);
20                         }
21
22                         callback({width: width, height: height});
23                 }
24
25                 img.onload = function() {
26                         done(img.clientWidth, img.clientHeight);
27                 };
28
29                 img.onerror = function() {
30                         done();
31                 };
32
33                 var style = img.style;
34                 style.visibility = 'hidden';
35                 style.position = 'fixed';
36                 style.bottom = style.left = 0;
37                 style.width = style.height = 'auto';
38
39                 document.body.appendChild(img);
40                 img.src = url;
41         }
42
43         function applyPreview(items) {
44                 tinymce.each(items, function(item) {
45                         item.textStyle = function() {
46                                 return editor.formatter.getCssText({inline: 'img', classes: [item.value]});
47                         };
48                 });
49
50                 return items;
51         }
52
53         function createImageList(callback) {
54                 return function() {
55                         var imageList = editor.settings.image_list;
56
57                         if (typeof(imageList) == "string") {
58                                 tinymce.util.XHR.send({
59                                         url: imageList,
60                                         success: function(text) {
61                                                 callback(tinymce.util.JSON.parse(text));
62                                         }
63                                 });
64                         } else {
65                                 callback(imageList);
66                         }
67                 };
68         }
69
70         function showDialog(imageList) {
71                 var win, data = {}, dom = editor.dom, imgElm = editor.selection.getNode();
72                 var width, height, imageListCtrl, classListCtrl;
73
74                 function buildValues(listSettingName, dataItemName, defaultItems) {
75                         var selectedItem, items = [];
76
77                         tinymce.each(editor.settings[listSettingName] || defaultItems, function(target) {
78                                 var item = {
79                                         text: target.text || target.title,
80                                         value: target.value
81                                 };
82
83                                 items.push(item);
84
85                                 if (data[dataItemName] === target.value || (!selectedItem && target.selected)) {
86                                         selectedItem = item;
87                                 }
88                         });
89
90                         if (selectedItem && !data[dataItemName]) {
91                                 data[dataItemName] = selectedItem.value;
92                                 selectedItem.selected = true;
93                         }
94
95                         return items;
96                 }
97
98                 function buildImageList() {
99                         var imageListItems = [{text: 'None', value: ''}];
100
101                         tinymce.each(imageList, function(image) {
102                                 imageListItems.push({
103                                         text: image.text || image.title,
104                                         value: editor.convertURL(image.value || image.url, 'src'),
105                                         menu: image.menu
106                                 });
107                         });
108
109                         return imageListItems;
110                 }
111
112                 function recalcSize() {
113                         var widthCtrl, heightCtrl, newWidth, newHeight;
114
115                         widthCtrl = win.find('#width')[0];
116                         heightCtrl = win.find('#height')[0];
117
118                         newWidth = widthCtrl.value();
119                         newHeight = heightCtrl.value();
120
121                         if (win.find('#constrain')[0].checked() && width && height && newWidth && newHeight) {
122                                 if (width != newWidth) {
123                                         newHeight = Math.round((newWidth / width) * newHeight);
124                                         heightCtrl.value(newHeight);
125                                 } else {
126                                         newWidth = Math.round((newHeight / height) * newWidth);
127                                         widthCtrl.value(newWidth);
128                                 }
129                         }
130
131                         width = newWidth;
132                         height = newHeight;
133                 }
134
135                 function onSubmitForm() {
136                         function waitLoad(imgElm) {
137                                 function selectImage() {
138                                         imgElm.onload = imgElm.onerror = null;
139                                         editor.selection.select(imgElm);
140                                         editor.nodeChanged();
141                                 }
142
143                                 imgElm.onload = function() {
144                                         if (!data.width && !data.height) {
145                                                 dom.setAttribs(imgElm, {
146                                                         width: imgElm.clientWidth,
147                                                         height: imgElm.clientHeight
148                                                 });
149                                                 //WP
150                                                 editor.fire( 'wpNewImageRefresh', { node: imgElm } );
151                                         }
152
153                                         selectImage();
154                                 };
155
156                                 imgElm.onerror = selectImage;
157                         }
158
159                         updateStyle();
160                         recalcSize();
161
162                         data = tinymce.extend(data, win.toJSON());
163                         var caption = data.caption; // WP
164
165                         if (!data.alt) {
166                                 data.alt = '';
167                         }
168
169                         if (data.width === '') {
170                                 data.width = null;
171                         }
172
173                         if (data.height === '') {
174                                 data.height = null;
175                         }
176
177                         if (data.style === '') {
178                                 data.style = null;
179                         }
180
181                         data = {
182                                 src: data.src,
183                                 alt: data.alt,
184                                 width: data.width,
185                                 height: data.height,
186                                 style: data.style,
187                                 "class": data["class"]
188                         };
189
190                         if (!data["class"]) {
191                                 delete data["class"];
192                         }
193
194                         editor.undoManager.transact(function() {
195                                 // WP
196                                 var eventData = { node: imgElm, data: data, caption: caption };
197
198                                 editor.fire( 'wpImageFormSubmit', { imgData: eventData } );
199
200                                 if ( eventData.cancel ) {
201                                         waitLoad( eventData.node );
202                                         return;
203                                 }
204                                 // WP end
205
206                                 if (!data.src) {
207                                         if (imgElm) {
208                                                 dom.remove(imgElm);
209                                                 editor.focus();
210                                                 editor.nodeChanged();
211                                         }
212
213                                         return;
214                                 }
215
216                                 if (!imgElm) {
217                                         data.id = '__mcenew';
218                                         editor.focus();
219                                         editor.selection.setContent(dom.createHTML('img', data));
220                                         imgElm = dom.get('__mcenew');
221                                         dom.setAttrib(imgElm, 'id', null);
222                                 } else {
223                                         dom.setAttribs(imgElm, data);
224                                 }
225
226                                 waitLoad(imgElm);
227                         });
228                 }
229
230                 function removePixelSuffix(value) {
231                         if (value) {
232                                 value = value.replace(/px$/, '');
233                         }
234
235                         return value;
236                 }
237
238                 function srcChange() {
239                         if (imageListCtrl) {
240                                 imageListCtrl.value(editor.convertURL(this.value(), 'src'));
241                         }
242
243                         getImageSize(this.value(), function(data) {
244                                 if (data.width && data.height) {
245                                         width = data.width;
246                                         height = data.height;
247
248                                         win.find('#width').value(width);
249                                         win.find('#height').value(height);
250                                 }
251                         });
252                 }
253
254                 width = dom.getAttrib(imgElm, 'width');
255                 height = dom.getAttrib(imgElm, 'height');
256
257                 if (imgElm.nodeName == 'IMG' && !imgElm.getAttribute('data-mce-object') && !imgElm.getAttribute('data-mce-placeholder')) {
258                         data = {
259                                 src: dom.getAttrib(imgElm, 'src'),
260                                 alt: dom.getAttrib(imgElm, 'alt'),
261                                 "class": dom.getAttrib(imgElm, 'class'),
262                                 width: width,
263                                 height: height
264                         };
265
266                         // WP
267                         editor.fire( 'wpLoadImageData', { imgData: { data: data, node: imgElm } } );
268                 } else {
269                         imgElm = null;
270                 }
271
272                 if (imageList) {
273                         imageListCtrl = {
274                                 type: 'listbox',
275                                 label: 'Image list',
276                                 values: buildImageList(),
277                                 value: data.src && editor.convertURL(data.src, 'src'),
278                                 onselect: function(e) {
279                                         var altCtrl = win.find('#alt');
280
281                                         if (!altCtrl.value() || (e.lastControl && altCtrl.value() == e.lastControl.text())) {
282                                                 altCtrl.value(e.control.text());
283                                         }
284
285                                         win.find('#src').value(e.control.value());
286                                 },
287                                 onPostRender: function() {
288                                         imageListCtrl = this;
289                                 }
290                         };
291                 }
292
293                 if (editor.settings.image_class_list) {
294                         classListCtrl = {
295                                 name: 'class',
296                                 type: 'listbox',
297                                 label: 'Class',
298                                 values: applyPreview(buildValues('image_class_list', 'class'))
299                         };
300                 }
301
302                 // General settings shared between simple and advanced dialogs
303                 var generalFormItems = [
304                         {name: 'src', type: 'filepicker', filetype: 'image', label: 'Source', autofocus: true, onchange: srcChange},
305                         imageListCtrl
306                 ];
307
308                 if (editor.settings.image_description !== false) {
309                         generalFormItems.push({name: 'alt', type: 'textbox', label: 'Image description'});
310                 }
311
312                 if (editor.settings.image_dimensions !== false) {
313                         generalFormItems.push({
314                                 type: 'container',
315                                 label: 'Dimensions',
316                                 layout: 'flex',
317                                 direction: 'row',
318                                 align: 'center',
319                                 spacing: 5,
320                                 items: [
321                                         {name: 'width', type: 'textbox', maxLength: 5, size: 3, onchange: recalcSize, ariaLabel: 'Width'},
322                                         {type: 'label', text: 'x'},
323                                         {name: 'height', type: 'textbox', maxLength: 5, size: 3, onchange: recalcSize, ariaLabel: 'Height'},
324                                         {name: 'constrain', type: 'checkbox', checked: true, text: 'Constrain proportions'}
325                                 ]
326                         });
327                 }
328
329                 generalFormItems.push(classListCtrl);
330
331                 // WP
332                 editor.fire( 'wpLoadImageForm', { data: generalFormItems } );
333
334                 function updateStyle() {
335                         function addPixelSuffix(value) {
336                                 if (value.length > 0 && /^[0-9]+$/.test(value)) {
337                                         value += 'px';
338                                 }
339
340                                 return value;
341                         }
342
343                         if (!editor.settings.image_advtab) {
344                                 return;
345                         }
346
347                         var data = win.toJSON();
348                         var css = dom.parseStyle(data.style);
349
350                         delete css.margin;
351                         css['margin-top'] = css['margin-bottom'] = addPixelSuffix(data.vspace);
352                         css['margin-left'] = css['margin-right'] = addPixelSuffix(data.hspace);
353                         css['border-width'] = addPixelSuffix(data.border);
354
355                         win.find('#style').value(dom.serializeStyle(dom.parseStyle(dom.serializeStyle(css))));
356                 }
357
358                 if (editor.settings.image_advtab) {
359                         // Parse styles from img
360                         if (imgElm) {
361                                 data.hspace = removePixelSuffix(imgElm.style.marginLeft || imgElm.style.marginRight);
362                                 data.vspace = removePixelSuffix(imgElm.style.marginTop || imgElm.style.marginBottom);
363                                 data.border = removePixelSuffix(imgElm.style.borderWidth);
364                                 data.style = editor.dom.serializeStyle(editor.dom.parseStyle(editor.dom.getAttrib(imgElm, 'style')));
365                         }
366
367                         // Advanced dialog shows general+advanced tabs
368                         win = editor.windowManager.open({
369                                 title: 'Insert/edit image',
370                                 data: data,
371                                 bodyType: 'tabpanel',
372                                 body: [
373                                         {
374                                                 title: 'General',
375                                                 type: 'form',
376                                                 items: generalFormItems
377                                         },
378
379                                         {
380                                                 title: 'Advanced',
381                                                 type: 'form',
382                                                 pack: 'start',
383                                                 items: [
384                                                         {
385                                                                 label: 'Style',
386                                                                 name: 'style',
387                                                                 type: 'textbox'
388                                                         },
389                                                         {
390                                                                 type: 'form',
391                                                                 layout: 'grid',
392                                                                 packV: 'start',
393                                                                 columns: 2,
394                                                                 padding: 0,
395                                                                 alignH: ['left', 'right'],
396                                                                 defaults: {
397                                                                         type: 'textbox',
398                                                                         maxWidth: 50,
399                                                                         onchange: updateStyle
400                                                                 },
401                                                                 items: [
402                                                                         {label: 'Vertical space', name: 'vspace'},
403                                                                         {label: 'Horizontal space', name: 'hspace'},
404                                                                         {label: 'Border', name: 'border'}
405                                                                 ]
406                                                         }
407                                                 ]
408                                         }
409                                 ],
410                                 onSubmit: onSubmitForm
411                         });
412                 } else {
413                         // Simple default dialog
414                         win = editor.windowManager.open({
415                                 title: 'Insert/edit image',
416                                 data: data,
417                                 body: generalFormItems,
418                                 onSubmit: onSubmitForm
419                         });
420                 }
421         }
422
423         // WP
424         editor.addCommand( 'mceImage', function() {
425                 createImageList( showDialog )();
426         });
427
428         editor.addButton('image', {
429                 icon: 'image',
430                 tooltip: 'Insert/edit image',
431                 onclick: createImageList(showDialog),
432                 stateSelector: 'img:not([data-mce-object],[data-mce-placeholder])'
433         });
434
435         editor.addMenuItem('image', {
436                 icon: 'image',
437                 text: 'Insert image',
438                 onclick: createImageList(showDialog),
439                 context: 'insert',
440                 prependToContext: true
441         });
442 });