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