diff --git a/lib/editor/atto/plugins/image/styles.css b/lib/editor/atto/plugins/image/styles.css index 95a6b9769fd..4d455831966 100644 --- a/lib/editor/atto/plugins/image/styles.css +++ b/lib/editor/atto/plugins/image/styles.css @@ -27,3 +27,36 @@ .atto_image_size label { display: inline-block; } + +.atto_image_button_text-top { + vertical-align: text-top; + margin: 0 0.5em; +} + +.atto_image_button_middle { + vertical-align: middle; + margin: 0 0.5em; +} + +.atto_image_button_text-bottom { + vertical-align: text-bottom; + margin: 0 0.5em; +} + +.atto_image_button_text-top.img-responsive, +.atto_image_button_middle.img-responsive, +.atto_image_button_text-bottom.img-responsive { + max-width: calc(100% - 1em); +} + +.atto_image_button_left { + float: left; + margin: 0 0.5em 0 0; + max-width: calc(100% - 1em); +} + +.atto_image_button_right { + float: right; + margin: 0 0 0 0.5em; + max-width: calc(100% - 1em); +} diff --git a/lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button-debug.js b/lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button-debug.js index c0493175056..89ce285e708 100644 --- a/lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button-debug.js +++ b/lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button-debug.js @@ -48,7 +48,8 @@ var CSS = { INPUTCONSTRAIN: 'atto_image_constrain', INPUTCUSTOMSTYLE: 'atto_image_customstyle', IMAGEPREVIEW: 'atto_image_preview', - IMAGEPREVIEWBOX: 'atto_image_preview_box' + IMAGEPREVIEWBOX: 'atto_image_preview_box', + ALIGNSETTINGS: 'atto_image_button' }, SELECTORS = { INPUTURL: '.' + CSS.INPUTURL @@ -56,38 +57,34 @@ var CSS = { ALIGNMENTS = [ // Vertical alignment. { - name: 'text-top', + name: 'verticalAlign', str: 'alignment_top', - value: 'vertical-align', - margin: '0 .5em' + value: 'text-top', + margin: '0 0.5em' }, { - name: 'middle', + name: 'verticalAlign', str: 'alignment_middle', - value: 'vertical-align', - margin: '0 .5em' + value: 'middle', + margin: '0 0.5em' }, { - name: 'text-bottom', + name: 'verticalAlign', str: 'alignment_bottom', - value: 'vertical-align', - margin: '0 .5em', + value: 'text-bottom', + margin: '0 0.5em', isDefault: true }, // Floats. { - name: 'left', + name: 'float', str: 'alignment_left', - value: 'float', - margin: '0 .5em 0 0' + value: 'left', + margin: '0 0.5em 0 0' }, { - name: 'right', + name: 'float', str: 'alignment_right', - value: 'float', - margin: '0 0 0 .5em' - }, { - name: 'customstyle', - str: 'customstyle', - value: 'style' + value: 'right', + margin: '0 0 0 0.5em' } ], @@ -142,7 +139,7 @@ var CSS = { '' + '' + // Hidden input to store custom styles. @@ -165,7 +162,7 @@ var CSS = { '{{#if width}}width="{{width}}" {{/if}}' + '{{#if height}}height="{{height}}" {{/if}}' + '{{#if presentation}}role="presentation" {{/if}}' + - 'style="{{alignment}}{{margin}}{{customstyle}}"' + + '{{#if customstyle}}style="{{customstyle}}" {{/if}}' + '{{#if classlist}}class="{{classlist}}" {{/if}}' + '{{#if id}}id="{{id}}" {{/if}}' + '/>'; @@ -230,6 +227,7 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi * * @method _handleDragDrop * @param {EventFacade} e + * @return mixed * @private */ _handleDragDrop: function(e) { @@ -642,30 +640,25 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi */ _applyImageProperties: function(form) { var properties = this._getSelectedImageProperties(), - img = form.one('.' + CSS.IMAGEPREVIEW), - i, - css; + img = form.one('.' + CSS.IMAGEPREVIEW); if (properties === false) { img.setStyle('display', 'none'); // Set the default alignment. - for (i in ALIGNMENTS) { - if (ALIGNMENTS[i].isDefault === true) { - css = ALIGNMENTS[i].value + ':' + ALIGNMENTS[i].name + ';'; - form.one('.' + CSS.INPUTALIGNMENT).set('value', css); + ALIGNMENTS.some(function(alignment) { + if (alignment.isDefault) { + form.one('.' + CSS.INPUTALIGNMENT).set('value', alignment.value); + return true; } - } - // Remove the custom style option if this is a new image. - form.one('.' + CSS.INPUTALIGNMENT).getDOMNode().options.remove(ALIGNMENTS.length - 1); + + return false; + }, this); + return; } if (properties.align) { form.one('.' + CSS.INPUTALIGNMENT).set('value', properties.align); - // Remove the custom style option if we have a standard alignment. - form.one('.' + CSS.INPUTALIGNMENT).getDOMNode().options.remove(ALIGNMENTS.length - 1); - } else { - form.one('.' + CSS.INPUTALIGNMENT).set('value', 'style:customstyle;'); } if (properties.customstyle) { form.one('.' + CSS.INPUTCUSTOMSTYLE).set('value', properties.customstyle); @@ -712,25 +705,21 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi // Get the current selection. images = this.get('host').getSelectedNodes(), - i, width, height, style, - css, - image, - margin; + image; if (images) { images = images.filter('img'); } if (images && images.size()) { - image = images.item(0); + image = this._removeLegacyAlignment(images.item(0)); this._selectedImage = image; style = image.getAttribute('style'); properties.customstyle = style; - style = style.replace(/ /g, ''); width = image.getAttribute('width'); if (!width.match(REGEX.ISPERCENT)) { @@ -747,18 +736,7 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi if (height !== 0) { properties.height = height; } - for (i in ALIGNMENTS) { - css = ALIGNMENTS[i].value + ':' + ALIGNMENTS[i].name + ';'; - if (style.indexOf(css) !== -1) { - margin = 'margin:' + ALIGNMENTS[i].margin + ';'; - margin = margin.replace(/ /g, ''); - // Must match alignment and margins - otherwise custom style is selected. - if (style.indexOf(margin) !== -1) { - properties.align = css; - break; - } - } - } + this._getAlignmentPropeties(image, properties); properties.src = image.getAttribute('src'); properties.alt = image.getAttribute('alt') || ''; properties.presentation = (image.get('role') === 'presentation'); @@ -770,6 +748,40 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi return false; }, + /** + * Sets the alignment of a properties object. + * + * @method _getAlignmentPropeties + * @param {Node} image The image that the alignment properties should be found for + * @param {Object} properties The properties object that is created in _getSelectedImageProperties() + * @private + */ + _getAlignmentPropeties: function(image, properties) { + var complete = false, + defaultAlignment; + + // Check for an alignment value. + complete = ALIGNMENTS.some(function(alignment) { + var classname = this._getAlignmentClass(alignment.value); + if (image.hasClass(classname)) { + properties.align = alignment.value; + Y.log('Found alignment ' + alignment.value, 'debug', 'atto_image-button'); + + return true; + } + + if (alignment.isDefault) { + defaultAlignment = alignment.value; + } + + return false; + }, this); + + if (!complete && defaultAlignment) { + properties.align = defaultAlignment; + } + }, + /** * Update the form when the URL was changed. This includes updating the * height, width, and image preview. @@ -799,14 +811,11 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi alt = form.one('.' + CSS.INPUTALT).get('value'), width = form.one('.' + CSS.INPUTWIDTH).get('value'), height = form.one('.' + CSS.INPUTHEIGHT).get('value'), - alignment = form.one('.' + CSS.INPUTALIGNMENT).get('value'), - margin = '', + alignment = this._getAlignmentClass(form.one('.' + CSS.INPUTALIGNMENT).get('value')), presentation = form.one('.' + CSS.IMAGEPRESENTATION).get('checked'), constrain = form.one('.' + CSS.INPUTCONSTRAIN).get('checked'), imagehtml, - customstyle = '', - i, - css, + customstyle = form.one('.' + CSS.INPUTCUSTOMSTYLE).get('value'), classlist = [], host = this.get('host'); @@ -826,22 +835,13 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi host.setSelection(this._currentSelection); } - if (alignment === 'style:customstyle;') { - alignment = ''; - customstyle = form.one('.' + CSS.INPUTCUSTOMSTYLE).get('value'); - } else { - for (i in ALIGNMENTS) { - css = ALIGNMENTS[i].value + ':' + ALIGNMENTS[i].name + ';'; - if (alignment === css) { - margin = ' margin: ' + ALIGNMENTS[i].margin + ';'; - } - } - } - if (constrain) { classlist.push(CSS.RESPONSIVE); } + // Add the alignment class for the image. + classlist.push(alignment); + if (!width.match(REGEX.ISPERCENT) && isNaN(parseInt(width, 10))) { form.one('.' + CSS.INPUTWIDTH).focus(); return; @@ -858,8 +858,6 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi width: width, height: height, presentation: presentation, - alignment: alignment, - margin: margin, customstyle: customstyle, classlist: classlist.join(' ') }); @@ -875,6 +873,48 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi }, + /** + * Removes any legacy styles added by previous versions of the atto image button. + * + * @method _removeLegacyAlignment + * @param {Y.Node} imageNode + * @return {Y.Node} + * @private + */ + _removeLegacyAlignment: function(imageNode) { + if (!imageNode.getStyle('margin')) { + // There is no margin therefore this cannot match any known alignments. + return imageNode; + } + + ALIGNMENTS.some(function(alignment) { + if (imageNode.getStyle(alignment.name) !== alignment.value) { + // The name/value do not match. Skip. + return false; + } + + var normalisedNode = Y.Node.create('
'); + normalisedNode.setStyle('margin', alignment.margin); + if (imageNode.getStyle('margin') !== normalisedNode.getStyle('margin')) { + // The margin does not match. + return false; + } + + Y.log('Legacy alignment found and removed.', 'info', 'atto_image-button'); + imageNode.addClass(this._getAlignmentClass(alignment.value)); + imageNode.setStyle(alignment.name, null); + imageNode.setStyle('margin', null); + + return true; + }, this); + + return imageNode; + }, + + _getAlignmentClass: function(alignment) { + return CSS.ALIGNSETTINGS + '_' + alignment; + }, + /** * Update the alt text warning live. * diff --git a/lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button-min.js b/lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button-min.js index a973de75067..78edf53af19 100644 --- a/lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button-min.js +++ b/lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button-min.js @@ -1,3 +1,3 @@ -YUI.add("moodle-atto_image-button",function(e,t){var n={RESPONSIVE:"img-responsive",INPUTALIGNMENT:"atto_image_alignment",INPUTALT:"atto_image_altentry",INPUTHEIGHT:"atto_image_heightentry",INPUTSUBMIT:"atto_image_urlentrysubmit",INPUTURL:"atto_image_urlentry",INPUTSIZE:"atto_image_size",INPUTWIDTH:"atto_image_widthentry",IMAGEALTWARNING:"atto_image_altwarning",IMAGEBROWSER:"openimagebrowser",IMAGEPRESENTATION:"atto_image_presentation",INPUTCONSTRAIN:"atto_image_constrain",INPUTCUSTOMSTYLE:"atto_image_customstyle",IMAGEPREVIEW:"atto_image_preview",IMAGEPREVIEWBOX:"atto_image_preview_box"},r={INPUTURL:"."+n.INPUTURL},i=[{name:"text-top",str:"alignment_top",value:"vertical-align",margin:"0 .5em"},{name:"middle",str:"alignment_middle",value:"vertical-align",margin:"0 .5em"},{name:"text-bottom",str:"alignment_bottom",value:"vertical-align",margin:"0 .5em",isDefault:!0},{name:"left",str:"alignment_left",value:"float",margin:"0 .5em 0 0"},{name:"right",str:"alignment_right",value:"float",margin:"0 0 0 .5em"},{name:"customstyle",str:"customstyle",value:"style"}],s={ISPERCENT:/\d+%/},o="atto_image",u='

{{#if showFilepicker}}{{/if}}

x

',a='{{alt}}';e.namespace("M.atto_image").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{_currentSelection:null,_selectedImage:null,_form:null,_rawImageDimensions:null,initializer:function(){this.addButton({icon:"e/insert_edit_image",callback:this._displayDialogue,tags:"img",tagMatchRequiresAll:!1}),this.editor.delegate("dblclick",this._displayDialogue,"img",this),this.editor.delegate("click",this._handleClick,"img",this),this.editor.on("drop",this._handleDragDrop,this),this.editor.on("dragover",function(e){e.preventDefault()},this),this.editor.on("dragenter",function(e){e.preventDefault()},this)},_handleDragDrop:function(t){var n=this,r=this.get("host"),i=e.Handlebars.compile(a);r.saveSelection(),t=t._event;var s=t.dataTransfer&&t.dataTransfer.files&&t.dataTransfer.files.length;if(s&&/^image\//.test(t.dataTransfer.files[0].type)){var u=r.get("filepickeroptions").image,f=u.savepath===undefined?"/":u.savepath,l=new FormData,c=0,h="",p=new XMLHttpRequest,d="",v=Object.keys(u.repositories);t.preventDefault(),t.stopPropagation(),l.append("repo_upload_file",t.dataTransfer.files[0]),l.append("itemid",u.itemid);for(var m=0;m
{{#if showFilepicker}}{{/if}}

x

',a='{{alt}}';e.namespace("M.atto_image").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{_currentSelection:null,_selectedImage:null,_form:null,_rawImageDimensions:null,initializer:function(){this.addButton({icon:"e/insert_edit_image",callback:this._displayDialogue,tags:"img",tagMatchRequiresAll:!1}),this.editor.delegate("dblclick",this._displayDialogue,"img",this),this.editor.delegate("click",this._handleClick,"img",this),this.editor.on("drop",this._handleDragDrop,this),this.editor.on("dragover",function(e){e.preventDefault()},this),this.editor.on("dragenter",function(e){e.preventDefault()},this)},_handleDragDrop:function(t){var n=this,r=this.get("host"),i=e.Handlebars.compile(a);r.saveSelection(),t=t._event;var s=t.dataTransfer&&t.dataTransfer.files&&t.dataTransfer.files.length;if(s&&/^image\//.test(t.dataTransfer.files[0].type)){var u=r.get("filepickeroptions").image,f=u.savepath===undefined?"/":u.savepath,l=new FormData,c=0,h="",p=new XMLHttpRequest,d="",v=Object.keys(u.repositories);t.preventDefault(),t.stopPropagation(),l.append("repo_upload_file",t.dataTransfer.files[0]),l.append("itemid",u.itemid);for(var m=0;m");return r.setStyle("margin",n.margin),t.getStyle("margin")!==r.getStyle("margin")?!1:(t.addClass(this._getAlignmentClass(n.value)),t.setStyle(n.name,null),t.setStyle("margin",null),!0)},this),t):t},_getAlignmentClass:function(e){return n.ALIGNSETTINGS+"_"+e},_updateWarning:function(){var e=this._form,t=!0,r=e.one("."+n.INPUTALT).get("value"),i=e.one("."+n.IMAGEPRESENTATION).get("checked");return r===""&&!i?(e.one("."+n.IMAGEALTWARNING).setStyle("display","block"),e.one("."+n.INPUTALT).setAttribute("aria-invalid",!0),e.one("."+n.IMAGEPRESENTATION).setAttribute("aria-invalid",!0),t=!0):(e.one("."+n.IMAGEALTWARNING).setStyle("display","none"),e.one("."+n.INPUTALT).setAttribute("aria-invalid",!1),e.one("."+n.IMAGEPRESENTATION).setAttribute("aria-invalid",!1),t=!1),this.getDialogue().centerDialogue(),t}})},"@VERSION@",{requires:["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button.js b/lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button.js index c0493175056..1cf57d06852 100644 --- a/lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button.js +++ b/lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button.js @@ -48,7 +48,8 @@ var CSS = { INPUTCONSTRAIN: 'atto_image_constrain', INPUTCUSTOMSTYLE: 'atto_image_customstyle', IMAGEPREVIEW: 'atto_image_preview', - IMAGEPREVIEWBOX: 'atto_image_preview_box' + IMAGEPREVIEWBOX: 'atto_image_preview_box', + ALIGNSETTINGS: 'atto_image_button' }, SELECTORS = { INPUTURL: '.' + CSS.INPUTURL @@ -56,38 +57,34 @@ var CSS = { ALIGNMENTS = [ // Vertical alignment. { - name: 'text-top', + name: 'verticalAlign', str: 'alignment_top', - value: 'vertical-align', - margin: '0 .5em' + value: 'text-top', + margin: '0 0.5em' }, { - name: 'middle', + name: 'verticalAlign', str: 'alignment_middle', - value: 'vertical-align', - margin: '0 .5em' + value: 'middle', + margin: '0 0.5em' }, { - name: 'text-bottom', + name: 'verticalAlign', str: 'alignment_bottom', - value: 'vertical-align', - margin: '0 .5em', + value: 'text-bottom', + margin: '0 0.5em', isDefault: true }, // Floats. { - name: 'left', + name: 'float', str: 'alignment_left', - value: 'float', - margin: '0 .5em 0 0' + value: 'left', + margin: '0 0.5em 0 0' }, { - name: 'right', + name: 'float', str: 'alignment_right', - value: 'float', - margin: '0 0 0 .5em' - }, { - name: 'customstyle', - str: 'customstyle', - value: 'style' + value: 'right', + margin: '0 0 0 0.5em' } ], @@ -142,7 +139,7 @@ var CSS = { '' + '' + // Hidden input to store custom styles. @@ -165,7 +162,7 @@ var CSS = { '{{#if width}}width="{{width}}" {{/if}}' + '{{#if height}}height="{{height}}" {{/if}}' + '{{#if presentation}}role="presentation" {{/if}}' + - 'style="{{alignment}}{{margin}}{{customstyle}}"' + + '{{#if customstyle}}style="{{customstyle}}" {{/if}}' + '{{#if classlist}}class="{{classlist}}" {{/if}}' + '{{#if id}}id="{{id}}" {{/if}}' + '/>'; @@ -230,6 +227,7 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi * * @method _handleDragDrop * @param {EventFacade} e + * @return mixed * @private */ _handleDragDrop: function(e) { @@ -642,30 +640,25 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi */ _applyImageProperties: function(form) { var properties = this._getSelectedImageProperties(), - img = form.one('.' + CSS.IMAGEPREVIEW), - i, - css; + img = form.one('.' + CSS.IMAGEPREVIEW); if (properties === false) { img.setStyle('display', 'none'); // Set the default alignment. - for (i in ALIGNMENTS) { - if (ALIGNMENTS[i].isDefault === true) { - css = ALIGNMENTS[i].value + ':' + ALIGNMENTS[i].name + ';'; - form.one('.' + CSS.INPUTALIGNMENT).set('value', css); + ALIGNMENTS.some(function(alignment) { + if (alignment.isDefault) { + form.one('.' + CSS.INPUTALIGNMENT).set('value', alignment.value); + return true; } - } - // Remove the custom style option if this is a new image. - form.one('.' + CSS.INPUTALIGNMENT).getDOMNode().options.remove(ALIGNMENTS.length - 1); + + return false; + }, this); + return; } if (properties.align) { form.one('.' + CSS.INPUTALIGNMENT).set('value', properties.align); - // Remove the custom style option if we have a standard alignment. - form.one('.' + CSS.INPUTALIGNMENT).getDOMNode().options.remove(ALIGNMENTS.length - 1); - } else { - form.one('.' + CSS.INPUTALIGNMENT).set('value', 'style:customstyle;'); } if (properties.customstyle) { form.one('.' + CSS.INPUTCUSTOMSTYLE).set('value', properties.customstyle); @@ -712,25 +705,21 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi // Get the current selection. images = this.get('host').getSelectedNodes(), - i, width, height, style, - css, - image, - margin; + image; if (images) { images = images.filter('img'); } if (images && images.size()) { - image = images.item(0); + image = this._removeLegacyAlignment(images.item(0)); this._selectedImage = image; style = image.getAttribute('style'); properties.customstyle = style; - style = style.replace(/ /g, ''); width = image.getAttribute('width'); if (!width.match(REGEX.ISPERCENT)) { @@ -747,18 +736,7 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi if (height !== 0) { properties.height = height; } - for (i in ALIGNMENTS) { - css = ALIGNMENTS[i].value + ':' + ALIGNMENTS[i].name + ';'; - if (style.indexOf(css) !== -1) { - margin = 'margin:' + ALIGNMENTS[i].margin + ';'; - margin = margin.replace(/ /g, ''); - // Must match alignment and margins - otherwise custom style is selected. - if (style.indexOf(margin) !== -1) { - properties.align = css; - break; - } - } - } + this._getAlignmentPropeties(image, properties); properties.src = image.getAttribute('src'); properties.alt = image.getAttribute('alt') || ''; properties.presentation = (image.get('role') === 'presentation'); @@ -770,6 +748,39 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi return false; }, + /** + * Sets the alignment of a properties object. + * + * @method _getAlignmentPropeties + * @param {Node} image The image that the alignment properties should be found for + * @param {Object} properties The properties object that is created in _getSelectedImageProperties() + * @private + */ + _getAlignmentPropeties: function(image, properties) { + var complete = false, + defaultAlignment; + + // Check for an alignment value. + complete = ALIGNMENTS.some(function(alignment) { + var classname = this._getAlignmentClass(alignment.value); + if (image.hasClass(classname)) { + properties.align = alignment.value; + + return true; + } + + if (alignment.isDefault) { + defaultAlignment = alignment.value; + } + + return false; + }, this); + + if (!complete && defaultAlignment) { + properties.align = defaultAlignment; + } + }, + /** * Update the form when the URL was changed. This includes updating the * height, width, and image preview. @@ -799,14 +810,11 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi alt = form.one('.' + CSS.INPUTALT).get('value'), width = form.one('.' + CSS.INPUTWIDTH).get('value'), height = form.one('.' + CSS.INPUTHEIGHT).get('value'), - alignment = form.one('.' + CSS.INPUTALIGNMENT).get('value'), - margin = '', + alignment = this._getAlignmentClass(form.one('.' + CSS.INPUTALIGNMENT).get('value')), presentation = form.one('.' + CSS.IMAGEPRESENTATION).get('checked'), constrain = form.one('.' + CSS.INPUTCONSTRAIN).get('checked'), imagehtml, - customstyle = '', - i, - css, + customstyle = form.one('.' + CSS.INPUTCUSTOMSTYLE).get('value'), classlist = [], host = this.get('host'); @@ -826,22 +834,13 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi host.setSelection(this._currentSelection); } - if (alignment === 'style:customstyle;') { - alignment = ''; - customstyle = form.one('.' + CSS.INPUTCUSTOMSTYLE).get('value'); - } else { - for (i in ALIGNMENTS) { - css = ALIGNMENTS[i].value + ':' + ALIGNMENTS[i].name + ';'; - if (alignment === css) { - margin = ' margin: ' + ALIGNMENTS[i].margin + ';'; - } - } - } - if (constrain) { classlist.push(CSS.RESPONSIVE); } + // Add the alignment class for the image. + classlist.push(alignment); + if (!width.match(REGEX.ISPERCENT) && isNaN(parseInt(width, 10))) { form.one('.' + CSS.INPUTWIDTH).focus(); return; @@ -858,8 +857,6 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi width: width, height: height, presentation: presentation, - alignment: alignment, - margin: margin, customstyle: customstyle, classlist: classlist.join(' ') }); @@ -875,6 +872,47 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi }, + /** + * Removes any legacy styles added by previous versions of the atto image button. + * + * @method _removeLegacyAlignment + * @param {Y.Node} imageNode + * @return {Y.Node} + * @private + */ + _removeLegacyAlignment: function(imageNode) { + if (!imageNode.getStyle('margin')) { + // There is no margin therefore this cannot match any known alignments. + return imageNode; + } + + ALIGNMENTS.some(function(alignment) { + if (imageNode.getStyle(alignment.name) !== alignment.value) { + // The name/value do not match. Skip. + return false; + } + + var normalisedNode = Y.Node.create('
'); + normalisedNode.setStyle('margin', alignment.margin); + if (imageNode.getStyle('margin') !== normalisedNode.getStyle('margin')) { + // The margin does not match. + return false; + } + + imageNode.addClass(this._getAlignmentClass(alignment.value)); + imageNode.setStyle(alignment.name, null); + imageNode.setStyle('margin', null); + + return true; + }, this); + + return imageNode; + }, + + _getAlignmentClass: function(alignment) { + return CSS.ALIGNSETTINGS + '_' + alignment; + }, + /** * Update the alt text warning live. * diff --git a/lib/editor/atto/plugins/image/yui/src/button/js/button.js b/lib/editor/atto/plugins/image/yui/src/button/js/button.js index f59848de497..7a8f82d799c 100644 --- a/lib/editor/atto/plugins/image/yui/src/button/js/button.js +++ b/lib/editor/atto/plugins/image/yui/src/button/js/button.js @@ -46,7 +46,8 @@ var CSS = { INPUTCONSTRAIN: 'atto_image_constrain', INPUTCUSTOMSTYLE: 'atto_image_customstyle', IMAGEPREVIEW: 'atto_image_preview', - IMAGEPREVIEWBOX: 'atto_image_preview_box' + IMAGEPREVIEWBOX: 'atto_image_preview_box', + ALIGNSETTINGS: 'atto_image_button' }, SELECTORS = { INPUTURL: '.' + CSS.INPUTURL @@ -54,38 +55,34 @@ var CSS = { ALIGNMENTS = [ // Vertical alignment. { - name: 'text-top', + name: 'verticalAlign', str: 'alignment_top', - value: 'vertical-align', - margin: '0 .5em' + value: 'text-top', + margin: '0 0.5em' }, { - name: 'middle', + name: 'verticalAlign', str: 'alignment_middle', - value: 'vertical-align', - margin: '0 .5em' + value: 'middle', + margin: '0 0.5em' }, { - name: 'text-bottom', + name: 'verticalAlign', str: 'alignment_bottom', - value: 'vertical-align', - margin: '0 .5em', + value: 'text-bottom', + margin: '0 0.5em', isDefault: true }, // Floats. { - name: 'left', + name: 'float', str: 'alignment_left', - value: 'float', - margin: '0 .5em 0 0' + value: 'left', + margin: '0 0.5em 0 0' }, { - name: 'right', + name: 'float', str: 'alignment_right', - value: 'float', - margin: '0 0 0 .5em' - }, { - name: 'customstyle', - str: 'customstyle', - value: 'style' + value: 'right', + margin: '0 0 0 0.5em' } ], @@ -140,7 +137,7 @@ var CSS = { '' + '' + // Hidden input to store custom styles. @@ -163,7 +160,7 @@ var CSS = { '{{#if width}}width="{{width}}" {{/if}}' + '{{#if height}}height="{{height}}" {{/if}}' + '{{#if presentation}}role="presentation" {{/if}}' + - 'style="{{alignment}}{{margin}}{{customstyle}}"' + + '{{#if customstyle}}style="{{customstyle}}" {{/if}}' + '{{#if classlist}}class="{{classlist}}" {{/if}}' + '{{#if id}}id="{{id}}" {{/if}}' + '/>'; @@ -228,6 +225,7 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi * * @method _handleDragDrop * @param {EventFacade} e + * @return mixed * @private */ _handleDragDrop: function(e) { @@ -640,30 +638,25 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi */ _applyImageProperties: function(form) { var properties = this._getSelectedImageProperties(), - img = form.one('.' + CSS.IMAGEPREVIEW), - i, - css; + img = form.one('.' + CSS.IMAGEPREVIEW); if (properties === false) { img.setStyle('display', 'none'); // Set the default alignment. - for (i in ALIGNMENTS) { - if (ALIGNMENTS[i].isDefault === true) { - css = ALIGNMENTS[i].value + ':' + ALIGNMENTS[i].name + ';'; - form.one('.' + CSS.INPUTALIGNMENT).set('value', css); + ALIGNMENTS.some(function(alignment) { + if (alignment.isDefault) { + form.one('.' + CSS.INPUTALIGNMENT).set('value', alignment.value); + return true; } - } - // Remove the custom style option if this is a new image. - form.one('.' + CSS.INPUTALIGNMENT).getDOMNode().options.remove(ALIGNMENTS.length - 1); + + return false; + }, this); + return; } if (properties.align) { form.one('.' + CSS.INPUTALIGNMENT).set('value', properties.align); - // Remove the custom style option if we have a standard alignment. - form.one('.' + CSS.INPUTALIGNMENT).getDOMNode().options.remove(ALIGNMENTS.length - 1); - } else { - form.one('.' + CSS.INPUTALIGNMENT).set('value', 'style:customstyle;'); } if (properties.customstyle) { form.one('.' + CSS.INPUTCUSTOMSTYLE).set('value', properties.customstyle); @@ -710,25 +703,21 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi // Get the current selection. images = this.get('host').getSelectedNodes(), - i, width, height, style, - css, - image, - margin; + image; if (images) { images = images.filter('img'); } if (images && images.size()) { - image = images.item(0); + image = this._removeLegacyAlignment(images.item(0)); this._selectedImage = image; style = image.getAttribute('style'); properties.customstyle = style; - style = style.replace(/ /g, ''); width = image.getAttribute('width'); if (!width.match(REGEX.ISPERCENT)) { @@ -745,18 +734,7 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi if (height !== 0) { properties.height = height; } - for (i in ALIGNMENTS) { - css = ALIGNMENTS[i].value + ':' + ALIGNMENTS[i].name + ';'; - if (style.indexOf(css) !== -1) { - margin = 'margin:' + ALIGNMENTS[i].margin + ';'; - margin = margin.replace(/ /g, ''); - // Must match alignment and margins - otherwise custom style is selected. - if (style.indexOf(margin) !== -1) { - properties.align = css; - break; - } - } - } + this._getAlignmentPropeties(image, properties); properties.src = image.getAttribute('src'); properties.alt = image.getAttribute('alt') || ''; properties.presentation = (image.get('role') === 'presentation'); @@ -768,6 +746,40 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi return false; }, + /** + * Sets the alignment of a properties object. + * + * @method _getAlignmentPropeties + * @param {Node} image The image that the alignment properties should be found for + * @param {Object} properties The properties object that is created in _getSelectedImageProperties() + * @private + */ + _getAlignmentPropeties: function(image, properties) { + var complete = false, + defaultAlignment; + + // Check for an alignment value. + complete = ALIGNMENTS.some(function(alignment) { + var classname = this._getAlignmentClass(alignment.value); + if (image.hasClass(classname)) { + properties.align = alignment.value; + Y.log('Found alignment ' + alignment.value, 'debug', 'atto_image-button'); + + return true; + } + + if (alignment.isDefault) { + defaultAlignment = alignment.value; + } + + return false; + }, this); + + if (!complete && defaultAlignment) { + properties.align = defaultAlignment; + } + }, + /** * Update the form when the URL was changed. This includes updating the * height, width, and image preview. @@ -797,14 +809,11 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi alt = form.one('.' + CSS.INPUTALT).get('value'), width = form.one('.' + CSS.INPUTWIDTH).get('value'), height = form.one('.' + CSS.INPUTHEIGHT).get('value'), - alignment = form.one('.' + CSS.INPUTALIGNMENT).get('value'), - margin = '', + alignment = this._getAlignmentClass(form.one('.' + CSS.INPUTALIGNMENT).get('value')), presentation = form.one('.' + CSS.IMAGEPRESENTATION).get('checked'), constrain = form.one('.' + CSS.INPUTCONSTRAIN).get('checked'), imagehtml, - customstyle = '', - i, - css, + customstyle = form.one('.' + CSS.INPUTCUSTOMSTYLE).get('value'), classlist = [], host = this.get('host'); @@ -824,22 +833,13 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi host.setSelection(this._currentSelection); } - if (alignment === 'style:customstyle;') { - alignment = ''; - customstyle = form.one('.' + CSS.INPUTCUSTOMSTYLE).get('value'); - } else { - for (i in ALIGNMENTS) { - css = ALIGNMENTS[i].value + ':' + ALIGNMENTS[i].name + ';'; - if (alignment === css) { - margin = ' margin: ' + ALIGNMENTS[i].margin + ';'; - } - } - } - if (constrain) { classlist.push(CSS.RESPONSIVE); } + // Add the alignment class for the image. + classlist.push(alignment); + if (!width.match(REGEX.ISPERCENT) && isNaN(parseInt(width, 10))) { form.one('.' + CSS.INPUTWIDTH).focus(); return; @@ -856,8 +856,6 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi width: width, height: height, presentation: presentation, - alignment: alignment, - margin: margin, customstyle: customstyle, classlist: classlist.join(' ') }); @@ -873,6 +871,48 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi }, + /** + * Removes any legacy styles added by previous versions of the atto image button. + * + * @method _removeLegacyAlignment + * @param {Y.Node} imageNode + * @return {Y.Node} + * @private + */ + _removeLegacyAlignment: function(imageNode) { + if (!imageNode.getStyle('margin')) { + // There is no margin therefore this cannot match any known alignments. + return imageNode; + } + + ALIGNMENTS.some(function(alignment) { + if (imageNode.getStyle(alignment.name) !== alignment.value) { + // The name/value do not match. Skip. + return false; + } + + var normalisedNode = Y.Node.create('
'); + normalisedNode.setStyle('margin', alignment.margin); + if (imageNode.getStyle('margin') !== normalisedNode.getStyle('margin')) { + // The margin does not match. + return false; + } + + Y.log('Legacy alignment found and removed.', 'info', 'atto_image-button'); + imageNode.addClass(this._getAlignmentClass(alignment.value)); + imageNode.setStyle(alignment.name, null); + imageNode.setStyle('margin', null); + + return true; + }, this); + + return imageNode; + }, + + _getAlignmentClass: function(alignment) { + return CSS.ALIGNSETTINGS + '_' + alignment; + }, + /** * Update the alt text warning live. *