333 lines
9.2 KiB
Plaintext
333 lines
9.2 KiB
Plaintext
module.exports = function() {
|
|
events: {
|
|
'click button': 'command'
|
|
},
|
|
|
|
template: 'spytext-toolbar',
|
|
|
|
command: function() {
|
|
var command = $(e.currentTarget).attr('data-command');
|
|
}
|
|
};
|
|
var SpytextButton = function(config, spytext) {
|
|
this.spytext = spytext;
|
|
this.config = typeof config.preset === 'string' ? merge(this.presets[config.preset], config) : config;
|
|
this.element = $('<button class="spytext-button" st-button-type="' + config.preset + '" tabindex="' + -1 + '">')[0];
|
|
|
|
for(var property in this.events)
|
|
$(this.element).on(property, this.events[property].bind(this));
|
|
|
|
this.disable();
|
|
};
|
|
|
|
SpytextButton.prototype = {
|
|
setActive: function() {
|
|
$(this.element).addClass('active');
|
|
},
|
|
|
|
unsetActive: function() {
|
|
$(this.element).removeClass('active');
|
|
},
|
|
|
|
enable: function() {
|
|
this.element.disabled = false;
|
|
},
|
|
|
|
disable: function() {
|
|
this.element.disabled = true;
|
|
this.unsetActive();
|
|
},
|
|
|
|
events: {
|
|
click: function(e) {
|
|
e.preventDefault();
|
|
this.spytext.execute(this.config.action, this.config.options);
|
|
}
|
|
},
|
|
|
|
presets: {
|
|
alignLeft: { title: 'Align Left', action: 'align', options: { alignment: 'left' }},
|
|
alignRight: { title: 'Align Right', action: 'align', options: { alignment: 'right' }},
|
|
alignCenter: { title: 'Align Center', action: 'align', options: { alignment: 'center' }},
|
|
alignJustify: { title: 'Align Justify', action: 'align', options: { alignment: 'justify' }},
|
|
bold: { title: 'Bold', action: 'format', options: { tag: 'B' }},
|
|
strikeThrough: { title: 'Strike Through', action: 'format', options: { tag: 'STRIKE' }},
|
|
underline: { title: 'Underline', action: 'format', options: { tag: 'U' }},
|
|
italic: { title: 'Italic', action: 'format', options: { tag: 'I' }},
|
|
removeFormat: { action: 'removeFormat' },
|
|
typeHeading1: { title: 'Heading 1', action: 'block', options: { tag: 'H1' }},
|
|
typeHeading2: { title: 'Heading 2', action: 'block', options: { tag: 'H2' }},
|
|
typeHeading3: { title: 'Heading 3', action: 'block', options: { tag: 'H3' }},
|
|
typeHeading4: { title: 'Heading 4', action: 'block', options: { tag: 'H4' }},
|
|
typeHeading5: { title: 'Heading 5', action: 'block', options: { tag: 'H5' }},
|
|
typeHeading6: { title: 'Heading 6', action: 'block', options: { tag: 'H6' }},
|
|
typeParagraph: { title: 'Paragraph', action: 'block', options: { tag: 'P' }},
|
|
orderedList: { title: 'Ordered List', action: 'list', options: { tag: 'OL' }},
|
|
unorderedList: { title: 'Unordered List', action: 'list', options: { tag: 'UL' }},
|
|
indent: { title: 'Indent', action: 'indent', options: { outdent: false }},
|
|
outdent: { title: 'Outdent', action: 'indent', options: { outdent: true }}
|
|
}
|
|
};
|
|
|
|
var SpytextDropdown = function(config, spytext) {
|
|
this.spytext = spytext;
|
|
this.config = typeof config.preset === 'string' ? merge(this.presets[config.preset], config) : config;
|
|
this.items = [];
|
|
this.element = $('<ul class="spytext-dropdown">')[0];
|
|
|
|
var property;
|
|
|
|
this.config.items.forEach(function(item) {
|
|
var $el = $('<li><span>' + item.title + '</span></li>');
|
|
$(this.element).append($el);
|
|
|
|
for(property in this.events.item)
|
|
$el.on(property, this.events.item[property].bind(this));
|
|
|
|
this.items.push(item);
|
|
}.bind(this));
|
|
|
|
for(property in this.events.dropdown)
|
|
$(this.element).on(property, this.events.dropdown[property].bind(this));
|
|
|
|
this.index = 0;
|
|
this.length = $(this.element).children().length;
|
|
this.disable();
|
|
};
|
|
|
|
SpytextDropdown.prototype = {
|
|
setIndex: function(index) {
|
|
this.index = index;
|
|
var liHeight = this.element.children[0].offsetHeight;
|
|
var children = this.element.children;
|
|
|
|
for(var i = 0; i < children.length; i++) {
|
|
$(children[i]).css('top', '-' + (index * liHeight) + 'px');
|
|
|
|
if(i === index) $(children[i]).addClass('active');
|
|
else $(children[i]).removeClass('active');
|
|
}
|
|
},
|
|
|
|
setNoActive: function() {
|
|
this.index = 0;
|
|
var children = this.element.children;
|
|
|
|
for(var i = 0; i < children.length; i++) {
|
|
$(children[i]).css('top', '0');
|
|
$(children[i]).removeClass('active');
|
|
}
|
|
},
|
|
|
|
setActive: function(options) {
|
|
for(var i = 0; i < this.items.length; i++)
|
|
for(var prop in options)
|
|
if(options[prop] === this.items[i].options[prop])
|
|
return this.setIndex(i);
|
|
},
|
|
|
|
enable: function() {
|
|
$(this.element).removeClass('disabled');
|
|
},
|
|
|
|
disable: function() {
|
|
$(this.element).addClass('disabled').removeClass('expanded');
|
|
this.setNoActive();
|
|
},
|
|
|
|
events: {
|
|
dropdown: {
|
|
click: function(e) {
|
|
if(this.spytext.currentField) {
|
|
$(this.element).toggleClass('expanded');
|
|
}
|
|
}
|
|
},
|
|
|
|
item: {
|
|
click: function(e) {
|
|
if($(this.element).hasClass('expanded')) {
|
|
var index = $(this.element).children().index(e.currentTarget);
|
|
this.spytext.execute(this.config.action, this.items[index].options);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
presets: {
|
|
type: {
|
|
action: 'block',
|
|
items: [
|
|
{ title: 'Heading 1', options: { tag: 'H1' }},
|
|
{ title: 'Heading 2', options: { tag: 'H2' }},
|
|
{ title: 'Heading 3', options: { tag: 'H3' }},
|
|
{ title: 'Heading 4', options: { tag: 'H4' }},
|
|
{ title: 'Heading 5', options: { tag: 'H5' }},
|
|
{ title: 'Heading 6', options: { tag: 'H6' }},
|
|
{ title: 'Paragraph', options: { tag: 'P' }}
|
|
]
|
|
}
|
|
}
|
|
};
|
|
|
|
var SpytextToolbar = function(config, spytext) {
|
|
this.dropdowns = [];
|
|
this.buttons = [];
|
|
this.spytext = spytext;
|
|
this.config = typeof config.preset === 'string' ? merge(this.presets[config.preset], config) : config;
|
|
this.element = $('<div class="spytext-toolbar">')[0];
|
|
|
|
for(var property in this.config.dropdowns)
|
|
this.addDropdown.call(this, this.config.dropdowns[property], property);
|
|
|
|
for(property in this.config.buttonGroups)
|
|
this.addButtonGroup.call(this, this.config.buttonGroups[property], property);
|
|
|
|
for(property in this.events)
|
|
$(this.element).on(property, this.events[property].bind(this));
|
|
};
|
|
|
|
SpytextToolbar.prototype = {
|
|
addButtonGroup: function(group) {
|
|
var $ul = $('<UL>').addClass('spytext-button-group ' + group.name);
|
|
group.buttons.forEach(function(buttonType) {
|
|
var $li = $('<LI>');
|
|
var button = this.addButton({ preset: buttonType }, this.spytext);
|
|
$ul.append($li);
|
|
$li.append(button.element);
|
|
}.bind(this));
|
|
$(this.element).append($ul);
|
|
},
|
|
|
|
addButton: function(config) {
|
|
var button = new SpytextButton(config, this.spytext);
|
|
this.buttons[config.preset] = button;
|
|
return button;
|
|
},
|
|
|
|
addDropdown: function(config) {
|
|
config = typeof config === 'string' ? { preset: config } : config;
|
|
var dropdown = new SpytextDropdown(config, this.spytext);
|
|
this.dropdowns[config.preset] = dropdown;
|
|
$(this.element).append(dropdown.element);
|
|
return dropdown;
|
|
},
|
|
|
|
enable: function() {
|
|
for(var i in this.buttons) {
|
|
var button = this.buttons[i];
|
|
//button.element.setAttribute('disabled');
|
|
button.enable();
|
|
}
|
|
for(var j in this.dropdowns) {
|
|
this.dropdowns[j].enable();
|
|
//button.element.setAttribute('disabled');
|
|
}
|
|
$(this.element).addClass('active');
|
|
},
|
|
|
|
disable: function() {
|
|
for(var i in this.buttons) {
|
|
this.buttons[i].disable();
|
|
}
|
|
for(var j in this.dropdowns) {
|
|
this.dropdowns[j].disable();
|
|
}
|
|
$(this.element).removeClass('active');
|
|
},
|
|
|
|
setActiveStyles: function() {
|
|
function setBlock(tag) {
|
|
switch(tag) {
|
|
case 'P':
|
|
case 'H1':
|
|
case 'H2':
|
|
case 'H3':
|
|
case 'H4':
|
|
case 'H5':
|
|
case 'H6':
|
|
if(that.dropdowns.type) {
|
|
that.dropdowns.type.setActive({ tag: tag });
|
|
}
|
|
break;
|
|
case 'UL':
|
|
that.buttons.unorderedList.setActive();
|
|
that.dropdowns.type.setNoActive();
|
|
break;
|
|
case 'OL':
|
|
that.buttons.orderedList.setActive();
|
|
that.dropdowns.type.setNoActive();
|
|
break;
|
|
}
|
|
}
|
|
|
|
var that = this;
|
|
var tags = [];
|
|
var blocks = [];
|
|
var rng;
|
|
var s = 0;
|
|
|
|
while(!rng) {
|
|
rng = this.spytext.currentField.selectron.range();
|
|
if(s++ > 10000) return;
|
|
}
|
|
|
|
if(!rng) return;
|
|
|
|
if(rng.collapsed) {
|
|
tags = ancestors(rng.startContainer, null, this.spytext.currentField.element);
|
|
|
|
// The last element should always be the block element, such as P or UL.
|
|
} else {
|
|
var el = rng.commonAncestorContainer;
|
|
tags = ancestors(el, null, this.spytext.element);
|
|
}
|
|
|
|
if(tags.length > 0) blocks.push(tags.pop());
|
|
|
|
for(var i in this.buttons) {
|
|
var button = this.buttons[i];
|
|
if(button.config.options && $(tags).is(button.config.options.tag).length > 0) {
|
|
button.setActive();
|
|
} else button.unsetActive();
|
|
}
|
|
|
|
var blockTag;
|
|
for(var j = 0; j < blocks.length; j++) {
|
|
if(blockTag && blockTag !== blocks[j].tagName) {
|
|
blockTag = null;
|
|
break;
|
|
} else {
|
|
blockTag = blocks[j].tagName || null;
|
|
}
|
|
}
|
|
if(blockTag) setBlock(blockTag);
|
|
},
|
|
|
|
presets: {
|
|
standard: {
|
|
dropdowns: [ 'type' ],
|
|
buttonGroups: [
|
|
//{ name: 'block', buttons: ['typeHeading1', 'typeHeading2', 'typeHeading3', 'typeHeading4', 'typeHeading5', 'typeHeading6', 'typeParagraph']},
|
|
{ name: 'format', buttons: ['bold', 'italic', 'underline', 'strikeThrough', 'removeFormat']},
|
|
{ name: 'align', buttons: ['alignLeft', 'alignCenter', 'alignRight', 'alignJustify']},
|
|
{ name: 'list', buttons: ['unorderedList', 'orderedList']},
|
|
{ name: 'indent', buttons: ['indent', 'outdent']}
|
|
]
|
|
},
|
|
format: {
|
|
buttonGroups: [
|
|
{ name: 'format', buttons: ['bold', 'underline', 'strikeThrough', 'removeFormat']},
|
|
]
|
|
}
|
|
},
|
|
|
|
events: {
|
|
mousedown: function(e) {
|
|
// this is needed to prevent toolbar from stealing focus
|
|
e.preventDefault();
|
|
}
|
|
}
|
|
};
|
|
|