angelovcom.net

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

plugin.js (40022B)


      1 (function () {
      2 var image = (function (domGlobals) {
      3     'use strict';
      4 
      5     var global = tinymce.util.Tools.resolve('tinymce.PluginManager');
      6 
      7     var hasDimensions = function (editor) {
      8       return editor.settings.image_dimensions === false ? false : true;
      9     };
     10     var hasAdvTab = function (editor) {
     11       return editor.settings.image_advtab === true ? true : false;
     12     };
     13     var getPrependUrl = function (editor) {
     14       return editor.getParam('image_prepend_url', '');
     15     };
     16     var getClassList = function (editor) {
     17       return editor.getParam('image_class_list');
     18     };
     19     var hasDescription = function (editor) {
     20       return editor.settings.image_description === false ? false : true;
     21     };
     22     var hasImageTitle = function (editor) {
     23       return editor.settings.image_title === true ? true : false;
     24     };
     25     var hasImageCaption = function (editor) {
     26       return editor.settings.image_caption === true ? true : false;
     27     };
     28     var getImageList = function (editor) {
     29       return editor.getParam('image_list', false);
     30     };
     31     var hasUploadUrl = function (editor) {
     32       return editor.getParam('images_upload_url', false);
     33     };
     34     var hasUploadHandler = function (editor) {
     35       return editor.getParam('images_upload_handler', false);
     36     };
     37     var getUploadUrl = function (editor) {
     38       return editor.getParam('images_upload_url');
     39     };
     40     var getUploadHandler = function (editor) {
     41       return editor.getParam('images_upload_handler');
     42     };
     43     var getUploadBasePath = function (editor) {
     44       return editor.getParam('images_upload_base_path');
     45     };
     46     var getUploadCredentials = function (editor) {
     47       return editor.getParam('images_upload_credentials');
     48     };
     49     var Settings = {
     50       hasDimensions: hasDimensions,
     51       hasAdvTab: hasAdvTab,
     52       getPrependUrl: getPrependUrl,
     53       getClassList: getClassList,
     54       hasDescription: hasDescription,
     55       hasImageTitle: hasImageTitle,
     56       hasImageCaption: hasImageCaption,
     57       getImageList: getImageList,
     58       hasUploadUrl: hasUploadUrl,
     59       hasUploadHandler: hasUploadHandler,
     60       getUploadUrl: getUploadUrl,
     61       getUploadHandler: getUploadHandler,
     62       getUploadBasePath: getUploadBasePath,
     63       getUploadCredentials: getUploadCredentials
     64     };
     65 
     66     var Global = typeof domGlobals.window !== 'undefined' ? domGlobals.window : Function('return this;')();
     67 
     68     var path = function (parts, scope) {
     69       var o = scope !== undefined && scope !== null ? scope : Global;
     70       for (var i = 0; i < parts.length && o !== undefined && o !== null; ++i) {
     71         o = o[parts[i]];
     72       }
     73       return o;
     74     };
     75     var resolve = function (p, scope) {
     76       var parts = p.split('.');
     77       return path(parts, scope);
     78     };
     79 
     80     var unsafe = function (name, scope) {
     81       return resolve(name, scope);
     82     };
     83     var getOrDie = function (name, scope) {
     84       var actual = unsafe(name, scope);
     85       if (actual === undefined || actual === null) {
     86         throw new Error(name + ' not available on this browser');
     87       }
     88       return actual;
     89     };
     90     var Global$1 = { getOrDie: getOrDie };
     91 
     92     function FileReader () {
     93       var f = Global$1.getOrDie('FileReader');
     94       return new f();
     95     }
     96 
     97     var global$1 = tinymce.util.Tools.resolve('tinymce.util.Promise');
     98 
     99     var global$2 = tinymce.util.Tools.resolve('tinymce.util.Tools');
    100 
    101     var global$3 = tinymce.util.Tools.resolve('tinymce.util.XHR');
    102 
    103     var parseIntAndGetMax = function (val1, val2) {
    104       return Math.max(parseInt(val1, 10), parseInt(val2, 10));
    105     };
    106     var getImageSize = function (url, callback) {
    107       var img = domGlobals.document.createElement('img');
    108       function done(width, height) {
    109         if (img.parentNode) {
    110           img.parentNode.removeChild(img);
    111         }
    112         callback({
    113           width: width,
    114           height: height
    115         });
    116       }
    117       img.onload = function () {
    118         var width = parseIntAndGetMax(img.width, img.clientWidth);
    119         var height = parseIntAndGetMax(img.height, img.clientHeight);
    120         done(width, height);
    121       };
    122       img.onerror = function () {
    123         done(0, 0);
    124       };
    125       var style = img.style;
    126       style.visibility = 'hidden';
    127       style.position = 'fixed';
    128       style.bottom = style.left = '0px';
    129       style.width = style.height = 'auto';
    130       domGlobals.document.body.appendChild(img);
    131       img.src = url;
    132     };
    133     var buildListItems = function (inputList, itemCallback, startItems) {
    134       function appendItems(values, output) {
    135         output = output || [];
    136         global$2.each(values, function (item) {
    137           var menuItem = { text: item.text || item.title };
    138           if (item.menu) {
    139             menuItem.menu = appendItems(item.menu);
    140           } else {
    141             menuItem.value = item.value;
    142             itemCallback(menuItem);
    143           }
    144           output.push(menuItem);
    145         });
    146         return output;
    147       }
    148       return appendItems(inputList, startItems || []);
    149     };
    150     var removePixelSuffix = function (value) {
    151       if (value) {
    152         value = value.replace(/px$/, '');
    153       }
    154       return value;
    155     };
    156     var addPixelSuffix = function (value) {
    157       if (value.length > 0 && /^[0-9]+$/.test(value)) {
    158         value += 'px';
    159       }
    160       return value;
    161     };
    162     var mergeMargins = function (css) {
    163       if (css.margin) {
    164         var splitMargin = css.margin.split(' ');
    165         switch (splitMargin.length) {
    166         case 1:
    167           css['margin-top'] = css['margin-top'] || splitMargin[0];
    168           css['margin-right'] = css['margin-right'] || splitMargin[0];
    169           css['margin-bottom'] = css['margin-bottom'] || splitMargin[0];
    170           css['margin-left'] = css['margin-left'] || splitMargin[0];
    171           break;
    172         case 2:
    173           css['margin-top'] = css['margin-top'] || splitMargin[0];
    174           css['margin-right'] = css['margin-right'] || splitMargin[1];
    175           css['margin-bottom'] = css['margin-bottom'] || splitMargin[0];
    176           css['margin-left'] = css['margin-left'] || splitMargin[1];
    177           break;
    178         case 3:
    179           css['margin-top'] = css['margin-top'] || splitMargin[0];
    180           css['margin-right'] = css['margin-right'] || splitMargin[1];
    181           css['margin-bottom'] = css['margin-bottom'] || splitMargin[2];
    182           css['margin-left'] = css['margin-left'] || splitMargin[1];
    183           break;
    184         case 4:
    185           css['margin-top'] = css['margin-top'] || splitMargin[0];
    186           css['margin-right'] = css['margin-right'] || splitMargin[1];
    187           css['margin-bottom'] = css['margin-bottom'] || splitMargin[2];
    188           css['margin-left'] = css['margin-left'] || splitMargin[3];
    189         }
    190         delete css.margin;
    191       }
    192       return css;
    193     };
    194     var createImageList = function (editor, callback) {
    195       var imageList = Settings.getImageList(editor);
    196       if (typeof imageList === 'string') {
    197         global$3.send({
    198           url: imageList,
    199           success: function (text) {
    200             callback(JSON.parse(text));
    201           }
    202         });
    203       } else if (typeof imageList === 'function') {
    204         imageList(callback);
    205       } else {
    206         callback(imageList);
    207       }
    208     };
    209     var waitLoadImage = function (editor, data, imgElm) {
    210       function selectImage() {
    211         imgElm.onload = imgElm.onerror = null;
    212         if (editor.selection) {
    213           editor.selection.select(imgElm);
    214           editor.nodeChanged();
    215         }
    216       }
    217       imgElm.onload = function () {
    218         if (!data.width && !data.height && Settings.hasDimensions(editor)) {
    219           editor.dom.setAttribs(imgElm, {
    220             width: imgElm.clientWidth,
    221             height: imgElm.clientHeight
    222           });
    223         }
    224         selectImage();
    225       };
    226       imgElm.onerror = selectImage;
    227     };
    228     var blobToDataUri = function (blob) {
    229       return new global$1(function (resolve, reject) {
    230         var reader = FileReader();
    231         reader.onload = function () {
    232           resolve(reader.result);
    233         };
    234         reader.onerror = function () {
    235           reject(reader.error.message);
    236         };
    237         reader.readAsDataURL(blob);
    238       });
    239     };
    240     var Utils = {
    241       getImageSize: getImageSize,
    242       buildListItems: buildListItems,
    243       removePixelSuffix: removePixelSuffix,
    244       addPixelSuffix: addPixelSuffix,
    245       mergeMargins: mergeMargins,
    246       createImageList: createImageList,
    247       waitLoadImage: waitLoadImage,
    248       blobToDataUri: blobToDataUri
    249     };
    250 
    251     var global$4 = tinymce.util.Tools.resolve('tinymce.dom.DOMUtils');
    252 
    253     var hasOwnProperty = Object.prototype.hasOwnProperty;
    254     var shallow = function (old, nu) {
    255       return nu;
    256     };
    257     var baseMerge = function (merger) {
    258       return function () {
    259         var objects = new Array(arguments.length);
    260         for (var i = 0; i < objects.length; i++) {
    261           objects[i] = arguments[i];
    262         }
    263         if (objects.length === 0) {
    264           throw new Error('Can\'t merge zero objects');
    265         }
    266         var ret = {};
    267         for (var j = 0; j < objects.length; j++) {
    268           var curObject = objects[j];
    269           for (var key in curObject) {
    270             if (hasOwnProperty.call(curObject, key)) {
    271               ret[key] = merger(ret[key], curObject[key]);
    272             }
    273           }
    274         }
    275         return ret;
    276       };
    277     };
    278     var merge = baseMerge(shallow);
    279 
    280     var DOM = global$4.DOM;
    281     var getHspace = function (image) {
    282       if (image.style.marginLeft && image.style.marginRight && image.style.marginLeft === image.style.marginRight) {
    283         return Utils.removePixelSuffix(image.style.marginLeft);
    284       } else {
    285         return '';
    286       }
    287     };
    288     var getVspace = function (image) {
    289       if (image.style.marginTop && image.style.marginBottom && image.style.marginTop === image.style.marginBottom) {
    290         return Utils.removePixelSuffix(image.style.marginTop);
    291       } else {
    292         return '';
    293       }
    294     };
    295     var getBorder = function (image) {
    296       if (image.style.borderWidth) {
    297         return Utils.removePixelSuffix(image.style.borderWidth);
    298       } else {
    299         return '';
    300       }
    301     };
    302     var getAttrib = function (image, name) {
    303       if (image.hasAttribute(name)) {
    304         return image.getAttribute(name);
    305       } else {
    306         return '';
    307       }
    308     };
    309     var getStyle = function (image, name) {
    310       return image.style[name] ? image.style[name] : '';
    311     };
    312     var hasCaption = function (image) {
    313       return image.parentNode !== null && image.parentNode.nodeName === 'FIGURE';
    314     };
    315     var setAttrib = function (image, name, value) {
    316       image.setAttribute(name, value);
    317     };
    318     var wrapInFigure = function (image) {
    319       var figureElm = DOM.create('figure', { class: 'image' });
    320       DOM.insertAfter(figureElm, image);
    321       figureElm.appendChild(image);
    322       figureElm.appendChild(DOM.create('figcaption', { contentEditable: true }, 'Caption'));
    323       figureElm.contentEditable = 'false';
    324     };
    325     var removeFigure = function (image) {
    326       var figureElm = image.parentNode;
    327       DOM.insertAfter(image, figureElm);
    328       DOM.remove(figureElm);
    329     };
    330     var toggleCaption = function (image) {
    331       if (hasCaption(image)) {
    332         removeFigure(image);
    333       } else {
    334         wrapInFigure(image);
    335       }
    336     };
    337     var normalizeStyle = function (image, normalizeCss) {
    338       var attrValue = image.getAttribute('style');
    339       var value = normalizeCss(attrValue !== null ? attrValue : '');
    340       if (value.length > 0) {
    341         image.setAttribute('style', value);
    342         image.setAttribute('data-mce-style', value);
    343       } else {
    344         image.removeAttribute('style');
    345       }
    346     };
    347     var setSize = function (name, normalizeCss) {
    348       return function (image, name, value) {
    349         if (image.style[name]) {
    350           image.style[name] = Utils.addPixelSuffix(value);
    351           normalizeStyle(image, normalizeCss);
    352         } else {
    353           setAttrib(image, name, value);
    354         }
    355       };
    356     };
    357     var getSize = function (image, name) {
    358       if (image.style[name]) {
    359         return Utils.removePixelSuffix(image.style[name]);
    360       } else {
    361         return getAttrib(image, name);
    362       }
    363     };
    364     var setHspace = function (image, value) {
    365       var pxValue = Utils.addPixelSuffix(value);
    366       image.style.marginLeft = pxValue;
    367       image.style.marginRight = pxValue;
    368     };
    369     var setVspace = function (image, value) {
    370       var pxValue = Utils.addPixelSuffix(value);
    371       image.style.marginTop = pxValue;
    372       image.style.marginBottom = pxValue;
    373     };
    374     var setBorder = function (image, value) {
    375       var pxValue = Utils.addPixelSuffix(value);
    376       image.style.borderWidth = pxValue;
    377     };
    378     var setBorderStyle = function (image, value) {
    379       image.style.borderStyle = value;
    380     };
    381     var getBorderStyle = function (image) {
    382       return getStyle(image, 'borderStyle');
    383     };
    384     var isFigure = function (elm) {
    385       return elm.nodeName === 'FIGURE';
    386     };
    387     var defaultData = function () {
    388       return {
    389         src: '',
    390         alt: '',
    391         title: '',
    392         width: '',
    393         height: '',
    394         class: '',
    395         style: '',
    396         caption: false,
    397         hspace: '',
    398         vspace: '',
    399         border: '',
    400         borderStyle: ''
    401       };
    402     };
    403     var getStyleValue = function (normalizeCss, data) {
    404       var image = domGlobals.document.createElement('img');
    405       setAttrib(image, 'style', data.style);
    406       if (getHspace(image) || data.hspace !== '') {
    407         setHspace(image, data.hspace);
    408       }
    409       if (getVspace(image) || data.vspace !== '') {
    410         setVspace(image, data.vspace);
    411       }
    412       if (getBorder(image) || data.border !== '') {
    413         setBorder(image, data.border);
    414       }
    415       if (getBorderStyle(image) || data.borderStyle !== '') {
    416         setBorderStyle(image, data.borderStyle);
    417       }
    418       return normalizeCss(image.getAttribute('style'));
    419     };
    420     var create = function (normalizeCss, data) {
    421       var image = domGlobals.document.createElement('img');
    422       write(normalizeCss, merge(data, { caption: false }), image);
    423       setAttrib(image, 'alt', data.alt);
    424       if (data.caption) {
    425         var figure = DOM.create('figure', { class: 'image' });
    426         figure.appendChild(image);
    427         figure.appendChild(DOM.create('figcaption', { contentEditable: true }, 'Caption'));
    428         figure.contentEditable = 'false';
    429         return figure;
    430       } else {
    431         return image;
    432       }
    433     };
    434     var read = function (normalizeCss, image) {
    435       return {
    436         src: getAttrib(image, 'src'),
    437         alt: getAttrib(image, 'alt'),
    438         title: getAttrib(image, 'title'),
    439         width: getSize(image, 'width'),
    440         height: getSize(image, 'height'),
    441         class: getAttrib(image, 'class'),
    442         style: normalizeCss(getAttrib(image, 'style')),
    443         caption: hasCaption(image),
    444         hspace: getHspace(image),
    445         vspace: getVspace(image),
    446         border: getBorder(image),
    447         borderStyle: getStyle(image, 'borderStyle')
    448       };
    449     };
    450     var updateProp = function (image, oldData, newData, name, set) {
    451       if (newData[name] !== oldData[name]) {
    452         set(image, name, newData[name]);
    453       }
    454     };
    455     var normalized = function (set, normalizeCss) {
    456       return function (image, name, value) {
    457         set(image, value);
    458         normalizeStyle(image, normalizeCss);
    459       };
    460     };
    461     var write = function (normalizeCss, newData, image) {
    462       var oldData = read(normalizeCss, image);
    463       updateProp(image, oldData, newData, 'caption', function (image, _name, _value) {
    464         return toggleCaption(image);
    465       });
    466       updateProp(image, oldData, newData, 'src', setAttrib);
    467       updateProp(image, oldData, newData, 'alt', setAttrib);
    468       updateProp(image, oldData, newData, 'title', setAttrib);
    469       updateProp(image, oldData, newData, 'width', setSize('width', normalizeCss));
    470       updateProp(image, oldData, newData, 'height', setSize('height', normalizeCss));
    471       updateProp(image, oldData, newData, 'class', setAttrib);
    472       updateProp(image, oldData, newData, 'style', normalized(function (image, value) {
    473         return setAttrib(image, 'style', value);
    474       }, normalizeCss));
    475       updateProp(image, oldData, newData, 'hspace', normalized(setHspace, normalizeCss));
    476       updateProp(image, oldData, newData, 'vspace', normalized(setVspace, normalizeCss));
    477       updateProp(image, oldData, newData, 'border', normalized(setBorder, normalizeCss));
    478       updateProp(image, oldData, newData, 'borderStyle', normalized(setBorderStyle, normalizeCss));
    479     };
    480 
    481     var normalizeCss = function (editor, cssText) {
    482       var css = editor.dom.styles.parse(cssText);
    483       var mergedCss = Utils.mergeMargins(css);
    484       var compressed = editor.dom.styles.parse(editor.dom.styles.serialize(mergedCss));
    485       return editor.dom.styles.serialize(compressed);
    486     };
    487     var getSelectedImage = function (editor) {
    488       var imgElm = editor.selection.getNode();
    489       var figureElm = editor.dom.getParent(imgElm, 'figure.image');
    490       if (figureElm) {
    491         return editor.dom.select('img', figureElm)[0];
    492       }
    493       if (imgElm && (imgElm.nodeName !== 'IMG' || imgElm.getAttribute('data-mce-object') || imgElm.getAttribute('data-mce-placeholder'))) {
    494         return null;
    495       }
    496       return imgElm;
    497     };
    498     var splitTextBlock = function (editor, figure) {
    499       var dom = editor.dom;
    500       var textBlock = dom.getParent(figure.parentNode, function (node) {
    501         return editor.schema.getTextBlockElements()[node.nodeName];
    502       }, editor.getBody());
    503       if (textBlock) {
    504         return dom.split(textBlock, figure);
    505       } else {
    506         return figure;
    507       }
    508     };
    509     var readImageDataFromSelection = function (editor) {
    510       var image = getSelectedImage(editor);
    511       return image ? read(function (css) {
    512         return normalizeCss(editor, css);
    513       }, image) : defaultData();
    514     };
    515     var insertImageAtCaret = function (editor, data) {
    516       var elm = create(function (css) {
    517         return normalizeCss(editor, css);
    518       }, data);
    519       editor.dom.setAttrib(elm, 'data-mce-id', '__mcenew');
    520       editor.focus();
    521       editor.selection.setContent(elm.outerHTML);
    522       var insertedElm = editor.dom.select('*[data-mce-id="__mcenew"]')[0];
    523       editor.dom.setAttrib(insertedElm, 'data-mce-id', null);
    524       if (isFigure(insertedElm)) {
    525         var figure = splitTextBlock(editor, insertedElm);
    526         editor.selection.select(figure);
    527       } else {
    528         editor.selection.select(insertedElm);
    529       }
    530     };
    531     var syncSrcAttr = function (editor, image) {
    532       editor.dom.setAttrib(image, 'src', image.getAttribute('src'));
    533     };
    534     var deleteImage = function (editor, image) {
    535       if (image) {
    536         var elm = editor.dom.is(image.parentNode, 'figure.image') ? image.parentNode : image;
    537         editor.dom.remove(elm);
    538         editor.focus();
    539         editor.nodeChanged();
    540         if (editor.dom.isEmpty(editor.getBody())) {
    541           editor.setContent('');
    542           editor.selection.setCursorLocation();
    543         }
    544       }
    545     };
    546     var writeImageDataToSelection = function (editor, data) {
    547       var image = getSelectedImage(editor);
    548       write(function (css) {
    549         return normalizeCss(editor, css);
    550       }, data, image);
    551       syncSrcAttr(editor, image);
    552       if (isFigure(image.parentNode)) {
    553         var figure = image.parentNode;
    554         splitTextBlock(editor, figure);
    555         editor.selection.select(image.parentNode);
    556       } else {
    557         editor.selection.select(image);
    558         Utils.waitLoadImage(editor, data, image);
    559       }
    560     };
    561     var insertOrUpdateImage = function (editor, data) {
    562       var image = getSelectedImage(editor);
    563       if (image) {
    564         if (data.src) {
    565           writeImageDataToSelection(editor, data);
    566         } else {
    567           deleteImage(editor, image);
    568         }
    569       } else if (data.src) {
    570         insertImageAtCaret(editor, data);
    571       }
    572     };
    573 
    574     var updateVSpaceHSpaceBorder = function (editor) {
    575       return function (evt) {
    576         var dom = editor.dom;
    577         var rootControl = evt.control.rootControl;
    578         if (!Settings.hasAdvTab(editor)) {
    579           return;
    580         }
    581         var data = rootControl.toJSON();
    582         var css = dom.parseStyle(data.style);
    583         rootControl.find('#vspace').value('');
    584         rootControl.find('#hspace').value('');
    585         css = Utils.mergeMargins(css);
    586         if (css['margin-top'] && css['margin-bottom'] || css['margin-right'] && css['margin-left']) {
    587           if (css['margin-top'] === css['margin-bottom']) {
    588             rootControl.find('#vspace').value(Utils.removePixelSuffix(css['margin-top']));
    589           } else {
    590             rootControl.find('#vspace').value('');
    591           }
    592           if (css['margin-right'] === css['margin-left']) {
    593             rootControl.find('#hspace').value(Utils.removePixelSuffix(css['margin-right']));
    594           } else {
    595             rootControl.find('#hspace').value('');
    596           }
    597         }
    598         if (css['border-width']) {
    599           rootControl.find('#border').value(Utils.removePixelSuffix(css['border-width']));
    600         } else {
    601           rootControl.find('#border').value('');
    602         }
    603         if (css['border-style']) {
    604           rootControl.find('#borderStyle').value(css['border-style']);
    605         } else {
    606           rootControl.find('#borderStyle').value('');
    607         }
    608         rootControl.find('#style').value(dom.serializeStyle(dom.parseStyle(dom.serializeStyle(css))));
    609       };
    610     };
    611     var updateStyle = function (editor, win) {
    612       win.find('#style').each(function (ctrl) {
    613         var value = getStyleValue(function (css) {
    614           return normalizeCss(editor, css);
    615         }, merge(defaultData(), win.toJSON()));
    616         ctrl.value(value);
    617       });
    618     };
    619     var makeTab = function (editor) {
    620       return {
    621         title: 'Advanced',
    622         type: 'form',
    623         pack: 'start',
    624         items: [
    625           {
    626             label: 'Style',
    627             name: 'style',
    628             type: 'textbox',
    629             onchange: updateVSpaceHSpaceBorder(editor)
    630           },
    631           {
    632             type: 'form',
    633             layout: 'grid',
    634             packV: 'start',
    635             columns: 2,
    636             padding: 0,
    637             defaults: {
    638               type: 'textbox',
    639               maxWidth: 50,
    640               onchange: function (evt) {
    641                 updateStyle(editor, evt.control.rootControl);
    642               }
    643             },
    644             items: [
    645               {
    646                 label: 'Vertical space',
    647                 name: 'vspace'
    648               },
    649               {
    650                 label: 'Border width',
    651                 name: 'border'
    652               },
    653               {
    654                 label: 'Horizontal space',
    655                 name: 'hspace'
    656               },
    657               {
    658                 label: 'Border style',
    659                 type: 'listbox',
    660                 name: 'borderStyle',
    661                 width: 90,
    662                 maxWidth: 90,
    663                 onselect: function (evt) {
    664                   updateStyle(editor, evt.control.rootControl);
    665                 },
    666                 values: [
    667                   {
    668                     text: 'Select...',
    669                     value: ''
    670                   },
    671                   {
    672                     text: 'Solid',
    673                     value: 'solid'
    674                   },
    675                   {
    676                     text: 'Dotted',
    677                     value: 'dotted'
    678                   },
    679                   {
    680                     text: 'Dashed',
    681                     value: 'dashed'
    682                   },
    683                   {
    684                     text: 'Double',
    685                     value: 'double'
    686                   },
    687                   {
    688                     text: 'Groove',
    689                     value: 'groove'
    690                   },
    691                   {
    692                     text: 'Ridge',
    693                     value: 'ridge'
    694                   },
    695                   {
    696                     text: 'Inset',
    697                     value: 'inset'
    698                   },
    699                   {
    700                     text: 'Outset',
    701                     value: 'outset'
    702                   },
    703                   {
    704                     text: 'None',
    705                     value: 'none'
    706                   },
    707                   {
    708                     text: 'Hidden',
    709                     value: 'hidden'
    710                   }
    711                 ]
    712               }
    713             ]
    714           }
    715         ]
    716       };
    717     };
    718     var AdvTab = { makeTab: makeTab };
    719 
    720     var doSyncSize = function (widthCtrl, heightCtrl) {
    721       widthCtrl.state.set('oldVal', widthCtrl.value());
    722       heightCtrl.state.set('oldVal', heightCtrl.value());
    723     };
    724     var doSizeControls = function (win, f) {
    725       var widthCtrl = win.find('#width')[0];
    726       var heightCtrl = win.find('#height')[0];
    727       var constrained = win.find('#constrain')[0];
    728       if (widthCtrl && heightCtrl && constrained) {
    729         f(widthCtrl, heightCtrl, constrained.checked());
    730       }
    731     };
    732     var doUpdateSize = function (widthCtrl, heightCtrl, isContrained) {
    733       var oldWidth = widthCtrl.state.get('oldVal');
    734       var oldHeight = heightCtrl.state.get('oldVal');
    735       var newWidth = widthCtrl.value();
    736       var newHeight = heightCtrl.value();
    737       if (isContrained && oldWidth && oldHeight && newWidth && newHeight) {
    738         if (newWidth !== oldWidth) {
    739           newHeight = Math.round(newWidth / oldWidth * newHeight);
    740           if (!isNaN(newHeight)) {
    741             heightCtrl.value(newHeight);
    742           }
    743         } else {
    744           newWidth = Math.round(newHeight / oldHeight * newWidth);
    745           if (!isNaN(newWidth)) {
    746             widthCtrl.value(newWidth);
    747           }
    748         }
    749       }
    750       doSyncSize(widthCtrl, heightCtrl);
    751     };
    752     var syncSize = function (win) {
    753       doSizeControls(win, doSyncSize);
    754     };
    755     var updateSize = function (win) {
    756       doSizeControls(win, doUpdateSize);
    757     };
    758     var createUi = function () {
    759       var recalcSize = function (evt) {
    760         updateSize(evt.control.rootControl);
    761       };
    762       return {
    763         type: 'container',
    764         label: 'Dimensions',
    765         layout: 'flex',
    766         align: 'center',
    767         spacing: 5,
    768         items: [
    769           {
    770             name: 'width',
    771             type: 'textbox',
    772             maxLength: 5,
    773             size: 5,
    774             onchange: recalcSize,
    775             ariaLabel: 'Width'
    776           },
    777           {
    778             type: 'label',
    779             text: 'x'
    780           },
    781           {
    782             name: 'height',
    783             type: 'textbox',
    784             maxLength: 5,
    785             size: 5,
    786             onchange: recalcSize,
    787             ariaLabel: 'Height'
    788           },
    789           {
    790             name: 'constrain',
    791             type: 'checkbox',
    792             checked: true,
    793             text: 'Constrain proportions'
    794           }
    795         ]
    796       };
    797     };
    798     var SizeManager = {
    799       createUi: createUi,
    800       syncSize: syncSize,
    801       updateSize: updateSize
    802     };
    803 
    804     var onSrcChange = function (evt, editor) {
    805       var srcURL, prependURL, absoluteURLPattern;
    806       var meta = evt.meta || {};
    807       var control = evt.control;
    808       var rootControl = control.rootControl;
    809       var imageListCtrl = rootControl.find('#image-list')[0];
    810       if (imageListCtrl) {
    811         imageListCtrl.value(editor.convertURL(control.value(), 'src'));
    812       }
    813       global$2.each(meta, function (value, key) {
    814         rootControl.find('#' + key).value(value);
    815       });
    816       if (!meta.width && !meta.height) {
    817         srcURL = editor.convertURL(control.value(), 'src');
    818         prependURL = Settings.getPrependUrl(editor);
    819         absoluteURLPattern = new RegExp('^(?:[a-z]+:)?//', 'i');
    820         if (prependURL && !absoluteURLPattern.test(srcURL) && srcURL.substring(0, prependURL.length) !== prependURL) {
    821           srcURL = prependURL + srcURL;
    822         }
    823         control.value(srcURL);
    824         Utils.getImageSize(editor.documentBaseURI.toAbsolute(control.value()), function (data) {
    825           if (data.width && data.height && Settings.hasDimensions(editor)) {
    826             rootControl.find('#width').value(data.width);
    827             rootControl.find('#height').value(data.height);
    828             SizeManager.syncSize(rootControl);
    829           }
    830         });
    831       }
    832     };
    833     var onBeforeCall = function (evt) {
    834       evt.meta = evt.control.rootControl.toJSON();
    835     };
    836     var getGeneralItems = function (editor, imageListCtrl) {
    837       var generalFormItems = [
    838         {
    839           name: 'src',
    840           type: 'filepicker',
    841           filetype: 'image',
    842           label: 'Source',
    843           autofocus: true,
    844           onchange: function (evt) {
    845             onSrcChange(evt, editor);
    846           },
    847           onbeforecall: onBeforeCall
    848         },
    849         imageListCtrl
    850       ];
    851       if (Settings.hasDescription(editor)) {
    852         generalFormItems.push({
    853           name: 'alt',
    854           type: 'textbox',
    855           label: 'Image description'
    856         });
    857       }
    858       if (Settings.hasImageTitle(editor)) {
    859         generalFormItems.push({
    860           name: 'title',
    861           type: 'textbox',
    862           label: 'Image Title'
    863         });
    864       }
    865       if (Settings.hasDimensions(editor)) {
    866         generalFormItems.push(SizeManager.createUi());
    867       }
    868       if (Settings.getClassList(editor)) {
    869         generalFormItems.push({
    870           name: 'class',
    871           type: 'listbox',
    872           label: 'Class',
    873           values: Utils.buildListItems(Settings.getClassList(editor), function (item) {
    874             if (item.value) {
    875               item.textStyle = function () {
    876                 return editor.formatter.getCssText({
    877                   inline: 'img',
    878                   classes: [item.value]
    879                 });
    880               };
    881             }
    882           })
    883         });
    884       }
    885       if (Settings.hasImageCaption(editor)) {
    886         generalFormItems.push({
    887           name: 'caption',
    888           type: 'checkbox',
    889           label: 'Caption'
    890         });
    891       }
    892       return generalFormItems;
    893     };
    894     var makeTab$1 = function (editor, imageListCtrl) {
    895       return {
    896         title: 'General',
    897         type: 'form',
    898         items: getGeneralItems(editor, imageListCtrl)
    899       };
    900     };
    901     var MainTab = {
    902       makeTab: makeTab$1,
    903       getGeneralItems: getGeneralItems
    904     };
    905 
    906     var url = function () {
    907       return Global$1.getOrDie('URL');
    908     };
    909     var createObjectURL = function (blob) {
    910       return url().createObjectURL(blob);
    911     };
    912     var revokeObjectURL = function (u) {
    913       url().revokeObjectURL(u);
    914     };
    915     var URL = {
    916       createObjectURL: createObjectURL,
    917       revokeObjectURL: revokeObjectURL
    918     };
    919 
    920     var global$5 = tinymce.util.Tools.resolve('tinymce.ui.Factory');
    921 
    922     function XMLHttpRequest () {
    923       var f = Global$1.getOrDie('XMLHttpRequest');
    924       return new f();
    925     }
    926 
    927     var noop = function () {
    928     };
    929     var pathJoin = function (path1, path2) {
    930       if (path1) {
    931         return path1.replace(/\/$/, '') + '/' + path2.replace(/^\//, '');
    932       }
    933       return path2;
    934     };
    935     function Uploader (settings) {
    936       var defaultHandler = function (blobInfo, success, failure, progress) {
    937         var xhr, formData;
    938         xhr = XMLHttpRequest();
    939         xhr.open('POST', settings.url);
    940         xhr.withCredentials = settings.credentials;
    941         xhr.upload.onprogress = function (e) {
    942           progress(e.loaded / e.total * 100);
    943         };
    944         xhr.onerror = function () {
    945           failure('Image upload failed due to a XHR Transport error. Code: ' + xhr.status);
    946         };
    947         xhr.onload = function () {
    948           var json;
    949           if (xhr.status < 200 || xhr.status >= 300) {
    950             failure('HTTP Error: ' + xhr.status);
    951             return;
    952           }
    953           json = JSON.parse(xhr.responseText);
    954           if (!json || typeof json.location !== 'string') {
    955             failure('Invalid JSON: ' + xhr.responseText);
    956             return;
    957           }
    958           success(pathJoin(settings.basePath, json.location));
    959         };
    960         formData = new domGlobals.FormData();
    961         formData.append('file', blobInfo.blob(), blobInfo.filename());
    962         xhr.send(formData);
    963       };
    964       var uploadBlob = function (blobInfo, handler) {
    965         return new global$1(function (resolve, reject) {
    966           try {
    967             handler(blobInfo, resolve, reject, noop);
    968           } catch (ex) {
    969             reject(ex.message);
    970           }
    971         });
    972       };
    973       var isDefaultHandler = function (handler) {
    974         return handler === defaultHandler;
    975       };
    976       var upload = function (blobInfo) {
    977         return !settings.url && isDefaultHandler(settings.handler) ? global$1.reject('Upload url missing from the settings.') : uploadBlob(blobInfo, settings.handler);
    978       };
    979       settings = global$2.extend({
    980         credentials: false,
    981         handler: defaultHandler
    982       }, settings);
    983       return { upload: upload };
    984     }
    985 
    986     var onFileInput = function (editor) {
    987       return function (evt) {
    988         var Throbber = global$5.get('Throbber');
    989         var rootControl = evt.control.rootControl;
    990         var throbber = new Throbber(rootControl.getEl());
    991         var file = evt.control.value();
    992         var blobUri = URL.createObjectURL(file);
    993         var uploader = Uploader({
    994           url: Settings.getUploadUrl(editor),
    995           basePath: Settings.getUploadBasePath(editor),
    996           credentials: Settings.getUploadCredentials(editor),
    997           handler: Settings.getUploadHandler(editor)
    998         });
    999         var finalize = function () {
   1000           throbber.hide();
   1001           URL.revokeObjectURL(blobUri);
   1002         };
   1003         throbber.show();
   1004         return Utils.blobToDataUri(file).then(function (dataUrl) {
   1005           var blobInfo = editor.editorUpload.blobCache.create({
   1006             blob: file,
   1007             blobUri: blobUri,
   1008             name: file.name ? file.name.replace(/\.[^\.]+$/, '') : null,
   1009             base64: dataUrl.split(',')[1]
   1010           });
   1011           return uploader.upload(blobInfo).then(function (url) {
   1012             var src = rootControl.find('#src');
   1013             src.value(url);
   1014             rootControl.find('tabpanel')[0].activateTab(0);
   1015             src.fire('change');
   1016             finalize();
   1017             return url;
   1018           });
   1019         }).catch(function (err) {
   1020           editor.windowManager.alert(err);
   1021           finalize();
   1022         });
   1023       };
   1024     };
   1025     var acceptExts = '.jpg,.jpeg,.png,.gif';
   1026     var makeTab$2 = function (editor) {
   1027       return {
   1028         title: 'Upload',
   1029         type: 'form',
   1030         layout: 'flex',
   1031         direction: 'column',
   1032         align: 'stretch',
   1033         padding: '20 20 20 20',
   1034         items: [
   1035           {
   1036             type: 'container',
   1037             layout: 'flex',
   1038             direction: 'column',
   1039             align: 'center',
   1040             spacing: 10,
   1041             items: [
   1042               {
   1043                 text: 'Browse for an image',
   1044                 type: 'browsebutton',
   1045                 accept: acceptExts,
   1046                 onchange: onFileInput(editor)
   1047               },
   1048               {
   1049                 text: 'OR',
   1050                 type: 'label'
   1051               }
   1052             ]
   1053           },
   1054           {
   1055             text: 'Drop an image here',
   1056             type: 'dropzone',
   1057             accept: acceptExts,
   1058             height: 100,
   1059             onchange: onFileInput(editor)
   1060           }
   1061         ]
   1062       };
   1063     };
   1064     var UploadTab = { makeTab: makeTab$2 };
   1065 
   1066     function curry(fn) {
   1067       var initialArgs = [];
   1068       for (var _i = 1; _i < arguments.length; _i++) {
   1069         initialArgs[_i - 1] = arguments[_i];
   1070       }
   1071       return function () {
   1072         var restArgs = [];
   1073         for (var _i = 0; _i < arguments.length; _i++) {
   1074           restArgs[_i] = arguments[_i];
   1075         }
   1076         var all = initialArgs.concat(restArgs);
   1077         return fn.apply(null, all);
   1078       };
   1079     }
   1080 
   1081     var submitForm = function (editor, evt) {
   1082       var win = evt.control.getRoot();
   1083       SizeManager.updateSize(win);
   1084       editor.undoManager.transact(function () {
   1085         var data = merge(readImageDataFromSelection(editor), win.toJSON());
   1086         insertOrUpdateImage(editor, data);
   1087       });
   1088       editor.editorUpload.uploadImagesAuto();
   1089     };
   1090     function Dialog (editor) {
   1091       function showDialog(imageList) {
   1092         var data = readImageDataFromSelection(editor);
   1093         var win, imageListCtrl;
   1094         if (imageList) {
   1095           imageListCtrl = {
   1096             type: 'listbox',
   1097             label: 'Image list',
   1098             name: 'image-list',
   1099             values: Utils.buildListItems(imageList, function (item) {
   1100               item.value = editor.convertURL(item.value || item.url, 'src');
   1101             }, [{
   1102                 text: 'None',
   1103                 value: ''
   1104               }]),
   1105             value: data.src && editor.convertURL(data.src, 'src'),
   1106             onselect: function (e) {
   1107               var altCtrl = win.find('#alt');
   1108               if (!altCtrl.value() || e.lastControl && altCtrl.value() === e.lastControl.text()) {
   1109                 altCtrl.value(e.control.text());
   1110               }
   1111               win.find('#src').value(e.control.value()).fire('change');
   1112             },
   1113             onPostRender: function () {
   1114               imageListCtrl = this;
   1115             }
   1116           };
   1117         }
   1118         if (Settings.hasAdvTab(editor) || Settings.hasUploadUrl(editor) || Settings.hasUploadHandler(editor)) {
   1119           var body = [MainTab.makeTab(editor, imageListCtrl)];
   1120           if (Settings.hasAdvTab(editor)) {
   1121             body.push(AdvTab.makeTab(editor));
   1122           }
   1123           if (Settings.hasUploadUrl(editor) || Settings.hasUploadHandler(editor)) {
   1124             body.push(UploadTab.makeTab(editor));
   1125           }
   1126           win = editor.windowManager.open({
   1127             title: 'Insert/edit image',
   1128             data: data,
   1129             bodyType: 'tabpanel',
   1130             body: body,
   1131             onSubmit: curry(submitForm, editor)
   1132           });
   1133         } else {
   1134           win = editor.windowManager.open({
   1135             title: 'Insert/edit image',
   1136             data: data,
   1137             body: MainTab.getGeneralItems(editor, imageListCtrl),
   1138             onSubmit: curry(submitForm, editor)
   1139           });
   1140         }
   1141         SizeManager.syncSize(win);
   1142       }
   1143       function open() {
   1144         Utils.createImageList(editor, showDialog);
   1145       }
   1146       return { open: open };
   1147     }
   1148 
   1149     var register = function (editor) {
   1150       editor.addCommand('mceImage', Dialog(editor).open);
   1151     };
   1152     var Commands = { register: register };
   1153 
   1154     var hasImageClass = function (node) {
   1155       var className = node.attr('class');
   1156       return className && /\bimage\b/.test(className);
   1157     };
   1158     var toggleContentEditableState = function (state) {
   1159       return function (nodes) {
   1160         var i = nodes.length, node;
   1161         var toggleContentEditable = function (node) {
   1162           node.attr('contenteditable', state ? 'true' : null);
   1163         };
   1164         while (i--) {
   1165           node = nodes[i];
   1166           if (hasImageClass(node)) {
   1167             node.attr('contenteditable', state ? 'false' : null);
   1168             global$2.each(node.getAll('figcaption'), toggleContentEditable);
   1169           }
   1170         }
   1171       };
   1172     };
   1173     var setup = function (editor) {
   1174       editor.on('preInit', function () {
   1175         editor.parser.addNodeFilter('figure', toggleContentEditableState(true));
   1176         editor.serializer.addNodeFilter('figure', toggleContentEditableState(false));
   1177       });
   1178     };
   1179     var FilterContent = { setup: setup };
   1180 
   1181     var register$1 = function (editor) {
   1182       editor.addButton('image', {
   1183         icon: 'image',
   1184         tooltip: 'Insert/edit image',
   1185         onclick: Dialog(editor).open,
   1186         stateSelector: 'img:not([data-mce-object],[data-mce-placeholder]),figure.image'
   1187       });
   1188       editor.addMenuItem('image', {
   1189         icon: 'image',
   1190         text: 'Image',
   1191         onclick: Dialog(editor).open,
   1192         context: 'insert',
   1193         prependToContext: true
   1194       });
   1195     };
   1196     var Buttons = { register: register$1 };
   1197 
   1198     global.add('image', function (editor) {
   1199       FilterContent.setup(editor);
   1200       Buttons.register(editor);
   1201       Commands.register(editor);
   1202     });
   1203     function Plugin () {
   1204     }
   1205 
   1206     return Plugin;
   1207 
   1208 }(window));
   1209 })();