diff --git a/cnx/aloha-config.coffee b/cnx/aloha-config.coffee
index 135bef555a..9a0212b9b5 100644
--- a/cnx/aloha-config.coffee
+++ b/cnx/aloha-config.coffee
@@ -8,7 +8,7 @@
@Aloha.settings =
jQuery: @jQuery # Use the same version of jQuery
logLevels:
- error: true
+ error: false
warn: true
info: false
debug: false
@@ -47,11 +47,16 @@
'oer/note'
]
- note:
- types:
- 'note': true
- 'noteish': true
- 'noteish-notitle': false
+ note: [
+ { label: 'Note', cls: 'note', hasTitle: true }
+ { label: 'Aside', cls: 'note', hasTitle: true, type: 'aside' }
+ { label: 'Warning', cls: 'note', hasTitle: true, type: 'warning' }
+ { label: 'Tip', cls: 'note', hasTitle: true, type: 'tip' }
+ { label: 'Important', cls: 'note', hasTitle: true, type: 'important' }
+
+ { label: 'Noteish', cls: 'noteish', hasTitle: true }
+ { label: 'Noteish (no Title)', cls: 'noteish-notitle', hasTitle: false }
+ ]
# This whole thing is what's needed to:
#
diff --git a/cnx/aloha-config.js b/cnx/aloha-config.js
index 0b81d1c371..4e2f583720 100644
--- a/cnx/aloha-config.js
+++ b/cnx/aloha-config.js
@@ -6,7 +6,7 @@
this.Aloha.settings = {
jQuery: this.jQuery,
logLevels: {
- error: true,
+ error: false,
warn: true,
info: false,
debug: false
@@ -18,14 +18,42 @@
},
errorhandling: true,
plugins: {
- load: ['common/ui', 'oer/toolbar', 'oer/popover', 'oer/format', 'common/contenthandler', 'common/paste', 'common/block', 'common/list', 'oer/table', 'oer/popover', 'oer/math', 'extra/draganddropfiles', 'common/image', 'oer/assorted', 'oer/title', 'common/undo', 'oer/undobutton', 'oer/genericbutton', 'oer/semanticblock', 'oer/exercise', 'oer/note'],
- note: {
- types: {
- 'note': true,
- 'noteish': true,
- 'noteish-notitle': false
+ load: ['common/ui', 'oer/toolbar', 'oer/popover', 'oer/format', 'common/contenthandler', 'common/paste', 'common/block', 'common/list', 'oer/table', 'oer/popover', 'oer/math', 'extra/draganddropfiles', 'common/image', 'oer/assorted', 'oer/title', 'common/undo', 'oer/undobutton', 'oer/genericbutton', 'oer/semanticblock', 'oer/exercise', 'oer/note', 'oer/cnxmlplus-handler'],
+ note: [
+ {
+ label: 'Note',
+ cls: 'note',
+ hasTitle: true
+ }, {
+ label: 'Aside',
+ cls: 'note',
+ hasTitle: true,
+ type: 'aside'
+ }, {
+ label: 'Warning',
+ cls: 'note',
+ hasTitle: true,
+ type: 'warning'
+ }, {
+ label: 'Tip',
+ cls: 'note',
+ hasTitle: true,
+ type: 'tip'
+ }, {
+ label: 'Important',
+ cls: 'note',
+ hasTitle: true,
+ type: 'important'
+ }, {
+ label: 'Noteish',
+ cls: 'noteish',
+ hasTitle: true
+ }, {
+ label: 'Noteish (no Title)',
+ cls: 'noteish-notitle',
+ hasTitle: false
}
- },
+ ],
draganddropfiles: {
upload: {
config: {
diff --git a/src/plugins/oer/note/lib/note-plugin.coffee b/src/plugins/oer/note/lib/note-plugin.coffee
index 00a0460134..55242600ba 100644
--- a/src/plugins/oer/note/lib/note-plugin.coffee
+++ b/src/plugins/oer/note/lib/note-plugin.coffee
@@ -8,41 +8,71 @@ define [
'semanticblock/semanticblock-plugin'
'css!note/css/note-plugin.css'], (Aloha, Plugin, jQuery, Ephemera, UI, Button, semanticBlock) ->
- TITLE_CONTAINER = '''
+ TITLE_CONTAINER = jQuery('''
- '''
+ ''')
+
+ # Find all classes that could mean something is "notish"
+ # so they can be removed when the type is changed from the dropdown.
+ notishClasses = {}
Plugin.create 'note',
+ # Default Settings
+ # -------
+ # The plugin can listen to various classes that should "behave" like a note.
+ # For each notish element provide a:
+ # - `label`: **Required** Shows up in dropdown
+ # - `cls` : **Required** The classname to enable this plugin on
+ # - `hasTitle`: **Required** `true` if the element allows optional titles
+ # - `type`: value in the `data-type` attribute.
+ # - `tagName`: Default: `div`. The HTML element name to use when creating a new note
+ # - `titleTagName`: Default: `div`. The HTML element name to use when creating a new title
+ #
+ # For example, a Warning could look like this:
+ #
+ # { label:'Warning', cls:'note', hasTitle:false, type:'warning'}
+ #
+ # Then, when the user selects "Warning" from the dropdown the element's
+ # class and type will be changed and its `> .title` will be removed.
+ defaults: [
+ { label: 'Note', cls: 'note', hasTitle: true }
+ ]
init: () ->
# Load up specific classes to listen to or use the default
- types = @settings.types or {note: true}
- jQuery.map types, (hasTitle, className) ->
-
- # These 2 variables should be moved into the config so other note-ish classes
- # can define what the element name is that is generated for the note and
+ types = @settings
+ jQuery.each types, (i, type) =>
+ className = type.cls or throw 'BUG Invalid configuration of not plugin. cls required!'
+ typeName = type.type
+ hasTitle = !!type.hasTitle
+ label = type.label or throw 'BUG Invalid configuration of not plugin. label required!'
+
+ # These 2 variables allow other note-ish classes
+ # to define what the element name is that is generated for the note and
# for the title.
#
# Maybe they could eventually be functions so titles for inline notes generate
# a `span` instead of a `div` for example.
- tagName = 'div'
- titleTagName = 'div'
+ tagName = type.tagName or 'div'
+ titleTagName = type.titleTagName or 'div'
+
+ selector = ".#{className}:not([data-type])"
+ selector = ".#{className}[data-type='#{typeName}']" if typeName
+
+ notishClasses[className] = true
+
+
newTemplate = jQuery("<#{tagName}>#{tagName}")
newTemplate.addClass(className)
- newTemplate.attr('data-type', className)
+ newTemplate.attr('data-type', typeName) if typeName
if hasTitle
newTemplate.append("<#{titleTagName} class='title'>#{titleTagName}")
- semanticBlock.activateHandler(className, (element) ->
+ semanticBlock.activateHandler(selector, (element) =>
if hasTitle
titleElement = element.children('.title')
@@ -58,9 +88,40 @@ define [
element.children().remove()
if hasTitle
- titleContainer = jQuery(TITLE_CONTAINER)
+ titleContainer = TITLE_CONTAINER.clone()
+ # Add dropdown elements for each possible type
+ jQuery.each @settings, (i, foo) =>
+ $option = jQuery('')
+ $option.appendTo(titleContainer.find('.dropdown-menu'))
+ $option = $option.children('a')
+ $option.text(foo.label)
+ $option.on 'click', =>
+ # Remove the title if this type does not have one
+ # The title was moved into `.type-container` for some reason
+ if foo.hasTitle
+ # If there is no `.title` element then add one in and enable it as an Aloha block
+ if not element.find('> .type-container > .title')[0]
+ $newTitle = jQuery("<#{foo.titleTagName or 'span'} class='title'>#{foo.titleTagName or 'span'}")
+ element.children('.type-container').append($newTitle)
+ $newTitle.aloha()
+
+ else
+ element.find('> .type-container > .title').remove()
+
+ # Remove the `data-type` if this type does not have one
+ if foo.type
+ element.attr('data-type', foo.type)
+ else
+ element.removeAttr('data-type')
+
+ # Remove all notish class names and then add this one in
+ for key of notishClasses
+ element.removeClass key
+ element.addClass(foo.cls)
+
+
titleContainer.find('.title').text(title)
- titleContainer.find('.type').text(type.charAt(0).toUpperCase() + type.slice(1) )
+ titleContainer.find('.type').text(label)
titleContainer.prependTo(element)
titleContainer.children('.title').aloha()
@@ -71,7 +132,7 @@ define [
.appendTo(element)
.aloha()
)
- semanticBlock.deactivateHandler(className, (element) ->
+ semanticBlock.deactivateHandler(selector, (element) ->
bodyElement = element.children('.body')
body = bodyElement.children()
@@ -93,10 +154,10 @@ define [
element.append(body)
)
# Add a listener
- UI.adopt "insert-#{className}", Button,
+ UI.adopt "insert-#{className}#{typeName}", Button,
click: -> semanticBlock.insertAtCursor(newTemplate.clone())
# For legacy toolbars listen to 'insertNote'
- if 'note' == className
+ if 'note' == className and not typeName
UI.adopt "insertNote", Button,
click: -> semanticBlock.insertAtCursor(newTemplate.clone())
diff --git a/src/plugins/oer/note/lib/note-plugin.js b/src/plugins/oer/note/lib/note-plugin.js
index b2d57bb351..3d6313ecfc 100644
--- a/src/plugins/oer/note/lib/note-plugin.js
+++ b/src/plugins/oer/note/lib/note-plugin.js
@@ -2,26 +2,48 @@
(function() {
define(['aloha', 'aloha/plugin', 'jquery', 'aloha/ephemera', 'ui/ui', 'ui/button', 'semanticblock/semanticblock-plugin', 'css!note/css/note-plugin.css'], function(Aloha, Plugin, jQuery, Ephemera, UI, Button, semanticBlock) {
- var TITLE_CONTAINER;
- TITLE_CONTAINER = '';
+ var TITLE_CONTAINER, notishClasses;
+ TITLE_CONTAINER = jQuery('');
+ notishClasses = {};
return Plugin.create('note', {
+ defaults: [
+ {
+ label: 'Note',
+ cls: 'note',
+ hasTitle: true
+ }
+ ],
init: function() {
- var types;
- types = this.settings.types || {
- note: true
- };
- return jQuery.map(types, function(hasTitle, className) {
- var newTemplate, tagName, titleTagName;
- tagName = 'div';
- titleTagName = 'div';
+ var types,
+ _this = this;
+ types = this.settings;
+ return jQuery.each(types, function(i, type) {
+ var className, hasTitle, label, newTemplate, selector, tagName, titleTagName, typeName;
+ className = type.cls || (function() {
+ throw 'BUG Invalid configuration of not plugin. cls required!';
+ })();
+ typeName = type.type;
+ hasTitle = !!type.hasTitle;
+ label = type.label || (function() {
+ throw 'BUG Invalid configuration of not plugin. label required!';
+ })();
+ tagName = type.tagName || 'div';
+ titleTagName = type.titleTagName || 'div';
+ selector = "." + className + ":not([data-type])";
+ if (typeName) {
+ selector = "." + className + "[data-type='" + typeName + "']";
+ }
+ notishClasses[className] = true;
newTemplate = jQuery("<" + tagName + ">" + tagName);
newTemplate.addClass(className);
- newTemplate.attr('data-type', className);
+ if (typeName) {
+ newTemplate.attr('data-type', typeName);
+ }
if (hasTitle) {
newTemplate.append("<" + titleTagName + " class='title'>" + titleTagName);
}
- semanticBlock.activateHandler(className, function(element) {
- var body, title, titleContainer, titleElement, type;
+ semanticBlock.activateHandler(selector, function(element) {
+ var body, title, titleContainer, titleElement;
if (hasTitle) {
titleElement = element.children('.title');
if (titleElement.length) {
@@ -35,15 +57,43 @@
body = element.children();
element.children().remove();
if (hasTitle) {
- titleContainer = jQuery(TITLE_CONTAINER);
+ titleContainer = TITLE_CONTAINER.clone();
+ jQuery.each(_this.settings, function(i, foo) {
+ var $option;
+ $option = jQuery('');
+ $option.appendTo(titleContainer.find('.dropdown-menu'));
+ $option = $option.children('a');
+ $option.text(foo.label);
+ return $option.on('click', function() {
+ var $newTitle, key;
+ if (foo.hasTitle) {
+ if (!element.find('> .type-container > .title')[0]) {
+ $newTitle = jQuery("<" + (foo.titleTagName || 'span') + " class='title'>" + (foo.titleTagName || 'span'));
+ element.children('.type-container').append($newTitle);
+ $newTitle.aloha();
+ }
+ } else {
+ element.find('> .type-container > .title').remove();
+ }
+ if (foo.type) {
+ element.attr('data-type', foo.type);
+ } else {
+ element.removeAttr('data-type');
+ }
+ for (key in notishClasses) {
+ element.removeClass(key);
+ }
+ return element.addClass(foo.cls);
+ });
+ });
titleContainer.find('.title').text(title);
- titleContainer.find('.type').text(type.charAt(0).toUpperCase() + type.slice(1));
+ titleContainer.find('.type').text(label);
titleContainer.prependTo(element);
titleContainer.children('.title').aloha();
}
return $('').addClass('body').attr('placeholder', "Type the text of your " + className + " here.").append(body).appendTo(element).aloha();
});
- semanticBlock.deactivateHandler(className, function(element) {
+ semanticBlock.deactivateHandler(selector, function(element) {
var body, bodyElement, title, titleElement;
bodyElement = element.children('.body');
body = bodyElement.children();
@@ -62,12 +112,12 @@
}
return element.append(body);
});
- UI.adopt("insert-" + className, Button, {
+ UI.adopt("insert-" + className + typeName, Button, {
click: function() {
return semanticBlock.insertAtCursor(newTemplate.clone());
}
});
- if ('note' === className) {
+ if ('note' === className && !typeName) {
return UI.adopt("insertNote", Button, {
click: function() {
return semanticBlock.insertAtCursor(newTemplate.clone());
diff --git a/src/plugins/oer/semanticblock/lib/semanticblock-plugin.coffee b/src/plugins/oer/semanticblock/lib/semanticblock-plugin.coffee
index 9a930709a9..8f0cf3fc45 100644
--- a/src/plugins/oer/semanticblock/lib/semanticblock-plugin.coffee
+++ b/src/plugins/oer/semanticblock/lib/semanticblock-plugin.coffee
@@ -60,10 +60,9 @@ define ['aloha', 'block/blockmanager', 'aloha/plugin', 'aloha/pluginmanager', 'j
unless element.parent('.semantic-container').length or element.is('.semantic-container')
element.addClass 'aloha-oer-block'
element.wrap(blockTemplate).parent().append(blockControls.clone()).alohaBlock()
- type = undefined
- for type of activateHandlers
- if element.hasClass(type)
- activateHandlers[type] element
+ for selector of activateHandlers
+ if element.is(selector)
+ activateHandlers[selector] element
break
deactivate = (element) ->
@@ -71,10 +70,9 @@ define ['aloha', 'block/blockmanager', 'aloha/plugin', 'aloha/pluginmanager', 'j
element.removeClass 'aloha-oer-block ui-draggable'
element.removeAttr 'style'
- type = undefined
- for type of deactivateHandlers
- if element.hasClass(type)
- deactivateHandlers[type] element
+ for selector of deactivateHandlers
+ if element.is(selector)
+ deactivateHandlers[selector] element
break
element.siblings('.semantic-controls').remove()
element.unwrap()
@@ -96,8 +94,8 @@ define ['aloha', 'block/blockmanager', 'aloha/plugin', 'aloha/pluginmanager', 'j
Plugin.create 'semanticblock',
makeClean: (content) ->
- for type of deactivateHandlers
- content.find('.aloha-oer-block.'+type).each ->
+ for selector of deactivateHandlers
+ content.find(".aloha-oer-block#{selector}").each ->
deactivate jQuery(this)
init: ->
@@ -116,7 +114,7 @@ define ['aloha', 'block/blockmanager', 'aloha/plugin', 'aloha/pluginmanager', 'j
$root = params.obj
# Add a `.aloha-oer-block` to all registered classes
classes = []
- classes.push ".#{cls}" for cls of activateHandlers
+ classes.push selector for selector of activateHandlers
$root.find(classes.join()).each (i, el) ->
$el = jQuery(el)
$el.addClass 'aloha-oer-block' if not $el.parents('.semantic-drag-source')[0]
@@ -159,11 +157,11 @@ define ['aloha', 'block/blockmanager', 'aloha/plugin', 'aloha/pluginmanager', 'j
$element = Aloha.jQuery('.semantic-temp').removeClass('semantic-temp')
activate $element
- activateHandler: (type, handler) ->
- activateHandlers[type] = handler
+ activateHandler: (selector, handler) ->
+ activateHandlers[selector] = handler
- deactivateHandler: (type, handler) ->
- deactivateHandlers[type] = handler
+ deactivateHandler: (selector, handler) ->
+ deactivateHandlers[selector] = handler
registerEvent: (name, selector, callback) ->
pluginEvents.push
diff --git a/src/plugins/oer/semanticblock/lib/semanticblock-plugin.js b/src/plugins/oer/semanticblock/lib/semanticblock-plugin.js
index 8de9baafe7..a1c5a4f7ee 100644
--- a/src/plugins/oer/semanticblock/lib/semanticblock-plugin.js
+++ b/src/plugins/oer/semanticblock/lib/semanticblock-plugin.js
@@ -75,15 +75,14 @@
];
insertElement = function(element) {};
activate = function(element) {
- var type, _results;
+ var selector, _results;
if (!(element.parent('.semantic-container').length || element.is('.semantic-container'))) {
element.addClass('aloha-oer-block');
element.wrap(blockTemplate).parent().append(blockControls.clone()).alohaBlock();
- type = void 0;
_results = [];
- for (type in activateHandlers) {
- if (element.hasClass(type)) {
- activateHandlers[type](element);
+ for (selector in activateHandlers) {
+ if (element.is(selector)) {
+ activateHandlers[selector](element);
break;
} else {
_results.push(void 0);
@@ -93,14 +92,13 @@
}
};
deactivate = function(element) {
- var type;
+ var selector;
if (element.parent('.semantic-container').length || element.is('.semantic-container')) {
element.removeClass('aloha-oer-block ui-draggable');
element.removeAttr('style');
- type = void 0;
- for (type in deactivateHandlers) {
- if (element.hasClass(type)) {
- deactivateHandlers[type](element);
+ for (selector in deactivateHandlers) {
+ if (element.is(selector)) {
+ deactivateHandlers[selector](element);
break;
}
}
@@ -130,10 +128,10 @@
});
return Plugin.create('semanticblock', {
makeClean: function(content) {
- var type, _results;
+ var selector, _results;
_results = [];
- for (type in deactivateHandlers) {
- _results.push(content.find('.aloha-oer-block.' + type).each(function() {
+ for (selector in deactivateHandlers) {
+ _results.push(content.find(".aloha-oer-block" + selector).each(function() {
return deactivate(jQuery(this));
}));
}
@@ -160,11 +158,11 @@
}
});
return Aloha.bind('aloha-editable-created', function(e, params) {
- var $root, classes, cls;
+ var $root, classes, selector;
$root = params.obj;
classes = [];
- for (cls in activateHandlers) {
- classes.push("." + cls);
+ for (selector in activateHandlers) {
+ classes.push(selector);
}
$root.find(classes.join()).each(function(i, el) {
var $el;
@@ -217,11 +215,11 @@
$element = Aloha.jQuery('.semantic-temp').removeClass('semantic-temp');
return activate($element);
},
- activateHandler: function(type, handler) {
- return activateHandlers[type] = handler;
+ activateHandler: function(selector, handler) {
+ return activateHandlers[selector] = handler;
},
- deactivateHandler: function(type, handler) {
- return deactivateHandlers[type] = handler;
+ deactivateHandler: function(selector, handler) {
+ return deactivateHandlers[selector] = handler;
},
registerEvent: function(name, selector, callback) {
return pluginEvents.push({