org.apache.myfaces.custom.inputHtml.resource.kupubasetools.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of tomahawk Show documentation
Show all versions of tomahawk Show documentation
JSF components and utilities that can be used with any JSF implementation.
This library is compatible with both JSF1.1 and JSF1.2; however for JSF1.2 users there
is an alternative build of Tomahawk available that takes advantage of JSF1.2 features to
offer some additional benefits.
/*****************************************************************************
*
* Copyright (c) 2003-2005 Kupu Contributors. All rights reserved.
*
* This software is distributed under the terms of the Kupu
* License. See LICENSE.txt for license text. For a list of Kupu
* Contributors see CREDITS.txt.
*
*****************************************************************************/
// $Id: kupubasetools.js 928511 2010-03-28 22:53:14Z lu4242 $
//----------------------------------------------------------------------------
//
// Toolboxes
//
// These are addons for Kupu, simple plugins that implement a certain
// interface to provide functionality and control view aspects.
//
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// Superclasses
//----------------------------------------------------------------------------
function KupuTool() {
/* Superclass (or actually more of an interface) for tools
Tools must implement at least an initialize method and an
updateState method, and can implement other methods to add
certain extra functionality (e.g. createContextMenuElements).
*/
this.toolboxes = {};
// private methods
addEventHandler = addEventHandler;
};
// methods
KupuTool.prototype.initialize = function(editor) {
/* Initialize the tool.
Obviously this can be overriden but it will do
for the most simple cases
*/
this.editor = editor;
};
KupuTool.prototype.registerToolBox = function(id, toolbox) {
/* register a ui box
Note that this needs to be called *after* the tool has been
registered to the KupuEditor
*/
this.toolboxes[id] = toolbox;
toolbox.initialize(this, this.editor);
};
KupuTool.prototype.updateState = function(selNode, event) {
/* Is called when user moves cursor to other element
Calls the updateState for all toolboxes and may want perform
some actions itself
*/
for (var id in this.toolboxes) {
this.toolboxes[id].updateState(selNode, event);
};
};
KupuTool.prototype.enable = function() {
// Called when the tool is enabled after a form is dismissed.
};
KupuTool.prototype.disable = function() {
// Called when the tool is disabled (e.g. for a modal form)
};
function KupuToolBox() {
/* Superclass for a user-interface object that controls a tool */
};
KupuToolBox.prototype.initialize = function(tool, editor) {
/* store a reference to the tool and the editor */
this.tool = tool;
this.editor = editor;
};
KupuToolBox.prototype.updateState = function(selNode, event) {
/* update the toolbox according to the current iframe's situation */
};
function noContextMenu(object) {
/* Decorator for a tool to suppress the context menu */
object.createContextMenuElements = function(selNode, event) {
return [];
};
return object;
}
// Helper function for enabling/disabling tools
function kupuButtonDisable(button) {
button = button || this.button;
if (button) {
button.disabled = "disabled";
button.className += ' disabled';
}
};
function kupuButtonEnable(button) {
button = button || this.button;
if (button) {
button.disabled = "";
button.className = button.className.replace(/ *\bdisabled\b/g, '');
}
};
//----------------------------------------------------------------------------
// Implementations
//----------------------------------------------------------------------------
function KupuButton(buttonid, commandfunc, tool) {
/* Base prototype for kupu button tools */
if (arguments.length) {
this.buttonid = buttonid;
this.button = getFromSelector(buttonid);
this.commandfunc = commandfunc;
this.tool = tool;
this.disable = kupuButtonDisable;
this.enable = kupuButtonEnable;
};
};
KupuButton.prototype = new KupuTool;
KupuButton.prototype.initialize = function(editor) {
this.editor = editor;
if (!this.button) return;
addEventHandler(this.button, 'click', this.execCommand, this);
};
KupuButton.prototype.execCommand = function() {
/* exec this button's command */
this.commandfunc(this, this.editor, this.tool);
};
KupuButton.prototype.updateState = function(selNode, event) {
/* override this in subclasses to determine whether a button should
look 'pressed in' or not
*/
};
function KupuStateButton(buttonid, commandfunc, checkfunc, offclass, onclass) {
/* A button that can have two states (e.g. pressed and
not-pressed) based on CSS classes */
this.buttonid = buttonid;
this.button = getFromSelector(buttonid);
this.commandfunc = commandfunc;
this.checkfunc = checkfunc;
this.offclass = offclass;
this.onclass = onclass;
this.pressed = false;
this.execCommand = function() {
/* exec this button's command */
this.button.className = (this.pressed ? this.offclass : this.onclass);
this.pressed = !this.pressed;
this.editor.focusDocument();
this.commandfunc(this, this.editor);
};
this.updateState = function(selNode, event) {
/* check if we need to be clicked or unclicked, and update accordingly
if the state of the button should be changed, we set the class
*/
if (!this.button) return;
var currclass = this.button.className;
var newclass = null;
if (this.checkfunc(selNode, this, this.editor, event)) {
newclass = this.onclass;
this.pressed = true;
} else {
newclass = this.offclass;
this.pressed = false;
};
if (currclass != newclass) {
this.button.className = newclass;
};
};
};
KupuStateButton.prototype = new KupuButton;
/* Same as the state button, but the focusDocument call is delayed.
* Mozilla&Firefox have a bug on windows which can cause a crash if you
* change CSS positioning styles on an element which has focus.
*/
function KupuLateFocusStateButton(buttonid, commandfunc, checkfunc,
offclass, onclass) {
KupuStateButton.apply(this, [buttonid, commandfunc, checkfunc,
offclass, onclass]);
}
KupuLateFocusStateButton.prototype = new KupuStateButton;
KupuLateFocusStateButton.prototype.execCommand = function() {
/* exec this button's command */
this.button.className = (this.pressed ? this.offclass : this.onclass);
this.pressed = !this.pressed;
this.commandfunc(this, this.editor);
this.editor.focusDocument();
};
function KupuRemoveElementButton(buttonid, element_name, cssclass) {
/* A button specialized in removing elements in the current node
context. Typical usages include removing links, images, etc. */
this.button = getFromSelector(buttonid);
this.element_name = element_name;
this.onclass = 'invisible';
this.offclass = cssclass;
this.pressed = false;
};
KupuRemoveElementButton.prototype = new KupuStateButton;
KupuRemoveElementButton.prototype.commandfunc = function(button, editor) {
editor.focusDocument();
editor.removeNearestParentOfType(editor.getSelectedNode(), this.element_name);
editor.updateState();
};
KupuRemoveElementButton.prototype.checkfunc = function(currnode, button,
editor, event) {
var element = editor.getNearestParentOfType(currnode, this.element_name);
return (element ? false : true);
};
function KupuUI(textstyleselectid) {
/* View
This is the main view, which controls most of the toolbar buttons.
Even though this is probably never going to be removed from the view,
it was easier to implement this as a plain tool (plugin) as well.
*/
// attributes
this.tsselect = getFromSelector(textstyleselectid);
this.paraoptions = [];
this.tableoptions = [];
this.styleoptions = [];
this.tableoffset = 0;
this.styleoffset = 0;
this.tablegrp = null;
this.optionstate = -1;
this.otherstyle = null;
this.tablestyles = {};
this.charstyles = {};
this.styles = {}; // use an object here so we can use the 'in' operator later on
this.blocktagre = /^(p|div|h.|ul|ol|dl|menu|dir|pre|blockquote|address|center)$/i;
this.spanre = /^span\b/i;
this.tblre = /^thead|tbody|table|t[rdh]\b/i;
};
KupuUI.prototype = new KupuTool;
KupuUI.prototype.initialize = function(editor) {
/* initialize the ui like tools */
this.editor = editor;
this.cleanStyles();
this.enableOptions(false);
if (this.tsselect) {
this._selectevent = addEventHandler(this.tsselect, 'change', this.setTextStyleHandler, this);
}
};
KupuUI.prototype.getStyles = function() {
if (!this.paraoptions) {
this.cleanStyles();
}
return [ this.paraoptions, this.tableoptions ];
};
KupuUI.prototype.setTextStyleHandler = function(event) {
this.setTextStyle(this.tsselect.options[this.tsselect.selectedIndex].value);
};
// event handlers
KupuUI.prototype.basicButtonHandler = function(action) {
/* event handler for basic actions (toolbar buttons) */
this.editor.execCommand(action);
this.editor.updateState();
};
KupuUI.prototype.saveButtonHandler = function() {
/* handler for the save button */
this.editor.saveDocument();
};
KupuUI.prototype.saveAndExitButtonHandler = function(redirect_url) {
/* save the document and, if successful, redirect */
this.editor.saveDocument(redirect_url);
};
KupuUI.prototype.cutButtonHandler = function() {
try {
this.editor.execCommand('Cut');
} catch (e) {
if (this.editor.getBrowserName() == 'Mozilla') {
alert(_('Cutting from JavaScript is disabled on your Mozilla due to security settings. For more information, read http://www.mozilla.org/editor/midasdemo/securityprefs.html'));
} else {
throw e;
};
};
this.editor.updateState();
};
KupuUI.prototype.copyButtonHandler = function() {
try {
this.editor.execCommand('Copy');
} catch (e) {
if (this.editor.getBrowserName() == 'Mozilla') {
alert(_('Copying from JavaScript is disabled on your Mozilla due to security settings. For more information, read http://www.mozilla.org/editor/midasdemo/securityprefs.html'));
} else {
throw e;
};
};
this.editor.updateState();
};
KupuUI.prototype.pasteButtonHandler = function() {
try {
this.editor.execCommand('Paste');
} catch (e) {
if (this.editor.getBrowserName() == 'Mozilla') {
alert(_('Pasting from JavaScript is disabled on your Mozilla due to security settings. For more information, read http://www.mozilla.org/editor/midasdemo/securityprefs.html'));
} else {
throw e;
};
};
this.editor.updateState();
};
KupuUI.prototype.cleanStyles = function() {
if (!this.tsselect) return;
var options = this.tsselect.options;
var parastyles = this.styles;
var tablestyles = this.tablestyles;
var charstyles = this.charstyles;
var normal = ['Normal', 'p|'];
var td = ['Plain Cell', 'td|'];
var nostyle = ['(remove style)', ''];
var opts = [];
while (options.length) {
var opt = options[0];
options[0] = null;
var v = opt.value;
if (v.indexOf('|') > -1) {
var split = v.split('|');
v = split[0].toLowerCase() + "|" + split[1];
} else {
v = v.toLowerCase()+"|";
};
var optarray = [opt.text, v];
if (v=='td|') {
td = optarray;
} else if (v=='p|') {
normal = optarray;
} else if (v=='') {
nostyle = optarray;
} else {
opts.push([opt.text,v]);
}
}
this.tableoptions.push(td);
tablestyles[td[1]] = 0;
this.paraoptions.push(normal);
parastyles[normal[1]] = 0;
for (var i = 0; i < opts.length; i++) {
optarray = opts[i];
v = optarray[1];
if (this.spanre.test(v)) {
charstyles[v] = this.styleoptions.length;
this.styleoptions.push(optarray);
} else if (this.tblre.test(v)) {
tablestyles[v] = this.tableoptions.length;
this.tableoptions.push(optarray);
} else {
parastyles[v] = this.paraoptions.length;
this.paraoptions.push(optarray);
};
};
this.paraoptions.push(nostyle);
this.styleoffset = this.paraoptions.length;
this.tableoffset = this.styleoffset + this.styleoptions.length;
};
// Remove otherstyle and switch to appropriate style set.
KupuUI.prototype.enableOptions = function(inTable) {
if (!this.tsselect) return;
var select = this.tsselect;
var options = select.options;
if (this.otherstyle) {
options[0] = null;
this.otherstyle = null;
}
if (this.optionstate == inTable) return; /* No change */
// while (select.firstChild) select.removeChild(select.firstChild);
function option(info) {
return newElement('option', {'value': info[1]}, [info[0]]);
}
if (this.optionstate==-1) {
for (var i = 0; i < this.paraoptions.length; i++) {
select.appendChild(option(this.paraoptions[i]));
}
if (this.styleoptions.length) {
var grp = document.createElement('optgroup');
grp.label = 'Character styles';
for (var i = 0; i < this.styleoptions.length; i++) {
grp.appendChild(option(this.styleoptions[i]));
}
select.appendChild(grp);
}
}
if (inTable) {
var grp = (this.tablegrp = document.createElement('optgroup'));
grp.label = 'Table elements';
for (var i = 0; i < this.tableoptions.length; i++) {
grp.appendChild(option(this.tableoptions[i]));
}
select.appendChild(grp);
} else {
while (select.options[this.tableoffset]) {
select.options[this.tableoffset] = null;
};
if (this.tablegrp) {
select.removeChild(this.tablegrp);
this.tablegrp = null;
};
};
this.optionstate = inTable;
};
KupuUI.prototype.setIndex = function(currnode, tag, index, styles) {
var className = currnode.className;
this.styletag = tag;
this.classname = className;
var style = tag+'|'+className;
if (style in styles) {
return styles[style];
} else if (!className && tag in styles) {
return styles[tag];
}
return index;
};
KupuUI.prototype.nodeStyle = function(node) {
var currnode = node;
var index = -1;
this.styletag = undefined;
this.classname = '';
// Set the table state correctly
this.intable = false;
while(currnode) {
var tag = currnode.nodeName;
if (/^body$/i.test(tag)) break;
if (this.tblre.test(tag)) {
this.intable = true;
break;
};
currnode = currnode.parentNode;
};
currnode = node;
while (currnode) {
var tag = currnode.nodeName.toLowerCase();
if (/^body$/.test(tag)) {
if (!this.styletag) {
// Forced style messes up in Firefox: return -1 to
// indicate no style
return -1;
}
break;
}
if (this.spanre.test(tag)) {
index = this.setIndex(currnode, tag, index, this.charstyles);
if (index >= 0) return index+this.styleoffset; // span takes priority
} else if (this.blocktagre.test(tag)) {
index = this.setIndex(currnode, tag, index, this.styles);
} else if (this.tblre.test(tag)) {
if (index > 0) return index; // block or span takes priority.
index = this.setIndex(currnode, tag, index, this.tablestyles);
if (index >= 0 || tag=='table') {
return index+this.tableoffset; // Stop processing if in a table
}
}
currnode = currnode.parentNode;
}
return index;
};
KupuUI.prototype.updateState = function(selNode) {
/* set the text-style pulldown */
// first get the nearest style
// search the list of nodes like in the original one, break if we encounter a match,
// this method does some more than the original one since it can handle commands in
// the form of '