"),n=window.getSelection().focusNode,r=this._getParentBlock(n,i!=="replace"),i==="adddiv"&&(r=this._addDivIfNeeded(r)),r&&r.setAttribute("class",t[1]);else{var s=t[1].split(" ");this.get("host").toggleInlineSelectionClass(s)}this.markUpdated()},_getParentBlock:function(t,n){var r,i,s;for(r=t;r;r=r.parentNode){if(r.nodeType!==1)continue;i=e.one(r);if(i.hasClass("editor_atto_content"))return null;s=i.getComputedStyle("display");if(s==="block"||s==="inline-block"||n&&s==="list-item")return i}},_getParentBlockOld:function(e){var t,n;for(t=e;t;t=t.parentNode){if(t.nodeType!==1)continue;n=window.getComputedStyle(t,null);if(n)return t}return null},_addDivIfNeeded:function(t){var n,r,i;return t?t.get("tagName").toLowerCase()==="div"?t:(n=t.get("parentNode"),n.get("tagName").toLowerCase()==="div"&&n.get("children").size()===1?n:(r=t.next(),i=e.Node.create("
"),i.appendChild(t),r?n.insertBefore(i,r):n.appendChild(i),i)):null},_getDiv:function(e){var t;return e?e.get("tagName").toLowerCase()==="div"?e:(t=e.get("parentNode"),t.get("tagName").toLowerCase()==="div"?t:null):null},hasRangeSelected:function(){var e,t;return e=rangy.getSelection(),e.rangeCount?(t=e.getRangeAt(0),!t.collapsed):!1}},{ATTRS:{styles:{value:{}},blockmethod:{value:"setclass"}}})},"@VERSION@",{requires:["moodle-editor_atto-plugin"]});
diff --git a/yui/build/moodle-atto_styles-button/moodle-atto_styles-button.js b/yui/build/moodle-atto_styles-button/moodle-atto_styles-button.js
index ac42fcf..181cc34 100644
--- a/yui/build/moodle-atto_styles-button/moodle-atto_styles-button.js
+++ b/yui/build/moodle-atto_styles-button/moodle-atto_styles-button.js
@@ -95,37 +95,33 @@ Y.namespace('M.atto_styles').Button = Y.Base.create('button', Y.M.editor_atto.Ed
* @private
*/
_changeStyle: function(e, style) {
- var eID, element, p, pstyle;
+ var element, node, blockMethod;
+ blockMethod = this.get('blockmethod');
if (style[0] === '
') {
element = window.getSelection().focusNode;
- for (p = element; p; p = p.parentNode) {
- if (p.nodeType !== 1) {
- continue;
- }
- pstyle = window.getComputedStyle(p, null);
- if (pstyle) {
- p.removeAttribute('class');
- break;
+ if (blockMethod === 'replace') {
+ node = this._getParentBlockOld(element); // Find a styled element.
+ } else {
+ node = this._getParentBlock(element, true); // Find a block or list-item element.
+ if (blockMethod === 'adddiv') {
+ node = this._getDiv(node);
}
}
- return;
+ if (node) {
+ node.removeAttribute('class');
+ }
} else if (style[0] === '') {
- document.execCommand('formatBlock', false, '');
+ if (blockMethod === 'replace') {
+ document.execCommand('formatBlock', false, '
');
+ }
element = window.getSelection().focusNode;
- for (p = element; p; p = p.parentNode) {
- if (p.nodeType !== 1) {
- continue;
- }
- pstyle = window.getComputedStyle(p, null);
- if (pstyle) {
- var displaystyle = pstyle.getPropertyValue('display');
- if (displaystyle === 'block') {
- eID = p;
- break;
- }
- }
+ node = this._getParentBlock(element, (blockMethod !== 'replace'));
+ if (blockMethod === 'adddiv') {
+ node = this._addDivIfNeeded(node);
+ }
+ if (node) {
+ node.setAttribute('class', style[1]);
}
- eID.setAttribute('class', style[1]);
} else {
var styles = style[1].split(" ");
this.get('host').toggleInlineSelectionClass(styles);
@@ -134,6 +130,105 @@ Y.namespace('M.atto_styles').Button = Y.Base.create('button', Y.M.editor_atto.Ed
this.markUpdated();
},
+ /**
+ * Find the nearest parent with display:block (or list-item)
+ * @param el Node
+ * @param includeListItem bool - true if list-item is a valid display type to return
+ * @returns Node|null
+ * @private
+ */
+ _getParentBlock: function(el, includeListItem) {
+ var p, node, display;
+ for (p = el; p; p = p.parentNode) {
+ if (p.nodeType !== 1) {
+ continue;
+ }
+ node = Y.one(p);
+ if (node.hasClass('editor_atto_content')) {
+ return null;
+ }
+ display = node.getComputedStyle('display');
+ if (display === 'block' || display === 'inline-block' || (includeListItem && display === 'list-item')) {
+ return node;
+ }
+ }
+ },
+
+ /**
+ * Find the nearest parent with any associated style.
+ * @param el Node
+ * @returns Node|null
+ * @private
+ */
+ _getParentBlockOld: function(el) {
+ var p, pstyle;
+ for (p = el; p; p = p.parentNode) {
+ if (p.nodeType !== 1) {
+ continue;
+ }
+ pstyle = window.getComputedStyle(p, null);
+ if (pstyle) {
+ return p;
+ }
+ }
+ return null;
+ },
+
+ /**
+ * Make sure we are targetting a div element - creating one if none is found.
+ * @param el Node
+ * @returns Node|null
+ * @private
+ */
+ _addDivIfNeeded: function(el) {
+ var parent, next, div;
+ if (!el) {
+ return null;
+ }
+ if (el.get('tagName').toLowerCase() === 'div') {
+ return el; // The block element is already a div - just return it.
+ }
+ parent = el.get('parentNode');
+ if (parent.get('tagName').toLowerCase() === 'div') {
+ if (parent.get('children').size() === 1) {
+ return parent; // The block element is surrounded by a div - return that.
+ }
+ }
+
+ // Need to wrap the existing element in a div.
+ next = el.next();
+ div = Y.Node.create('
');
+ div.appendChild(el);
+ if (next) {
+ parent.insertBefore(div, next);
+ } else {
+ parent.appendChild(div);
+ }
+ return div;
+ },
+
+ /**
+ * Look for a div that
+ * @param el Node
+ * @returns Node|null
+ * @private
+ */
+ _getDiv: function(el) {
+ var parent;
+ if (!el) {
+ return null;
+ }
+ if (el.get('tagName').toLowerCase() === 'div') {
+ return el; // The block element is already a div - just return it.
+ }
+ parent = el.get('parentNode');
+ if (parent.get('tagName').toLowerCase() === 'div') {
+ return parent; // The block is surrounded by a div - return it.
+ }
+
+ return null; // Not able to find a suitable div.
+ },
+
hasRangeSelected: function() {
var selection, range;
@@ -154,6 +249,9 @@ Y.namespace('M.atto_styles').Button = Y.Base.create('button', Y.M.editor_atto.Ed
*/
styles: {
value: {}
+ },
+ blockmethod: {
+ value: 'setclass'
}
}
});
diff --git a/yui/src/button/js/button.js b/yui/src/button/js/button.js
index 1803e3c..602ed73 100644
--- a/yui/src/button/js/button.js
+++ b/yui/src/button/js/button.js
@@ -93,37 +93,33 @@ Y.namespace('M.atto_styles').Button = Y.Base.create('button', Y.M.editor_atto.Ed
* @private
*/
_changeStyle: function(e, style) {
- var eID, element, p, pstyle;
+ var element, node, blockMethod;
+ blockMethod = this.get('blockmethod');
if (style[0] === '
') {
element = window.getSelection().focusNode;
- for (p = element; p; p = p.parentNode) {
- if (p.nodeType !== 1) {
- continue;
- }
- pstyle = window.getComputedStyle(p, null);
- if (pstyle) {
- p.removeAttribute('class');
- break;
+ if (blockMethod === 'replace') {
+ node = this._getParentBlockOld(element); // Find a styled element.
+ } else {
+ node = this._getParentBlock(element, true); // Find a block or list-item element.
+ if (blockMethod === 'adddiv') {
+ node = this._getDiv(node);
}
}
- return;
+ if (node) {
+ node.removeAttribute('class');
+ }
} else if (style[0] === '') {
- document.execCommand('formatBlock', false, '');
+ if (blockMethod === 'replace') {
+ document.execCommand('formatBlock', false, '
');
+ }
element = window.getSelection().focusNode;
- for (p = element; p; p = p.parentNode) {
- if (p.nodeType !== 1) {
- continue;
- }
- pstyle = window.getComputedStyle(p, null);
- if (pstyle) {
- var displaystyle = pstyle.getPropertyValue('display');
- if (displaystyle === 'block') {
- eID = p;
- break;
- }
- }
+ node = this._getParentBlock(element, (blockMethod !== 'replace'));
+ if (blockMethod === 'adddiv') {
+ node = this._addDivIfNeeded(node);
+ }
+ if (node) {
+ node.setAttribute('class', style[1]);
}
- eID.setAttribute('class', style[1]);
} else {
var styles = style[1].split(" ");
this.get('host').toggleInlineSelectionClass(styles);
@@ -132,6 +128,105 @@ Y.namespace('M.atto_styles').Button = Y.Base.create('button', Y.M.editor_atto.Ed
this.markUpdated();
},
+ /**
+ * Find the nearest parent with display:block (or list-item)
+ * @param el Node
+ * @param includeListItem bool - true if list-item is a valid display type to return
+ * @returns Node|null
+ * @private
+ */
+ _getParentBlock: function(el, includeListItem) {
+ var p, node, display;
+ for (p = el; p; p = p.parentNode) {
+ if (p.nodeType !== 1) {
+ continue;
+ }
+ node = Y.one(p);
+ if (node.hasClass('editor_atto_content')) {
+ return null;
+ }
+ display = node.getComputedStyle('display');
+ if (display === 'block' || display === 'inline-block' || (includeListItem && display === 'list-item')) {
+ return node;
+ }
+ }
+ },
+
+ /**
+ * Find the nearest parent with any associated style.
+ * @param el Node
+ * @returns Node|null
+ * @private
+ */
+ _getParentBlockOld: function(el) {
+ var p, pstyle;
+ for (p = el; p; p = p.parentNode) {
+ if (p.nodeType !== 1) {
+ continue;
+ }
+ pstyle = window.getComputedStyle(p, null);
+ if (pstyle) {
+ return p;
+ }
+ }
+ return null;
+ },
+
+ /**
+ * Make sure we are targetting a div element - creating one if none is found.
+ * @param el Node
+ * @returns Node|null
+ * @private
+ */
+ _addDivIfNeeded: function(el) {
+ var parent, next, div;
+ if (!el) {
+ return null;
+ }
+ if (el.get('tagName').toLowerCase() === 'div') {
+ return el; // The block element is already a div - just return it.
+ }
+ parent = el.get('parentNode');
+ if (parent.get('tagName').toLowerCase() === 'div') {
+ if (parent.get('children').size() === 1) {
+ return parent; // The block element is surrounded by a div - return that.
+ }
+ }
+
+ // Need to wrap the existing element in a div.
+ next = el.next();
+ div = Y.Node.create('
');
+ div.appendChild(el);
+ if (next) {
+ parent.insertBefore(div, next);
+ } else {
+ parent.appendChild(div);
+ }
+ return div;
+ },
+
+ /**
+ * Look for a div that
+ * @param el Node
+ * @returns Node|null
+ * @private
+ */
+ _getDiv: function(el) {
+ var parent;
+ if (!el) {
+ return null;
+ }
+ if (el.get('tagName').toLowerCase() === 'div') {
+ return el; // The block element is already a div - just return it.
+ }
+ parent = el.get('parentNode');
+ if (parent.get('tagName').toLowerCase() === 'div') {
+ return parent; // The block is surrounded by a div - return it.
+ }
+
+ return null; // Not able to find a suitable div.
+ },
+
hasRangeSelected: function() {
var selection, range;
@@ -152,6 +247,9 @@ Y.namespace('M.atto_styles').Button = Y.Base.create('button', Y.M.editor_atto.Ed
*/
styles: {
value: {}
+ },
+ blockmethod: {
+ value: 'setclass'
}
}
});