Skip to content

Commit

Permalink
New setting to choose how to apply block styles:
Browse files Browse the repository at this point in the history
* Replace - replace the parent block-level element with a div + style
* Set class - set the style on the parent block-level element
* Surround - surround the parent block-level element with a div + style
  • Loading branch information
davosmith committed Nov 13, 2015
1 parent b18c803 commit 71c8273
Show file tree
Hide file tree
Showing 8 changed files with 393 additions and 77 deletions.
10 changes: 10 additions & 0 deletions lang/en/atto_styles.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

$string['blockmethod'] = 'Block style method';
$string['blockmethod_desc'] = 'The method used for adding block styles, each finds the block-level element that surrounds the selection and then:
<ul>
<li>Replace - convert the element into a \'div\' tag and apply the style</li>
<li>Set class - applies the style directly to the element</li>
<li>Surround - surround the element with a \'div\' tag and apply the style</li>
</ul>';
$string['config'] = 'Styles configuration';
$string['config_desc'] = 'Configuration for the styles widget for Atto in JSON format.
<hr />
Expand Down Expand Up @@ -80,6 +87,9 @@
<li><a href="http://getbootstrap.com/2.3.2/components.html#alerts">Bootstrap alerts</a></li>
<li><a href="http://getbootstrap.com/2.3.2/components.html#misc">Bootstrap helper classes</a></li>
</ul>';
$string['method_adddiv'] = 'Surround';
$string['method_replace'] = 'Replace';
$string['method_setclass'] = 'Set class';
$string['nostyle'] = 'No style';
$string['pluginname'] = 'Styles';
$string['settings'] = 'Styles settings';
4 changes: 3 additions & 1 deletion lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,7 @@ function atto_styles_params_for_js($elementid, $options, $fpoptions) {

$styles = json_encode($styles);

return array('styles' => $styles);
$blockmethod = get_config('atto_styles', 'blockmethod');

return array('styles' => $styles, 'blockmethod' => $blockmethod);
}
10 changes: 10 additions & 0 deletions settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,14 @@
$desc,
$default);
$settings->add($setting);
$blockmethods = array(
'replace' => get_string('method_replace', 'atto_styles'),
'setclass' => get_string('method_setclass', 'atto_styles'),
'adddiv' => get_string('method_adddiv', 'atto_styles'),
);
$setting = new admin_setting_configselect('atto_styles/blockmethod',
new lang_string('blockmethod', 'atto_styles'),
new lang_string('blockmethod_desc', 'atto_styles'),
'replace', $blockmethods);
$settings->add($setting);
}
6 changes: 3 additions & 3 deletions version.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
defined('MOODLE_INTERNAL') || die();

$plugin->component = 'atto_styles';
$plugin->version = 2015051100;
$plugin->release = '2.9 (Build: 2015081800)';
$plugin->requires = 2015051100;
$plugin->version = 2015111300;
$plugin->release = '2.8 (Build: 2015111300)';
$plugin->requires = 2014111000; // Moodle 2.8+
$plugin->maturity = MATURITY_STABLE;
146 changes: 122 additions & 24 deletions yui/build/moodle-atto_styles-button/moodle-atto_styles-button-debug.js
Original file line number Diff line number Diff line change
Expand Up @@ -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] === '<nostyle>') {
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] === '<block>') {
document.execCommand('formatBlock', false, '<div>');
if (blockMethod === 'replace') {
document.execCommand('formatBlock', false, '<div>');
}
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);
Expand All @@ -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></div>');
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;

Expand All @@ -154,6 +249,9 @@ Y.namespace('M.atto_styles').Button = Y.Base.create('button', Y.M.editor_atto.Ed
*/
styles: {
value: {}
},
blockmethod: {
value: 'setclass'
}
}
});
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 71c8273

Please sign in to comment.