MDL-46531 editor_atto: Handle a null selection better on colour change
Sadly, there is no easy way to do this. When a range is empty, we need to create a new span, make the changes there, and then select it. Rangy does not provide a helper to do this yet (will be in 1.3) so we have to do it manually in the mean time.
This commit is contained in:
+32
-6
@@ -74,14 +74,40 @@ Y.namespace('M.atto_backcolor').Button = Y.Base.create('button', Y.M.editor_atto
|
||||
*
|
||||
* @method _changeStyle
|
||||
* @param {EventFacade} e
|
||||
* @param {string} className The class for the new font
|
||||
* @param {string} backColorClass The class for the new font
|
||||
* @private
|
||||
*/
|
||||
_changeStyle: function(e, className) {
|
||||
var id = Y.stamp({});
|
||||
this.get('host').toggleInlineSelectionClass([id]);
|
||||
this.editor.one('.' + id).setAttribute('class', '');
|
||||
this.get('host').toggleInlineSelectionClass([className, 'backcolor']);
|
||||
_changeStyle: function(e, backColorClass) {
|
||||
var host = this.get('host'),
|
||||
classname = host.PLACEHOLDER_CLASS,
|
||||
originalSelection = host.getSelection(),
|
||||
cssApplier = rangy.createCssClassApplier(classname, {normalize: true});
|
||||
|
||||
cssApplier.applyToSelection();
|
||||
|
||||
if (!Y.one('.' + classname)) {
|
||||
// The selection is likely empty. Create an empty span, and focus it.
|
||||
var firstRange = originalSelection[0],
|
||||
fragment = firstRange.createContextualFragment('<span class="' + classname + '"> </span>'),
|
||||
newRange = rangy.createRange(),
|
||||
selection;
|
||||
firstRange.insertNode(fragment.lastChild);
|
||||
firstRange.collapse();
|
||||
|
||||
// Update the originalSelection to point to the newly selected range.
|
||||
newRange.selectNodeContents(Y.one('.' + classname).getDOMNode());
|
||||
selection = rangy.getSelection();
|
||||
selection.setSingleRange(newRange);
|
||||
originalSelection = selection.getAllRanges();
|
||||
}
|
||||
|
||||
this.editor.all('.' + classname).each(function (node) {
|
||||
node.setAttribute('class', 'fontcolor ' + backColorClass);
|
||||
}, this);
|
||||
|
||||
host.setSelection(originalSelection);
|
||||
|
||||
this.markUpdated();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
YUI.add("moodle-atto_backcolor-button",function(e,t){var n=[{name:"white"},{name:"red"},{name:"yellow"},{name:"green"},{name:"blue"},{name:"black"}];e.namespace("M.atto_backcolor").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{initializer:function(){var t=[];e.Array.each(n,function(e){t.push({text:'<div class="'+e.name+'"></div>',callbackArgs:e.className||e.name})}),this.addToolbarMenu({icon:"e/text_highlight",overlayWidth:"4",globalItemConfig:{callback:this._changeStyle},items:t})},_changeStyle:function(t,n){var r=e.stamp({});this.get("host").toggleInlineSelectionClass([r]),this.editor.one("."+r).setAttribute("class",""),this.get("host").toggleInlineSelectionClass([n,"backcolor"])}})},"@VERSION@");
|
||||
YUI.add("moodle-atto_backcolor-button",function(e,t){var n=[{name:"white"},{name:"red"},{name:"yellow"},{name:"green"},{name:"blue"},{name:"black"}];e.namespace("M.atto_backcolor").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{initializer:function(){var t=[];e.Array.each(n,function(e){t.push({text:'<div class="'+e.name+'"></div>',callbackArgs:e.className||e.name})}),this.addToolbarMenu({icon:"e/text_highlight",overlayWidth:"4",globalItemConfig:{callback:this._changeStyle},items:t})},_changeStyle:function(t,n){var r=this.get("host"),i=r.PLACEHOLDER_CLASS,s=r.getSelection(),o=rangy.createCssClassApplier(i,{normalize:!0});o.applyToSelection();if(!e.one("."+i)){var u=s[0],a=u.createContextualFragment('<span class="'+i+'"> </span>'),f=rangy.createRange(),l;u.insertNode(a.lastChild),u.collapse(),f.selectNodeContents(e.one("."+i).getDOMNode()),l=rangy.getSelection(),l.setSingleRange(f),s=l.getAllRanges()}this.editor.all("."+i).each(function(e){e.setAttribute("class","fontcolor "+n)},this),r.setSelection(s),this.markUpdated()}})},"@VERSION@");
|
||||
|
||||
+32
-6
@@ -74,14 +74,40 @@ Y.namespace('M.atto_backcolor').Button = Y.Base.create('button', Y.M.editor_atto
|
||||
*
|
||||
* @method _changeStyle
|
||||
* @param {EventFacade} e
|
||||
* @param {string} className The class for the new font
|
||||
* @param {string} backColorClass The class for the new font
|
||||
* @private
|
||||
*/
|
||||
_changeStyle: function(e, className) {
|
||||
var id = Y.stamp({});
|
||||
this.get('host').toggleInlineSelectionClass([id]);
|
||||
this.editor.one('.' + id).setAttribute('class', '');
|
||||
this.get('host').toggleInlineSelectionClass([className, 'backcolor']);
|
||||
_changeStyle: function(e, backColorClass) {
|
||||
var host = this.get('host'),
|
||||
classname = host.PLACEHOLDER_CLASS,
|
||||
originalSelection = host.getSelection(),
|
||||
cssApplier = rangy.createCssClassApplier(classname, {normalize: true});
|
||||
|
||||
cssApplier.applyToSelection();
|
||||
|
||||
if (!Y.one('.' + classname)) {
|
||||
// The selection is likely empty. Create an empty span, and focus it.
|
||||
var firstRange = originalSelection[0],
|
||||
fragment = firstRange.createContextualFragment('<span class="' + classname + '"> </span>'),
|
||||
newRange = rangy.createRange(),
|
||||
selection;
|
||||
firstRange.insertNode(fragment.lastChild);
|
||||
firstRange.collapse();
|
||||
|
||||
// Update the originalSelection to point to the newly selected range.
|
||||
newRange.selectNodeContents(Y.one('.' + classname).getDOMNode());
|
||||
selection = rangy.getSelection();
|
||||
selection.setSingleRange(newRange);
|
||||
originalSelection = selection.getAllRanges();
|
||||
}
|
||||
|
||||
this.editor.all('.' + classname).each(function (node) {
|
||||
node.setAttribute('class', 'fontcolor ' + backColorClass);
|
||||
}, this);
|
||||
|
||||
host.setSelection(originalSelection);
|
||||
|
||||
this.markUpdated();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -72,13 +72,39 @@ Y.namespace('M.atto_backcolor').Button = Y.Base.create('button', Y.M.editor_atto
|
||||
*
|
||||
* @method _changeStyle
|
||||
* @param {EventFacade} e
|
||||
* @param {string} className The class for the new font
|
||||
* @param {string} backColorClass The class for the new font
|
||||
* @private
|
||||
*/
|
||||
_changeStyle: function(e, className) {
|
||||
var id = Y.stamp({});
|
||||
this.get('host').toggleInlineSelectionClass([id]);
|
||||
this.editor.one('.' + id).setAttribute('class', '');
|
||||
this.get('host').toggleInlineSelectionClass([className, 'backcolor']);
|
||||
_changeStyle: function(e, backColorClass) {
|
||||
var host = this.get('host'),
|
||||
classname = host.PLACEHOLDER_CLASS,
|
||||
originalSelection = host.getSelection(),
|
||||
cssApplier = rangy.createCssClassApplier(classname, {normalize: true});
|
||||
|
||||
cssApplier.applyToSelection();
|
||||
|
||||
if (!Y.one('.' + classname)) {
|
||||
// The selection is likely empty. Create an empty span, and focus it.
|
||||
var firstRange = originalSelection[0],
|
||||
fragment = firstRange.createContextualFragment('<span class="' + classname + '"> </span>'),
|
||||
newRange = rangy.createRange(),
|
||||
selection;
|
||||
firstRange.insertNode(fragment.lastChild);
|
||||
firstRange.collapse();
|
||||
|
||||
// Update the originalSelection to point to the newly selected range.
|
||||
newRange.selectNodeContents(Y.one('.' + classname).getDOMNode());
|
||||
selection = rangy.getSelection();
|
||||
selection.setSingleRange(newRange);
|
||||
originalSelection = selection.getAllRanges();
|
||||
}
|
||||
|
||||
this.editor.all('.' + classname).each(function (node) {
|
||||
node.setAttribute('class', 'fontcolor ' + backColorClass);
|
||||
}, this);
|
||||
|
||||
host.setSelection(originalSelection);
|
||||
|
||||
this.markUpdated();
|
||||
}
|
||||
});
|
||||
|
||||
+32
-6
@@ -76,14 +76,40 @@ Y.namespace('M.atto_fontcolor').Button = Y.Base.create('button', Y.M.editor_atto
|
||||
*
|
||||
* @method _changeStyle
|
||||
* @param {EventFacade} e
|
||||
* @param {string} className The class for the new font
|
||||
* @param {string} fontColorClass The class for the new font
|
||||
* @private
|
||||
*/
|
||||
_changeStyle: function(e, className) {
|
||||
var id = Y.stamp({});
|
||||
this.get('host').toggleInlineSelectionClass([id]);
|
||||
this.editor.one('.' + id).setAttribute('class', '');
|
||||
this.get('host').toggleInlineSelectionClass([className, 'fontcolor']);
|
||||
_changeStyle: function(e, fontColorClass) {
|
||||
var host = this.get('host'),
|
||||
classname = host.PLACEHOLDER_CLASS,
|
||||
originalSelection = host.getSelection(),
|
||||
cssApplier = rangy.createCssClassApplier(classname, {normalize: true});
|
||||
|
||||
cssApplier.applyToSelection();
|
||||
|
||||
if (!Y.one('.' + classname)) {
|
||||
// The selection is likely empty. Create an empty span, and focus it.
|
||||
var firstRange = originalSelection[0],
|
||||
fragment = firstRange.createContextualFragment('<span class="' + classname + '"> </span>'),
|
||||
newRange = rangy.createRange(),
|
||||
selection;
|
||||
firstRange.insertNode(fragment.lastChild);
|
||||
firstRange.collapse();
|
||||
|
||||
// Update the originalSelection to point to the newly selected range.
|
||||
newRange.selectNodeContents(Y.one('.' + classname).getDOMNode());
|
||||
selection = rangy.getSelection();
|
||||
selection.setSingleRange(newRange);
|
||||
originalSelection = selection.getAllRanges();
|
||||
}
|
||||
|
||||
this.editor.all('.' + classname).each(function (node) {
|
||||
node.setAttribute('class', 'fontcolor ' + fontColorClass);
|
||||
}, this);
|
||||
|
||||
host.setSelection(originalSelection);
|
||||
|
||||
this.markUpdated();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
YUI.add("moodle-atto_fontcolor-button",function(e,t){var n=[{name:"white"},{name:"red"},{name:"yellow"},{name:"green"},{name:"blue"},{name:"black"}];e.namespace("M.atto_fontcolor").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{initializer:function(){var t=[];e.Array.each(n,function(e){t.push({text:'<div class="'+e.name+'"></div>',callbackArgs:e.className||e.name,callback:this._changeStyle})}),this.addToolbarMenu({icon:"e/text_color",overlayWidth:"4",menuColor:"#333333",globalItemConfig:{callback:this._changeStyle},items:t})},_changeStyle:function(t,n){var r=e.stamp({});this.get("host").toggleInlineSelectionClass([r]),this.editor.one("."+r).setAttribute("class",""),this.get("host").toggleInlineSelectionClass([n,"fontcolor"])}})},"@VERSION@");
|
||||
YUI.add("moodle-atto_fontcolor-button",function(e,t){var n=[{name:"white"},{name:"red"},{name:"yellow"},{name:"green"},{name:"blue"},{name:"black"}];e.namespace("M.atto_fontcolor").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{initializer:function(){var t=[];e.Array.each(n,function(e){t.push({text:'<div class="'+e.name+'"></div>',callbackArgs:e.className||e.name,callback:this._changeStyle})}),this.addToolbarMenu({icon:"e/text_color",overlayWidth:"4",menuColor:"#333333",globalItemConfig:{callback:this._changeStyle},items:t})},_changeStyle:function(t,n){var r=this.get("host"),i=r.PLACEHOLDER_CLASS,s=r.getSelection(),o=rangy.createCssClassApplier(i,{normalize:!0});o.applyToSelection();if(!e.one("."+i)){var u=s[0],a=u.createContextualFragment('<span class="'+i+'"> </span>'),f=rangy.createRange(),l;u.insertNode(a.lastChild),u.collapse(),f.selectNodeContents(e.one("."+i).getDOMNode()),l=rangy.getSelection(),l.setSingleRange(f),s=l.getAllRanges()}this.editor.all("."+i).each(function(e){e.setAttribute("class","fontcolor "+n)},this),r.setSelection(s),this.markUpdated()}})},"@VERSION@");
|
||||
|
||||
+32
-6
@@ -76,14 +76,40 @@ Y.namespace('M.atto_fontcolor').Button = Y.Base.create('button', Y.M.editor_atto
|
||||
*
|
||||
* @method _changeStyle
|
||||
* @param {EventFacade} e
|
||||
* @param {string} className The class for the new font
|
||||
* @param {string} fontColorClass The class for the new font
|
||||
* @private
|
||||
*/
|
||||
_changeStyle: function(e, className) {
|
||||
var id = Y.stamp({});
|
||||
this.get('host').toggleInlineSelectionClass([id]);
|
||||
this.editor.one('.' + id).setAttribute('class', '');
|
||||
this.get('host').toggleInlineSelectionClass([className, 'fontcolor']);
|
||||
_changeStyle: function(e, fontColorClass) {
|
||||
var host = this.get('host'),
|
||||
classname = host.PLACEHOLDER_CLASS,
|
||||
originalSelection = host.getSelection(),
|
||||
cssApplier = rangy.createCssClassApplier(classname, {normalize: true});
|
||||
|
||||
cssApplier.applyToSelection();
|
||||
|
||||
if (!Y.one('.' + classname)) {
|
||||
// The selection is likely empty. Create an empty span, and focus it.
|
||||
var firstRange = originalSelection[0],
|
||||
fragment = firstRange.createContextualFragment('<span class="' + classname + '"> </span>'),
|
||||
newRange = rangy.createRange(),
|
||||
selection;
|
||||
firstRange.insertNode(fragment.lastChild);
|
||||
firstRange.collapse();
|
||||
|
||||
// Update the originalSelection to point to the newly selected range.
|
||||
newRange.selectNodeContents(Y.one('.' + classname).getDOMNode());
|
||||
selection = rangy.getSelection();
|
||||
selection.setSingleRange(newRange);
|
||||
originalSelection = selection.getAllRanges();
|
||||
}
|
||||
|
||||
this.editor.all('.' + classname).each(function (node) {
|
||||
node.setAttribute('class', 'fontcolor ' + fontColorClass);
|
||||
}, this);
|
||||
|
||||
host.setSelection(originalSelection);
|
||||
|
||||
this.markUpdated();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -74,13 +74,39 @@ Y.namespace('M.atto_fontcolor').Button = Y.Base.create('button', Y.M.editor_atto
|
||||
*
|
||||
* @method _changeStyle
|
||||
* @param {EventFacade} e
|
||||
* @param {string} className The class for the new font
|
||||
* @param {string} fontColorClass The class for the new font
|
||||
* @private
|
||||
*/
|
||||
_changeStyle: function(e, className) {
|
||||
var id = Y.stamp({});
|
||||
this.get('host').toggleInlineSelectionClass([id]);
|
||||
this.editor.one('.' + id).setAttribute('class', '');
|
||||
this.get('host').toggleInlineSelectionClass([className, 'fontcolor']);
|
||||
_changeStyle: function(e, fontColorClass) {
|
||||
var host = this.get('host'),
|
||||
classname = host.PLACEHOLDER_CLASS,
|
||||
originalSelection = host.getSelection(),
|
||||
cssApplier = rangy.createCssClassApplier(classname, {normalize: true});
|
||||
|
||||
cssApplier.applyToSelection();
|
||||
|
||||
if (!Y.one('.' + classname)) {
|
||||
// The selection is likely empty. Create an empty span, and focus it.
|
||||
var firstRange = originalSelection[0],
|
||||
fragment = firstRange.createContextualFragment('<span class="' + classname + '"> </span>'),
|
||||
newRange = rangy.createRange(),
|
||||
selection;
|
||||
firstRange.insertNode(fragment.lastChild);
|
||||
firstRange.collapse();
|
||||
|
||||
// Update the originalSelection to point to the newly selected range.
|
||||
newRange.selectNodeContents(Y.one('.' + classname).getDOMNode());
|
||||
selection = rangy.getSelection();
|
||||
selection.setSingleRange(newRange);
|
||||
originalSelection = selection.getAllRanges();
|
||||
}
|
||||
|
||||
this.editor.all('.' + classname).each(function (node) {
|
||||
node.setAttribute('class', 'fontcolor ' + fontColorClass);
|
||||
}, this);
|
||||
|
||||
host.setSelection(originalSelection);
|
||||
|
||||
this.markUpdated();
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user