]> scripts.mit.edu Git - autoinstalls/wordpress.git/blob - wp-includes/js/tinymce/plugins/image/plugin.js
WordPress 4.1-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 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                                 var srcURL = this.value(),
232                                 absoluteURLPattern = new RegExp('^(?:[a-z]+:)?//', 'i'),
233                                 baseURL = editor.settings.document_base_url;
234
235                                 //Pattern test the src url and make sure we haven't already prepended the url
236                                 if (baseURL && !absoluteURLPattern.test(srcURL) && srcURL.substring(0, baseURL.length) !== baseURL) {
237                                         this.value(baseURL + srcURL);
238                                 }
239
240                                 getImageSize(this.value(), function(data) {
241                                         if (data.width && data.height && imageDimensions) {
242                                                 width = data.width;
243                                                 height = data.height;
244
245                                                 win.find('#width').value(width);
246                                                 win.find('#height').value(height);
247                                         }
248                                 });
249                         }
250                 }
251
252                 width = dom.getAttrib(imgElm, 'width');
253                 height = dom.getAttrib(imgElm, 'height');
254
255                 if (imgElm.nodeName == 'IMG' && !imgElm.getAttribute('data-mce-object') && !imgElm.getAttribute('data-mce-placeholder')) {
256                         data = {
257                                 src: dom.getAttrib(imgElm, 'src'),
258                                 alt: dom.getAttrib(imgElm, 'alt'),
259                                 "class": dom.getAttrib(imgElm, 'class'),
260                                 width: width,
261                                 height: height
262                         };
263
264                         // WP
265                         editor.fire( 'wpLoadImageData', { imgData: { data: data, node: imgElm } } );
266                 } else {
267                         imgElm = null;
268                 }
269
270                 if (imageList) {
271                         imageListCtrl = {
272                                 type: 'listbox',
273                                 label: 'Image list',
274                                 values: buildListItems(
275                                         imageList,
276                                         function(item) {
277                                                 item.value = editor.convertURL(item.value || item.url, 'src');
278                                         },
279                                         [{text: 'None', value: ''}]
280                                 ),
281                                 value: data.src && editor.convertURL(data.src, 'src'),
282                                 onselect: function(e) {
283                                         var altCtrl = win.find('#alt');
284
285                                         if (!altCtrl.value() || (e.lastControl && altCtrl.value() == e.lastControl.text())) {
286                                                 altCtrl.value(e.control.text());
287                                         }
288
289                                         win.find('#src').value(e.control.value()).fire('change');
290                                 },
291                                 onPostRender: function() {
292                                         imageListCtrl = this;
293                                 }
294                         };
295                 }
296
297                 if (editor.settings.image_class_list) {
298                         classListCtrl = {
299                                 name: 'class',
300                                 type: 'listbox',
301                                 label: 'Class',
302                                 values: buildListItems(
303                                         editor.settings.image_class_list,
304                                         function(item) {
305                                                 if (item.value) {
306                                                         item.textStyle = function() {
307                                                                 return editor.formatter.getCssText({inline: 'img', classes: [item.value]});
308                                                         };
309                                                 }
310                                         }
311                                 )
312                         };
313                 }
314
315                 // General settings shared between simple and advanced dialogs
316                 var generalFormItems = [
317                         {
318                                 name: 'src',
319                                 type: 'filepicker',
320                                 filetype: 'image',
321                                 label: 'Source',
322                                 autofocus: true,
323                                 onchange: srcChange
324                         },
325                         imageListCtrl
326                 ];
327
328                 if (editor.settings.image_description !== false) {
329                         generalFormItems.push({name: 'alt', type: 'textbox', label: 'Image description'});
330                 }
331
332                 if (imageDimensions) {
333                         generalFormItems.push({
334                                 type: 'container',
335                                 label: 'Dimensions',
336                                 layout: 'flex',
337                                 direction: 'row',
338                                 align: 'center',
339                                 spacing: 5,
340                                 items: [
341                                         {name: 'width', type: 'textbox', maxLength: 5, size: 3, onchange: recalcSize, ariaLabel: 'Width'},
342                                         {type: 'label', text: 'x'},
343                                         {name: 'height', type: 'textbox', maxLength: 5, size: 3, onchange: recalcSize, ariaLabel: 'Height'},
344                                         {name: 'constrain', type: 'checkbox', checked: true, text: 'Constrain proportions'}
345                                 ]
346                         });
347                 }
348
349                 generalFormItems.push(classListCtrl);
350
351                 // WP
352                 editor.fire( 'wpLoadImageForm', { data: generalFormItems } );
353
354                 function updateStyle() {
355                         function addPixelSuffix(value) {
356                                 if (value.length > 0 && /^[0-9]+$/.test(value)) {
357                                         value += 'px';
358                                 }
359
360                                 return value;
361                         }
362
363                         if (!editor.settings.image_advtab) {
364                                 return;
365                         }
366
367                         var data = win.toJSON();
368                         var css = dom.parseStyle(data.style);
369
370                         delete css.margin;
371                         css['margin-top'] = css['margin-bottom'] = addPixelSuffix(data.vspace);
372                         css['margin-left'] = css['margin-right'] = addPixelSuffix(data.hspace);
373                         css['border-width'] = addPixelSuffix(data.border);
374
375                         win.find('#style').value(dom.serializeStyle(dom.parseStyle(dom.serializeStyle(css))));
376                 }
377
378                 if (editor.settings.image_advtab) {
379                         // Parse styles from img
380                         if (imgElm) {
381                                 data.hspace = removePixelSuffix(imgElm.style.marginLeft || imgElm.style.marginRight);
382                                 data.vspace = removePixelSuffix(imgElm.style.marginTop || imgElm.style.marginBottom);
383                                 data.border = removePixelSuffix(imgElm.style.borderWidth);
384                                 data.style = editor.dom.serializeStyle(editor.dom.parseStyle(editor.dom.getAttrib(imgElm, 'style')));
385                         }
386
387                         // Advanced dialog shows general+advanced tabs
388                         win = editor.windowManager.open({
389                                 title: 'Insert/edit image',
390                                 data: data,
391                                 bodyType: 'tabpanel',
392                                 body: [
393                                         {
394                                                 title: 'General',
395                                                 type: 'form',
396                                                 items: generalFormItems
397                                         },
398
399                                         {
400                                                 title: 'Advanced',
401                                                 type: 'form',
402                                                 pack: 'start',
403                                                 items: [
404                                                         {
405                                                                 label: 'Style',
406                                                                 name: 'style',
407                                                                 type: 'textbox'
408                                                         },
409                                                         {
410                                                                 type: 'form',
411                                                                 layout: 'grid',
412                                                                 packV: 'start',
413                                                                 columns: 2,
414                                                                 padding: 0,
415                                                                 alignH: ['left', 'right'],
416                                                                 defaults: {
417                                                                         type: 'textbox',
418                                                                         maxWidth: 50,
419                                                                         onchange: updateStyle
420                                                                 },
421                                                                 items: [
422                                                                         {label: 'Vertical space', name: 'vspace'},
423                                                                         {label: 'Horizontal space', name: 'hspace'},
424                                                                         {label: 'Border', name: 'border'}
425                                                                 ]
426                                                         }
427                                                 ]
428                                         }
429                                 ],
430                                 onSubmit: onSubmitForm
431                         });
432                 } else {
433                         // Simple default dialog
434                         win = editor.windowManager.open({
435                                 title: 'Insert/edit image',
436                                 data: data,
437                                 body: generalFormItems,
438                                 onSubmit: onSubmitForm
439                         });
440                 }
441         }
442
443         editor.addButton('image', {
444                 icon: 'image',
445                 tooltip: 'Insert/edit image',
446                 onclick: createImageList(showDialog),
447                 stateSelector: 'img:not([data-mce-object],[data-mce-placeholder])'
448         });
449
450         editor.addMenuItem('image', {
451                 icon: 'image',
452                 text: 'Insert image',
453                 onclick: createImageList(showDialog),
454                 context: 'insert',
455                 prependToContext: true
456         });
457
458         editor.addCommand('mceImage', createImageList(showDialog));
459 });