Merged 3.1 to HEAD

13275: updated web-client to use tinymce v3
 13276: overlay display fix for when field has large content


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@13585 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Lawrence Carvalho
2009-03-12 10:00:20 +00:00
parent f6b762476a
commit d5fbd06a47
380 changed files with 55391 additions and 11133 deletions

View File

@@ -0,0 +1,68 @@
/**
* $Id: Button.js 793 2008-04-10 17:32:40Z spocke $
*
* @author Moxiecode
* @copyright Copyright <20> 2004-2008, Moxiecode Systems AB, All rights reserved.
*/
(function() {
var DOM = tinymce.DOM;
/**#@+
* @class This class is used to create a UI button. A button is basically a link
* that is styled to look like a button or icon.
* @member tinymce.ui.Button
* @base tinymce.ui.Control
*/
tinymce.create('tinymce.ui.Button:tinymce.ui.Control', {
/**
* Constructs a new button control instance.
*
* @param {String} id Control id for the button.
* @param {Object} s Optional name/value settings object.
*/
Button : function(id, s) {
this.parent(id, s);
this.classPrefix = 'mceButton';
},
/**#@+
* @method
*/
/**
* Renders the button as a HTML string. This method is much faster than using the DOM and when
* creating a whole toolbar with buttons it does make a lot of difference.
*
* @return {String} HTML for the button control element.
*/
renderHTML : function() {
var cp = this.classPrefix, s = this.settings, h, l;
l = DOM.encode(s.label || '');
h = '<a id="' + this.id + '" href="javascript:;" class="' + cp + ' ' + cp + 'Enabled ' + s['class'] + (l ? ' ' + cp + 'Labeled' : '') +'" onmousedown="return false;" onclick="return false;" title="' + DOM.encode(s.title) + '">';
if (s.image)
h += '<img class="mceIcon" src="' + s.image + '" />' + l + '</a>';
else
h += '<span class="mceIcon ' + s['class'] + '"></span>' + (l ? '<span class="' + cp + 'Label">' + l + '</span>' : '') + '</a>';
return h;
},
/**
* Post render handler. This function will be called after the UI has been
* rendered so that events can be added.
*/
postRender : function() {
var t = this, s = t.settings;
tinymce.dom.Event.add(t.id, 'click', function(e) {
if (!t.isDisabled())
return s.onclick.call(s.scope, e);
});
}
/**#@-*/
});
})();

View File

@@ -0,0 +1,213 @@
/**
* $Id: ColorSplitButton.js 960 2008-11-12 18:30:32Z spocke $
*
* @author Moxiecode
* @copyright Copyright <20> 2004-2008, Moxiecode Systems AB, All rights reserved.
*/
(function() {
var DOM = tinymce.DOM, Event = tinymce.dom.Event, is = tinymce.is, each = tinymce.each;
/**#@+
* @class This class is used to create UI color split button. A color split button will present show a small color picker
* when you press the open menu.
* @member tinymce.ui.ColorSplitButton
* @base tinymce.ui.SplitButton
*/
tinymce.create('tinymce.ui.ColorSplitButton:tinymce.ui.SplitButton', {
/**
* Constructs a new color split button control instance.
*
* @param {String} id Control id for the color split button.
* @param {Object} s Optional name/value settings object.
*/
ColorSplitButton : function(id, s) {
var t = this;
t.parent(id, s);
t.settings = s = tinymce.extend({
colors : '000000,993300,333300,003300,003366,000080,333399,333333,800000,FF6600,808000,008000,008080,0000FF,666699,808080,FF0000,FF9900,99CC00,339966,33CCCC,3366FF,800080,999999,FF00FF,FFCC00,FFFF00,00FF00,00FFFF,00CCFF,993366,C0C0C0,FF99CC,FFCC99,FFFF99,CCFFCC,CCFFFF,99CCFF,CC99FF,FFFFFF',
grid_width : 8,
default_color : '#888888'
}, t.settings);
t.onShowMenu = new tinymce.util.Dispatcher(t);
t.onHideMenu = new tinymce.util.Dispatcher(t);
t.value = s.default_color;
},
/**#@+
* @method
*/
/**
* Shows the color menu. The color menu is a layer places under the button
* and displays a table of colors for the user to pick from.
*/
showMenu : function() {
var t = this, r, p, e, p2;
if (t.isDisabled())
return;
if (!t.isMenuRendered) {
t.renderMenu();
t.isMenuRendered = true;
}
if (t.isMenuVisible)
return t.hideMenu();
e = DOM.get(t.id);
DOM.show(t.id + '_menu');
DOM.addClass(e, 'mceSplitButtonSelected');
p2 = DOM.getPos(e);
DOM.setStyles(t.id + '_menu', {
left : p2.x,
top : p2.y + e.clientHeight,
zIndex : 200000
});
e = 0;
Event.add(DOM.doc, 'mousedown', t.hideMenu, t);
if (t._focused) {
t._keyHandler = Event.add(t.id + '_menu', 'keydown', function(e) {
if (e.keyCode == 27)
t.hideMenu();
});
DOM.select('a', t.id + '_menu')[0].focus(); // Select first link
}
t.onShowMenu.dispatch(t);
t.isMenuVisible = 1;
},
/**
* Hides the color menu. The optional event parameter is used to check where the event occured so it
* doesn't close them menu if it was a event inside the menu.
*
* @param {Event} e Optional event object.
*/
hideMenu : function(e) {
var t = this;
// Prevent double toogles by canceling the mouse click event to the button
if (e && e.type == "mousedown" && DOM.getParent(e.target, function(e) {return e.id === t.id + '_open';}))
return;
if (!e || !DOM.getParent(e.target, function(n) {return DOM.hasClass(n, 'mceSplitButtonMenu');})) {
DOM.removeClass(t.id, 'mceSplitButtonSelected');
Event.remove(DOM.doc, 'mousedown', t.hideMenu, t);
Event.remove(t.id + '_menu', 'keydown', t._keyHandler);
DOM.hide(t.id + '_menu');
}
t.onHideMenu.dispatch(t);
t.isMenuVisible = 0;
},
/**
* Renders the menu to the DOM.
*/
renderMenu : function() {
var t = this, m, i = 0, s = t.settings, n, tb, tr, w;
w = DOM.add(s.menu_container, 'div', {id : t.id + '_menu', 'class' : s['menu_class'] + ' ' + s['class'], style : 'position:absolute;left:0;top:-1000px;'});
m = DOM.add(w, 'div', {'class' : s['class'] + ' mceSplitButtonMenu'});
DOM.add(m, 'span', {'class' : 'mceMenuLine'});
n = DOM.add(m, 'table', {'class' : 'mceColorSplitMenu'});
tb = DOM.add(n, 'tbody');
// Generate color grid
i = 0;
each(is(s.colors, 'array') ? s.colors : s.colors.split(','), function(c) {
c = c.replace(/^#/, '');
if (!i--) {
tr = DOM.add(tb, 'tr');
i = s.grid_width - 1;
}
n = DOM.add(tr, 'td');
n = DOM.add(n, 'a', {
href : 'javascript:;',
style : {
backgroundColor : '#' + c
},
mce_color : '#' + c
});
});
if (s.more_colors_func) {
n = DOM.add(tb, 'tr');
n = DOM.add(n, 'td', {colspan : s.grid_width, 'class' : 'mceMoreColors'});
n = DOM.add(n, 'a', {id : t.id + '_more', href : 'javascript:;', onclick : 'return false;', 'class' : 'mceMoreColors'}, s.more_colors_title);
Event.add(n, 'click', function(e) {
s.more_colors_func.call(s.more_colors_scope || this);
return Event.cancel(e); // Cancel to fix onbeforeunload problem
});
}
DOM.addClass(m, 'mceColorSplitMenu');
Event.add(t.id + '_menu', 'click', function(e) {
var c;
e = e.target;
if (e.nodeName == 'A' && (c = e.getAttribute('mce_color')))
t.setColor(c);
return Event.cancel(e); // Prevent IE auto save warning
});
return w;
},
/**
* Sets the current color for the control and hides the menu if it should be visible.
*
* @param {String} c Color code value in hex for example: #FF00FF
*/
setColor : function(c) {
var t = this;
DOM.setStyle(t.id + '_preview', 'backgroundColor', c);
t.value = c;
t.hideMenu();
t.settings.onselect(c);
},
postRender : function() {
var t = this, id = t.id;
t.parent();
DOM.add(id + '_action', 'div', {id : id + '_preview', 'class' : 'mceColorPreview'});
DOM.setStyle(t.id + '_preview', 'backgroundColor', t.value);
},
/**
* Destroys the control. This means it will be removed from the DOM and any
* events tied to it will also be removed.
*/
destroy : function() {
this.parent();
Event.clear(this.id + '_menu');
Event.clear(this.id + '_more');
DOM.remove(this.id + '_menu');
}
/**#@-*/
});
})();

View File

@@ -0,0 +1,56 @@
/**
* $Id: Container.js 520 2008-01-07 16:30:32Z spocke $
*
* @author Moxiecode
* @copyright Copyright <20> 2004-2008, Moxiecode Systems AB, All rights reserved.
*/
/**#@+
* @class This class is the base class for all container controls like toolbars. This class should not
* be instantiated directly other container controls should inherit from this one.
* @member tinymce.ui.Container
* @base tinymce.ui.Control
*/
tinymce.create('tinymce.ui.Container:tinymce.ui.Control', {
/**
* Base contrustor a new container control instance.
*
* @param {String} id Control id to use for the container.
* @param {Object} s Optional name/value settings object.
*/
Container : function(id, s) {
this.parent(id, s);
this.controls = [];
this.lookup = {};
},
/**#@+
* @method
*/
/**
* Adds a control to the collection of controls for the container.
*
* @param {tinymce.ui.Control} c Control instance to add to the container.
* @return {tinymce.ui.Control} Same control instance that got passed in.
*/
add : function(c) {
this.lookup[c.id] = c;
this.controls.push(c);
return c;
},
/**
* Returns a control by id from the containers collection.
*
* @param {String} n Id for the control to retrive.
* @return {tinymce.ui.Control} Control instance by the specified name or undefined if it wasn't found.
*/
get : function(n) {
return this.lookup[n];
}
/**#@-*/
});

View File

@@ -0,0 +1,182 @@
/**
* $Id: Control.js 755 2008-03-29 19:14:42Z spocke $
*
* @author Moxiecode
* @copyright Copyright <20> 2004-2008, Moxiecode Systems AB, All rights reserved.
*/
(function() {
// Shorten class names
var DOM = tinymce.DOM, is = tinymce.is;
/**#@+
* @class This class is the base class for all controls like buttons, toolbars, containers. This class should not
* be instantiated directly other controls should inherit from this one.
* @member tinymce.ui.Control
*/
tinymce.create('tinymce.ui.Control', {
/**
* Constructs a new control instance.
*
* @param {String} id Control id.
* @param {Object} s Optional name/value settings object.
*/
Control : function(id, s) {
this.id = id;
this.settings = s = s || {};
this.rendered = false;
this.onRender = new tinymce.util.Dispatcher(this);
this.classPrefix = '';
this.scope = s.scope || this;
this.disabled = 0;
this.active = 0;
},
/**#@+
* @method
*/
/**
* Sets the disabled state for the control. This will add CSS classes to the
* element that contains the control. So that it can be disabled visually.
*
* @param {bool} s Boolean state if the control should be disabled or not.
*/
setDisabled : function(s) {
var e;
if (s != this.disabled) {
e = DOM.get(this.id);
// Add accessibility title for unavailable actions
if (e && this.settings.unavailable_prefix) {
if (s) {
this.prevTitle = e.title;
e.title = this.settings.unavailable_prefix + ": " + e.title;
} else
e.title = this.prevTitle;
}
this.setState('Disabled', s);
this.setState('Enabled', !s);
this.disabled = s;
}
},
/**
* Returns true/false if the control is disabled or not. This is a method since you can then
* choose to check some class or some internal bool state in subclasses.
*
* @return {bool} true/false if the control is disabled or not.
*/
isDisabled : function() {
return this.disabled;
},
/**
* Sets the activated state for the control. This will add CSS classes to the
* element that contains the control. So that it can be activated visually.
*
* @param {bool} s Boolean state if the control should be activated or not.
*/
setActive : function(s) {
if (s != this.active) {
this.setState('Active', s);
this.active = s;
}
},
/**
* Returns true/false if the control is disabled or not. This is a method since you can then
* choose to check some class or some internal bool state in subclasses.
*
* @return {bool} true/false if the control is disabled or not.
*/
isActive : function() {
return this.active;
},
/**
* Sets the specified class state for the control.
*
* @param {String} c Class name to add/remove depending on state.
* @param {bool} s True/false state if the class should be removed or added.
*/
setState : function(c, s) {
var n = DOM.get(this.id);
c = this.classPrefix + c;
if (s)
DOM.addClass(n, c);
else
DOM.removeClass(n, c);
},
/**
* Returns true/false if the control has been rendered or not.
*
* @return {bool} State if the control has been rendered or not.
*/
isRendered : function() {
return this.rendered;
},
/**
* Renders the control as a HTML string. This method is much faster than using the DOM and when
* creating a whole toolbar with buttons it does make a lot of difference.
*
* @return {String} HTML for the button control element.
*/
renderHTML : function() {
},
/**
* Renders the control to the specified container element.
*
* @param {Element} n HTML DOM element to add control to.
*/
renderTo : function(n) {
DOM.setHTML(n, this.renderHTML());
},
/**
* Post render event. This will be executed after the control has been rendered and can be used to
* set states, add events to the control etc. It's recommended for subclasses of the control to call this method by using this.parent().
*/
postRender : function() {
var t = this, b;
// Set pending states
if (is(t.disabled)) {
b = t.disabled;
t.disabled = -1;
t.setDisabled(b);
}
if (is(t.active)) {
b = t.active;
t.active = -1;
t.setActive(b);
}
},
/**
* Removes the control. This means it will be removed from the DOM and any
* events tied to it will also be removed.
*/
remove : function() {
DOM.remove(this.id);
this.destroy();
},
/**
* Destroys the control will free any memory by removing event listeners etc.
*/
destroy : function() {
tinymce.dom.Event.clear(this.id);
}
/**#@-*/
});
})();

View File

@@ -0,0 +1,397 @@
/**
* $Id: DropMenu.js 939 2008-10-13 15:47:19Z spocke $
*
* @author Moxiecode
* @copyright Copyright <20> 2004-2008, Moxiecode Systems AB, All rights reserved.
*/
(function() {
var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, Event = tinymce.dom.Event, Element = tinymce.dom.Element;
/**#@+
* @class This class is used to create drop menus, a drop menu can be a
* context menu, or a menu for a list box or a menu bar.
* @member tinymce.ui.DropMenu
* @base tinymce.ui.Menu
*/
tinymce.create('tinymce.ui.DropMenu:tinymce.ui.Menu', {
/**
* Constructs a new drop menu control instance.
*
* @param {String} id Button control id for the button.
* @param {Object} s Optional name/value settings object.
*/
DropMenu : function(id, s) {
s = s || {};
s.container = s.container || DOM.doc.body;
s.offset_x = s.offset_x || 0;
s.offset_y = s.offset_y || 0;
s.vp_offset_x = s.vp_offset_x || 0;
s.vp_offset_y = s.vp_offset_y || 0;
if (is(s.icons) && !s.icons)
s['class'] += ' mceNoIcons';
this.parent(id, s);
this.onShowMenu = new tinymce.util.Dispatcher(this);
this.onHideMenu = new tinymce.util.Dispatcher(this);
this.classPrefix = 'mceMenu';
},
/**#@+
* @method
*/
/**
* Created a new sub menu for the drop menu control.
*
* @param {Object} s Optional name/value settings object.
* @return {tinymce.ui.DropMenu} New drop menu instance.
*/
createMenu : function(s) {
var t = this, cs = t.settings, m;
s.container = s.container || cs.container;
s.parent = t;
s.constrain = s.constrain || cs.constrain;
s['class'] = s['class'] || cs['class'];
s.vp_offset_x = s.vp_offset_x || cs.vp_offset_x;
s.vp_offset_y = s.vp_offset_y || cs.vp_offset_y;
m = new tinymce.ui.DropMenu(s.id || DOM.uniqueId(), s);
m.onAddItem.add(t.onAddItem.dispatch, t.onAddItem);
return m;
},
/**
* Repaints the menu after new items have been added dynamically.
*/
update : function() {
var t = this, s = t.settings, tb = DOM.get('menu_' + t.id + '_tbl'), co = DOM.get('menu_' + t.id + '_co'), tw, th;
tw = s.max_width ? Math.min(tb.clientWidth, s.max_width) : tb.clientWidth;
th = s.max_height ? Math.min(tb.clientHeight, s.max_height) : tb.clientHeight;
if (!DOM.boxModel)
t.element.setStyles({width : tw + 2, height : th + 2});
else
t.element.setStyles({width : tw, height : th});
if (s.max_width)
DOM.setStyle(co, 'width', tw);
if (s.max_height) {
DOM.setStyle(co, 'height', th);
if (tb.clientHeight < s.max_height)
DOM.setStyle(co, 'overflow', 'hidden');
}
},
/**
* Displays the menu at the specified cordinate.
*
* @param {Number} x Horizontal position of the menu.
* @param {Number} y Vertical position of the menu.
* @param {Numner} px Optional parent X position used when menus are cascading.
*/
showMenu : function(x, y, px) {
var t = this, s = t.settings, co, vp = DOM.getViewPort(), w, h, mx, my, ot = 2, dm, tb, cp = t.classPrefix;
t.collapse(1);
if (t.isMenuVisible)
return;
if (!t.rendered) {
co = DOM.add(t.settings.container, t.renderNode());
each(t.items, function(o) {
o.postRender();
});
t.element = new Element('menu_' + t.id, {blocker : 1, container : s.container});
} else
co = DOM.get('menu_' + t.id);
// Move layer out of sight unless it's Opera since it scrolls to top of page due to an bug
if (!tinymce.isOpera)
DOM.setStyles(co, {left : -0xFFFF , top : -0xFFFF});
DOM.show(co);
t.update();
x += s.offset_x || 0;
y += s.offset_y || 0;
vp.w -= 4;
vp.h -= 4;
// Move inside viewport if not submenu
if (s.constrain) {
w = co.clientWidth - ot;
h = co.clientHeight - ot;
mx = vp.x + vp.w;
my = vp.y + vp.h;
if ((x + s.vp_offset_x + w) > mx)
x = px ? px - w : Math.max(0, (mx - s.vp_offset_x) - w);
if ((y + s.vp_offset_y + h) > my)
y = Math.max(0, (my - s.vp_offset_y) - h);
}
DOM.setStyles(co, {left : x , top : y});
t.element.update();
t.isMenuVisible = 1;
t.mouseClickFunc = Event.add(co, 'click', function(e) {
var m;
e = e.target;
if (e && (e = DOM.getParent(e, 'TR')) && !DOM.hasClass(e, cp + 'ItemSub')) {
m = t.items[e.id];
if (m.isDisabled())
return;
dm = t;
while (dm) {
if (dm.hideMenu)
dm.hideMenu();
dm = dm.settings.parent;
}
if (m.settings.onclick)
m.settings.onclick(e);
return Event.cancel(e); // Cancel to fix onbeforeunload problem
}
});
if (t.hasMenus()) {
t.mouseOverFunc = Event.add(co, 'mouseover', function(e) {
var m, r, mi;
e = e.target;
if (e && (e = DOM.getParent(e, 'TR'))) {
m = t.items[e.id];
if (t.lastMenu)
t.lastMenu.collapse(1);
if (m.isDisabled())
return;
if (e && DOM.hasClass(e, cp + 'ItemSub')) {
//p = DOM.getPos(s.container);
r = DOM.getRect(e);
m.showMenu((r.x + r.w - ot), r.y - ot, r.x);
t.lastMenu = m;
DOM.addClass(DOM.get(m.id).firstChild, cp + 'ItemActive');
}
}
});
}
t.onShowMenu.dispatch(t);
if (s.keyboard_focus) {
Event.add(co, 'keydown', t._keyHandler, t);
DOM.select('a', 'menu_' + t.id)[0].focus(); // Select first link
t._focusIdx = 0;
}
},
/**
* Hides the displayed menu.
*/
hideMenu : function(c) {
var t = this, co = DOM.get('menu_' + t.id), e;
if (!t.isMenuVisible)
return;
Event.remove(co, 'mouseover', t.mouseOverFunc);
Event.remove(co, 'click', t.mouseClickFunc);
Event.remove(co, 'keydown', t._keyHandler);
DOM.hide(co);
t.isMenuVisible = 0;
if (!c)
t.collapse(1);
if (t.element)
t.element.hide();
if (e = DOM.get(t.id))
DOM.removeClass(e.firstChild, t.classPrefix + 'ItemActive');
t.onHideMenu.dispatch(t);
},
/**
* Adds a new menu, menu item or sub classes of them to the drop menu.
*
* @param {tinymce.ui.Control} o Menu or menu item to add to the drop menu.
* @return {tinymce.ui.Control} Same as the input control, the menu or menu item.
*/
add : function(o) {
var t = this, co;
o = t.parent(o);
if (t.isRendered && (co = DOM.get('menu_' + t.id)))
t._add(DOM.select('tbody', co)[0], o);
return o;
},
/**
* Collapses the menu, this will hide the menu and all menu items.
*
* @param {bool} d Optional deep state. If this is set to true all children will be collapsed as well.
*/
collapse : function(d) {
this.parent(d);
this.hideMenu(1);
},
/**
* Removes a specific sub menu or menu item from the drop menu.
*
* @param {tinymce.ui.Control} o Menu item or menu to remove from drop menu.
* @return {tinymce.ui.Control} Control instance or null if it wasn't found.
*/
remove : function(o) {
DOM.remove(o.id);
this.destroy();
return this.parent(o);
},
/**
* Destroys the menu. This will remove the menu from the DOM and any events added to it etc.
*/
destroy : function() {
var t = this, co = DOM.get('menu_' + t.id);
Event.remove(co, 'mouseover', t.mouseOverFunc);
Event.remove(co, 'click', t.mouseClickFunc);
if (t.element)
t.element.remove();
DOM.remove(co);
},
/**
* Renders the specified menu node to the dom.
*
* @return {Element} Container element for the drop menu.
*/
renderNode : function() {
var t = this, s = t.settings, n, tb, co, w;
w = DOM.create('div', {id : 'menu_' + t.id, 'class' : s['class'], 'style' : 'position:absolute;left:0;top:0;z-index:200000'});
co = DOM.add(w, 'div', {id : 'menu_' + t.id + '_co', 'class' : t.classPrefix + (s['class'] ? ' ' + s['class'] : '')});
t.element = new Element('menu_' + t.id, {blocker : 1, container : s.container});
if (s.menu_line)
DOM.add(co, 'span', {'class' : t.classPrefix + 'Line'});
// n = DOM.add(co, 'div', {id : 'menu_' + t.id + '_co', 'class' : 'mceMenuContainer'});
n = DOM.add(co, 'table', {id : 'menu_' + t.id + '_tbl', border : 0, cellPadding : 0, cellSpacing : 0});
tb = DOM.add(n, 'tbody');
each(t.items, function(o) {
t._add(tb, o);
});
t.rendered = true;
return w;
},
// Internal functions
_keyHandler : function(e) {
var t = this, kc = e.keyCode;
function focus(d) {
var i = t._focusIdx + d, e = DOM.select('a', 'menu_' + t.id)[i];
if (e) {
t._focusIdx = i;
e.focus();
}
};
switch (kc) {
case 38:
focus(-1); // Select first link
return;
case 40:
focus(1);
return;
case 13:
return;
case 27:
return this.hideMenu();
}
},
_add : function(tb, o) {
var n, s = o.settings, a, ro, it, cp = this.classPrefix, ic;
if (s.separator) {
ro = DOM.add(tb, 'tr', {id : o.id, 'class' : cp + 'ItemSeparator'});
DOM.add(ro, 'td', {'class' : cp + 'ItemSeparator'});
if (n = ro.previousSibling)
DOM.addClass(n, 'mceLast');
return;
}
n = ro = DOM.add(tb, 'tr', {id : o.id, 'class' : cp + 'Item ' + cp + 'ItemEnabled'});
n = it = DOM.add(n, 'td');
n = a = DOM.add(n, 'a', {href : 'javascript:;', onclick : "return false;", onmousedown : 'return false;'});
DOM.addClass(it, s['class']);
// n = DOM.add(n, 'span', {'class' : 'item'});
ic = DOM.add(n, 'span', {'class' : 'mceIcon' + (s.icon ? ' mce_' + s.icon : '')});
if (s.icon_src)
DOM.add(ic, 'img', {src : s.icon_src});
n = DOM.add(n, s.element || 'span', {'class' : 'mceText', title : o.settings.title}, o.settings.title);
if (o.settings.style)
DOM.setAttrib(n, 'style', o.settings.style);
if (tb.childNodes.length == 1)
DOM.addClass(ro, 'mceFirst');
if ((n = ro.previousSibling) && DOM.hasClass(n, cp + 'ItemSeparator'))
DOM.addClass(ro, 'mceFirst');
if (o.collapse)
DOM.addClass(ro, cp + 'ItemSub');
if (n = ro.previousSibling)
DOM.removeClass(n, 'mceLast');
DOM.addClass(ro, 'mceLast');
}
/**#@-*/
});
})();

View File

@@ -0,0 +1,320 @@
/**
* $Id: ListBox.js 933 2008-09-27 08:41:46Z spocke $
*
* @author Moxiecode
* @copyright Copyright <20> 2004-2008, Moxiecode Systems AB, All rights reserved.
*/
(function() {
var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher;
/**#@+
* @class This class is used to create list boxes/select list. This one will generate
* a non native control. This one has the benefits of having visual items added.
* @member tinymce.ui.ListBox
* @base tinymce.ui.Control
*/
tinymce.create('tinymce.ui.ListBox:tinymce.ui.Control', {
/**
* Constructs a new listbox control instance.
*
* @param {String} id Control id for the list box.
* @param {Object} s Optional name/value settings object.
*/
ListBox : function(id, s) {
var t = this;
t.parent(id, s);
t.items = [];
t.onChange = new Dispatcher(t);
t.onPostRender = new Dispatcher(t);
t.onAdd = new Dispatcher(t);
t.onRenderMenu = new tinymce.util.Dispatcher(this);
t.classPrefix = 'mceListBox';
},
/**#@+
* @method
*/
/**
* Selects a item/option by value. This will both add a visual selection to the
* item and change the title of the control to the title of the option.
*
* @param {String/function} va Value to look for inside the list box or a function selector.
*/
select : function(va) {
var t = this, fv, f;
if (va == undefined)
return t.selectByIndex(-1);
// Is string or number make function selector
if (va && va.call)
f = va;
else {
f = function(v) {
return v == va;
};
}
// Do we need to do something?
if (va != t.selectedValue) {
// Find item
each(t.items, function(o, i) {
if (f(o.value)) {
fv = 1;
t.selectByIndex(i);
return false;
}
});
if (!fv)
t.selectByIndex(-1);
}
},
/**
* Selects a item/option by index. This will both add a visual selection to the
* item and change the title of the control to the title of the option.
*
* @param {String} idx Index to select, pass -1 to select menu/title of select box.
*/
selectByIndex : function(idx) {
var t = this, e, o;
if (idx != t.selectedIndex) {
e = DOM.get(t.id + '_text');
o = t.items[idx];
if (o) {
t.selectedValue = o.value;
t.selectedIndex = idx;
DOM.setHTML(e, DOM.encode(o.title));
DOM.removeClass(e, 'mceTitle');
} else {
DOM.setHTML(e, DOM.encode(t.settings.title));
DOM.addClass(e, 'mceTitle');
t.selectedValue = t.selectedIndex = null;
}
e = 0;
} else
t.selectedValue = t.selectedIndex = null;
},
/**
* Adds a option item to the list box.
*
* @param {String} n Title for the new option.
* @param {String} v Value for the new option.
* @param {Object} o Optional object with settings like for example class.
*/
add : function(n, v, o) {
var t = this;
o = o || {};
o = tinymce.extend(o, {
title : n,
value : v
});
t.items.push(o);
t.onAdd.dispatch(t, o);
},
/**
* Returns the number of items inside the list box.
*
* @param {Number} Number of items inside the list box.
*/
getLength : function() {
return this.items.length;
},
/**
* Renders the list box as a HTML string. This method is much faster than using the DOM and when
* creating a whole toolbar with buttons it does make a lot of difference.
*
* @return {String} HTML for the list box control element.
*/
renderHTML : function() {
var h = '', t = this, s = t.settings, cp = t.classPrefix;
h = '<table id="' + t.id + '" cellpadding="0" cellspacing="0" class="' + cp + ' ' + cp + 'Enabled' + (s['class'] ? (' ' + s['class']) : '') + '"><tbody><tr>';
h += '<td>' + DOM.createHTML('a', {id : t.id + '_text', href : 'javascript:;', 'class' : 'mceText', onclick : "return false;", onmousedown : 'return false;'}, DOM.encode(t.settings.title)) + '</td>';
h += '<td>' + DOM.createHTML('a', {id : t.id + '_open', tabindex : -1, href : 'javascript:;', 'class' : 'mceOpen', onclick : "return false;", onmousedown : 'return false;'}, '<span></span>') + '</td>';
h += '</tr></tbody></table>';
return h;
},
/**
* Displays the drop menu with all items.
*/
showMenu : function() {
var t = this, p1, p2, e = DOM.get(this.id), m;
if (t.isDisabled() || t.items.length == 0)
return;
if (t.menu && t.menu.isMenuVisible)
return t.hideMenu();
if (!t.isMenuRendered) {
t.renderMenu();
t.isMenuRendered = true;
}
p1 = DOM.getPos(this.settings.menu_container);
p2 = DOM.getPos(e);
m = t.menu;
m.settings.offset_x = p2.x;
m.settings.offset_y = p2.y;
m.settings.keyboard_focus = !tinymce.isOpera; // Opera is buggy when it comes to auto focus
// Select in menu
if (t.oldID)
m.items[t.oldID].setSelected(0);
each(t.items, function(o) {
if (o.value === t.selectedValue) {
m.items[o.id].setSelected(1);
t.oldID = o.id;
}
});
m.showMenu(0, e.clientHeight);
Event.add(DOM.doc, 'mousedown', t.hideMenu, t);
DOM.addClass(t.id, t.classPrefix + 'Selected');
//DOM.get(t.id + '_text').focus();
},
/**
* Hides the drop menu.
*/
hideMenu : function(e) {
var t = this;
// Prevent double toogles by canceling the mouse click event to the button
if (e && e.type == "mousedown" && (e.target.id == t.id + '_text' || e.target.id == t.id + '_open'))
return;
if (!e || !DOM.getParent(e.target, function(n) {return DOM.hasClass(n, 'mceMenu');})) {
DOM.removeClass(t.id, t.classPrefix + 'Selected');
Event.remove(DOM.doc, 'mousedown', t.hideMenu, t);
if (t.menu)
t.menu.hideMenu();
}
},
/**
* Renders the menu to the DOM.
*/
renderMenu : function() {
var t = this, m;
m = t.settings.control_manager.createDropMenu(t.id + '_menu', {
menu_line : 1,
'class' : t.classPrefix + 'Menu mceNoIcons',
max_width : 150,
max_height : 150
});
m.onHideMenu.add(t.hideMenu, t);
m.add({
title : t.settings.title,
'class' : 'mceMenuItemTitle',
onclick : function() {
if (t.settings.onselect('') !== false)
t.select(''); // Must be runned after
}
});
each(t.items, function(o) {
o.id = DOM.uniqueId();
o.onclick = function() {
if (t.settings.onselect(o.value) !== false)
t.select(o.value); // Must be runned after
};
m.add(o);
});
t.onRenderMenu.dispatch(t, m);
t.menu = m;
},
/**
* Post render event. This will be executed after the control has been rendered and can be used to
* set states, add events to the control etc. It's recommended for subclasses of the control to call this method by using this.parent().
*/
postRender : function() {
var t = this, cp = t.classPrefix;
Event.add(t.id, 'click', t.showMenu, t);
Event.add(t.id + '_text', 'focus', function(e) {
if (!t._focused) {
t.keyDownHandler = Event.add(t.id + '_text', 'keydown', function(e) {
var idx = -1, v, kc = e.keyCode;
// Find current index
each(t.items, function(v, i) {
if (t.selectedValue == v.value)
idx = i;
});
// Move up/down
if (kc == 38)
v = t.items[idx - 1];
else if (kc == 40)
v = t.items[idx + 1];
else if (kc == 13) {
// Fake select on enter
v = t.selectedValue;
t.selectedValue = null; // Needs to be null to fake change
t.settings.onselect(v);
return Event.cancel(e);
}
if (v) {
t.hideMenu();
t.select(v.value);
}
});
}
t._focused = 1;
});
Event.add(t.id + '_text', 'blur', function() {Event.remove(t.id + '_text', 'keydown', t.keyDownHandler); t._focused = 0;});
// Old IE doesn't have hover on all elements
if (tinymce.isIE6 || !DOM.boxModel) {
Event.add(t.id, 'mouseover', function() {
if (!DOM.hasClass(t.id, cp + 'Disabled'))
DOM.addClass(t.id, cp + 'Hover');
});
Event.add(t.id, 'mouseout', function() {
if (!DOM.hasClass(t.id, cp + 'Disabled'))
DOM.removeClass(t.id, cp + 'Hover');
});
}
t.onPostRender.dispatch(t, DOM.get(t.id));
},
destroy : function() {
this.parent();
Event.clear(this.id + '_text');
}
/**#@-*/
});
})();

175
source/web/scripts/tiny_mce/classes/ui/Menu.js vendored Executable file
View File

@@ -0,0 +1,175 @@
/**
* $Id: Menu.js 766 2008-04-03 20:37:06Z spocke $
*
* @author Moxiecode
* @copyright Copyright <20> 2004-2008, Moxiecode Systems AB, All rights reserved.
*/
(function() {
var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, walk = tinymce.walk;
/**#@+
* @class This class is base class for all menu types like DropMenus etc. This class should not
* be instantiated directly other menu controls should inherit from this one.
* @member tinymce.ui.Menu
* @base tinymce.ui.MenuItem
*/
tinymce.create('tinymce.ui.Menu:tinymce.ui.MenuItem', {
/**
* Constructs a new button control instance.
*
* @param {String} id Button control id for the button.
* @param {Object} s Optional name/value settings object.
*/
Menu : function(id, s) {
var t = this;
t.parent(id, s);
t.items = {};
t.collapsed = false;
t.menuCount = 0;
t.onAddItem = new tinymce.util.Dispatcher(this);
},
/**#@+
* @method
*/
/**
* Expands the menu, this will show them menu and all menu items.
*
* @param {bool} d Optional deep state. If this is set to true all children will be expanded as well.
*/
expand : function(d) {
var t = this;
if (d) {
walk(t, function(o) {
if (o.expand)
o.expand();
}, 'items', t);
}
t.collapsed = false;
},
/**
* Collapses the menu, this will hide the menu and all menu items.
*
* @param {bool} d Optional deep state. If this is set to true all children will be collapsed as well.
*/
collapse : function(d) {
var t = this;
if (d) {
walk(t, function(o) {
if (o.collapse)
o.collapse();
}, 'items', t);
}
t.collapsed = true;
},
/**
* Returns true/false if the menu has been collapsed or not.
*
* @return {bool} True/false state if the menu has been collapsed or not.
*/
isCollapsed : function() {
return this.collapsed;
},
/**
* Adds a new menu, menu item or sub classes of them to the drop menu.
*
* @param {tinymce.ui.Control} o Menu or menu item to add to the drop menu.
* @return {tinymce.ui.Control} Same as the input control, the menu or menu item.
*/
add : function(o) {
if (!o.settings)
o = new tinymce.ui.MenuItem(o.id || DOM.uniqueId(), o);
this.onAddItem.dispatch(this, o);
return this.items[o.id] = o;
},
/**
* Adds a menu separator between the menu items.
*
* @return {tinymce.ui.MenuItem} Menu item instance for the separator.
*/
addSeparator : function() {
return this.add({separator : true});
},
/**
* Adds a sub menu to the menu.
*
* @param {Object} o Menu control or a object with settings to be created into an control.
* @return {tinymce.ui.Menu} Menu control instance passed in or created.
*/
addMenu : function(o) {
if (!o.collapse)
o = this.createMenu(o);
this.menuCount++;
return this.add(o);
},
/**
* Returns true/false if the menu has sub menus or not.
*
* @return {bool} True/false state if the menu has sub menues or not.
*/
hasMenus : function() {
return this.menuCount !== 0;
},
/**
* Removes a specific sub menu or menu item from the menu.
*
* @param {tinymce.ui.Control} o Menu item or menu to remove from menu.
* @return {tinymce.ui.Control} Control instance or null if it wasn't found.
*/
remove : function(o) {
delete this.items[o.id];
},
/**
* Removes all menu items and sub menu items from the menu.
*/
removeAll : function() {
var t = this;
walk(t, function(o) {
if (o.removeAll)
o.removeAll();
else
o.remove();
o.destroy();
}, 'items', t);
t.items = {};
},
/**
* Created a new sub menu for the menu control.
*
* @param {Object} s Optional name/value settings object.
* @return {tinymce.ui.Menu} New drop menu instance.
*/
createMenu : function(o) {
var m = new tinymce.ui.Menu(o.id || DOM.uniqueId(), o);
m.onAddItem.add(this.onAddItem.dispatch, this.onAddItem);
return m;
}
/**#@-*/
});
})();

View File

@@ -0,0 +1,128 @@
/**
* $Id: Button.js 520 2008-01-07 16:30:32Z spocke $
*
* @author Moxiecode
* @copyright Copyright <20> 2004-2008, Moxiecode Systems AB, All rights reserved.
*/
(function() {
var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each;
/**#@+
* @class This class is used to create a UI button. A button is basically a link
* that is styled to look like a button or icon.
* @member tinymce.ui.Button
* @base tinymce.ui.Control
*/
tinymce.create('tinymce.ui.MenuButton:tinymce.ui.Button', {
/**
* Constructs a new split button control instance.
*
* @param {String} id Control id for the split button.
* @param {Object} s Optional name/value settings object.
*/
MenuButton : function(id, s) {
this.parent(id, s);
this.onRenderMenu = new tinymce.util.Dispatcher(this);
s.menu_container = s.menu_container || DOM.doc.body;
},
/**#@+
* @method
*/
/**
* Shows the menu.
*/
showMenu : function() {
var t = this, p1, p2, e = DOM.get(t.id), m;
if (t.isDisabled())
return;
if (!t.isMenuRendered) {
t.renderMenu();
t.isMenuRendered = true;
}
if (t.isMenuVisible)
return t.hideMenu();
p1 = DOM.getPos(t.settings.menu_container);
p2 = DOM.getPos(e);
m = t.menu;
m.settings.offset_x = p2.x;
m.settings.offset_y = p2.y;
m.settings.vp_offset_x = p2.x;
m.settings.vp_offset_y = p2.y;
m.settings.keyboard_focus = t._focused;
m.showMenu(0, e.clientHeight);
Event.add(DOM.doc, 'mousedown', t.hideMenu, t);
t.setState('Selected', 1);
t.isMenuVisible = 1;
},
/**
* Renders the menu to the DOM.
*/
renderMenu : function() {
var t = this, m;
m = t.settings.control_manager.createDropMenu(t.id + '_menu', {
menu_line : 1,
'class' : this.classPrefix + 'Menu',
icons : t.settings.icons
});
m.onHideMenu.add(t.hideMenu, t);
t.onRenderMenu.dispatch(t, m);
t.menu = m;
},
/**
* Hides the menu. The optional event parameter is used to check where the event occured so it
* doesn't close them menu if it was a event inside the menu.
*
* @param {Event} e Optional event object.
*/
hideMenu : function(e) {
var t = this;
// Prevent double toogles by canceling the mouse click event to the button
if (e && e.type == "mousedown" && DOM.getParent(e.target, function(e) {return e.id === t.id || e.id === t.id + '_open';}))
return;
if (!e || !DOM.getParent(e.target, function(n) {return DOM.hasClass(n, 'mceMenu');})) {
t.setState('Selected', 0);
Event.remove(DOM.doc, 'mousedown', t.hideMenu, t);
if (t.menu)
t.menu.hideMenu();
}
t.isMenuVisible = 0;
},
/**
* Post render handler. This function will be called after the UI has been
* rendered so that events can be added.
*/
postRender : function() {
var t = this, s = t.settings;
Event.add(t.id, 'click', function() {
if (!t.isDisabled()) {
if (s.onclick)
s.onclick(t.value);
t.showMenu();
}
});
}
/**#@-*/
});
})();

View File

@@ -0,0 +1,69 @@
/**
* $Id: MenuItem.js 520 2008-01-07 16:30:32Z spocke $
*
* @author Moxiecode
* @copyright Copyright <20> 2004-2008, Moxiecode Systems AB, All rights reserved.
*/
(function() {
var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, walk = tinymce.walk;
/**#@+
* @class This class is base class for all menu item types like DropMenus items etc. This class should not
* be instantiated directly other menu items should inherit from this one.
* @member tinymce.ui.MenuItem
* @base tinymce.ui.Control
*/
tinymce.create('tinymce.ui.MenuItem:tinymce.ui.Control', {
/**
* Constructs a new button control instance.
*
* @param {String} id Button control id for the button.
* @param {Object} s Optional name/value settings object.
*/
MenuItem : function(id, s) {
this.parent(id, s);
this.classPrefix = 'mceMenuItem';
},
/**#@+
* @method
*/
/**
* Sets the selected state for the control. This will add CSS classes to the
* element that contains the control. So that it can be selected visually.
*
* @param {bool} s Boolean state if the control should be selected or not.
*/
setSelected : function(s) {
this.setState('Selected', s);
this.selected = s;
},
/**
* Returns true/false if the control is selected or not.
*
* @return {bool} true/false if the control is selected or not.
*/
isSelected : function() {
return this.selected;
},
/**
* Post render handler. This function will be called after the UI has been
* rendered so that events can be added.
*/
postRender : function() {
var t = this;
t.parent();
// Set pending state
if (is(t.selected))
t.setSelected(t.selected);
}
/**#@-*/
});
})();

View File

@@ -0,0 +1,198 @@
/**
* $Id: NativeListBox.js 952 2008-11-03 17:56:04Z spocke $
*
* @author Moxiecode
* @copyright Copyright <20> 2004-2008, Moxiecode Systems AB, All rights reserved.
*/
(function() {
var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher;
/**#@+
* @class This class is used to create list boxes/select list. This one will generate
* a native control the way that the browser produces them by default.
* @member tinymce.ui.NativeListBox
* @base tinymce.ui.ListBox
*/
tinymce.create('tinymce.ui.NativeListBox:tinymce.ui.ListBox', {
/**
* Constructs a new button control instance.
*
* @param {String} id Button control id for the button.
* @param {Object} s Optional name/value settings object.
*/
NativeListBox : function(id, s) {
this.parent(id, s);
this.classPrefix = 'mceNativeListBox';
},
/**#@+
* @method
*/
/**
* Sets the disabled state for the control. This will add CSS classes to the
* element that contains the control. So that it can be disabled visually.
*
* @param {bool} s Boolean state if the control should be disabled or not.
*/
setDisabled : function(s) {
DOM.get(this.id).disabled = s;
},
/**
* Returns true/false if the control is disabled or not. This is a method since you can then
* choose to check some class or some internal bool state in subclasses.
*
* @return {bool} true/false if the control is disabled or not.
*/
isDisabled : function() {
return DOM.get(this.id).disabled;
},
/**
* Selects a item/option by value. This will both add a visual selection to the
* item and change the title of the control to the title of the option.
*
* @param {String/function} va Value to look for inside the list box or a function selector.
*/
select : function(va) {
var t = this, fv, f;
if (va == undefined)
return t.selectByIndex(-1);
// Is string or number make function selector
if (va && va.call)
f = va;
else {
f = function(v) {
return v == va;
};
}
// Do we need to do something?
if (va != t.selectedValue) {
// Find item
each(t.items, function(o, i) {
if (f(o.value)) {
fv = 1;
t.selectByIndex(i);
return false;
}
});
if (!fv)
t.selectByIndex(-1);
}
},
/**
* Selects a item/option by index. This will both add a visual selection to the
* item and change the title of the control to the title of the option.
*
* @param {String} idx Index to select, pass -1 to select menu/title of select box.
*/
selectByIndex : function(idx) {
DOM.get(this.id).selectedIndex = idx + 1;
this.selectedValue = this.items[idx] ? this.items[idx].value : null;
},
/**
* Adds a option item to the list box.
*
* @param {String} n Title for the new option.
* @param {String} v Value for the new option.
* @param {Object} o Optional object with settings like for example class.
*/
add : function(n, v, a) {
var o, t = this;
a = a || {};
a.value = v;
if (t.isRendered())
DOM.add(DOM.get(this.id), 'option', a, n);
o = {
title : n,
value : v,
attribs : a
};
t.items.push(o);
t.onAdd.dispatch(t, o);
},
/**
* Executes the specified callback function for the menu item. In this case when the user clicks the menu item.
*/
getLength : function() {
return DOM.get(this.id).options.length - 1;
},
/**
* Renders the list box as a HTML string. This method is much faster than using the DOM and when
* creating a whole toolbar with buttons it does make a lot of difference.
*
* @return {String} HTML for the list box control element.
*/
renderHTML : function() {
var h, t = this;
h = DOM.createHTML('option', {value : ''}, '-- ' + t.settings.title + ' --');
each(t.items, function(it) {
h += DOM.createHTML('option', {value : it.value}, it.title);
});
h = DOM.createHTML('select', {id : t.id, 'class' : 'mceNativeListBox'}, h);
return h;
},
/**
* Post render handler. This function will be called after the UI has been
* rendered so that events can be added.
*/
postRender : function() {
var t = this, ch;
t.rendered = true;
function onChange(e) {
var v = t.items[e.target.selectedIndex - 1];
if (v && (v = v.value)) {
t.onChange.dispatch(t, v);
if (t.settings.onselect)
t.settings.onselect(v);
}
};
Event.add(t.id, 'change', onChange);
// Accessibility keyhandler
Event.add(t.id, 'keydown', function(e) {
var bf;
Event.remove(t.id, 'change', ch);
bf = Event.add(t.id, 'blur', function() {
Event.add(t.id, 'change', onChange);
Event.remove(t.id, 'blur', bf);
});
if (e.keyCode == 13 || e.keyCode == 32) {
onChange(e);
return Event.cancel(e);
}
});
t.onPostRender.dispatch(t, DOM.get(t.id));
}
/**#@-*/
});
})();

View File

@@ -0,0 +1,34 @@
/**
* $Id: Separator.js 756 2008-03-29 19:53:48Z spocke $
*
* @author Moxiecode
* @copyright Copyright <20> 2004-2008, Moxiecode Systems AB, All rights reserved.
*/
/**#@+
* @class This class is used to create vertical separator between other controls.
* @member tinymce.ui.Separator
* @base tinymce.ui.Control
*/
tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
Separator : function(id, s) {
this.parent(id, s);
this.classPrefix = 'mceSeparator';
},
/**#@+
* @method
*/
/**
* Renders the separator as a HTML string. This method is much faster than using the DOM and when
* creating a whole toolbar with buttons it does make a lot of difference.
*
* @return {String} HTML for the separator control element.
*/
renderHTML : function() {
return tinymce.DOM.createHTML('span', {'class' : this.classPrefix});
}
/**#@-*/
});

View File

@@ -0,0 +1,99 @@
/**
* $Id: SplitButton.js 760 2008-04-01 14:13:07Z spocke $
*
* @author Moxiecode
* @copyright Copyright <20> 2004-2008, Moxiecode Systems AB, All rights reserved.
*/
(function() {
var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each;
/**#@+
* @class This class is used to create a split button. A button with a menu attached to it.
* @member tinymce.ui.SplitButton
* @base tinymce.ui.Button
*/
tinymce.create('tinymce.ui.SplitButton:tinymce.ui.MenuButton', {
/**
* Constructs a new split button control instance.
*
* @param {String} id Control id for the split button.
* @param {Object} s Optional name/value settings object.
*/
SplitButton : function(id, s) {
this.parent(id, s);
this.classPrefix = 'mceSplitButton';
},
/**#@+
* @method
*/
/**
* Renders the split button as a HTML string. This method is much faster than using the DOM and when
* creating a whole toolbar with buttons it does make a lot of difference.
*
* @return {String} HTML for the split button control element.
*/
renderHTML : function() {
var h, t = this, s = t.settings, h1;
h = '<tbody><tr>';
if (s.image)
h1 = DOM.createHTML('img ', {src : s.image, 'class' : 'mceAction ' + s['class']});
else
h1 = DOM.createHTML('span', {'class' : 'mceAction ' + s['class']}, '');
h += '<td>' + DOM.createHTML('a', {id : t.id + '_action', href : 'javascript:;', 'class' : 'mceAction ' + s['class'], onclick : "return false;", onmousedown : 'return false;', title : s.title}, h1) + '</td>';
h1 = DOM.createHTML('span', {'class' : 'mceOpen ' + s['class']});
h += '<td>' + DOM.createHTML('a', {id : t.id + '_open', href : 'javascript:;', 'class' : 'mceOpen ' + s['class'], onclick : "return false;", onmousedown : 'return false;', title : s.title}, h1) + '</td>';
h += '</tr></tbody>';
return DOM.createHTML('table', {id : t.id, 'class' : 'mceSplitButton mceSplitButtonEnabled ' + s['class'], cellpadding : '0', cellspacing : '0', onmousedown : 'return false;', title : s.title}, h);
},
/**
* Post render handler. This function will be called after the UI has been
* rendered so that events can be added.
*/
postRender : function() {
var t = this, s = t.settings;
if (s.onclick) {
Event.add(t.id + '_action', 'click', function() {
if (!t.isDisabled())
s.onclick(t.value);
});
}
Event.add(t.id + '_open', 'click', t.showMenu, t);
Event.add(t.id + '_open', 'focus', function() {t._focused = 1;});
Event.add(t.id + '_open', 'blur', function() {t._focused = 0;});
// Old IE doesn't have hover on all elements
if (tinymce.isIE6 || !DOM.boxModel) {
Event.add(t.id, 'mouseover', function() {
if (!DOM.hasClass(t.id, 'mceSplitButtonDisabled'))
DOM.addClass(t.id, 'mceSplitButtonHover');
});
Event.add(t.id, 'mouseout', function() {
if (!DOM.hasClass(t.id, 'mceSplitButtonDisabled'))
DOM.removeClass(t.id, 'mceSplitButtonHover');
});
}
},
destroy : function() {
this.parent();
Event.clear(this.id + '_action');
Event.clear(this.id + '_open');
}
/**#@-*/
});
})();

View File

@@ -0,0 +1,86 @@
/**
* $Id: Toolbar.js 706 2008-03-11 20:38:31Z spocke $
*
* @author Moxiecode
* @copyright Copyright <20> 2004-2008, Moxiecode Systems AB, All rights reserved.
*/
/**#@+
* @class This class is used to create toolbars a toolbar is a container for other controls like buttons etc.
* @member tinymce.ui.Toolbar
* @base tinymce.ui.Container
*/
tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
/**#@+
* @method
*/
/**
* Renders the toolbar as a HTML string. This method is much faster than using the DOM and when
* creating a whole toolbar with buttons it does make a lot of difference.
*
* @return {String} HTML for the toolbar control.
*/
renderHTML : function() {
var t = this, h = '', c, co, dom = tinymce.DOM, s = t.settings, i, pr, nx, cl;
cl = t.controls;
for (i=0; i<cl.length; i++) {
// Get current control, prev control, next control and if the control is a list box or not
co = cl[i];
pr = cl[i - 1];
nx = cl[i + 1];
// Add toolbar start
if (i === 0) {
c = 'mceToolbarStart';
if (co.Button)
c += ' mceToolbarStartButton';
else if (co.SplitButton)
c += ' mceToolbarStartSplitButton';
else if (co.ListBox)
c += ' mceToolbarStartListBox';
h += dom.createHTML('td', {'class' : c}, dom.createHTML('span', null, '<!-- IE -->'));
}
// Add toolbar end before list box and after the previous button
// This is to fix the o2k7 editor skins
if (pr && co.ListBox) {
if (pr.Button || pr.SplitButton)
h += dom.createHTML('td', {'class' : 'mceToolbarEnd'}, dom.createHTML('span', null, '<!-- IE -->'));
}
// Render control HTML
// IE 8 quick fix, needed to propertly generate a hit area for anchors
if (dom.stdMode)
h += '<td style="position: relative">' + co.renderHTML() + '</td>';
else
h += '<td>' + co.renderHTML() + '</td>';
// Add toolbar start after list box and before the next button
// This is to fix the o2k7 editor skins
if (nx && co.ListBox) {
if (nx.Button || nx.SplitButton)
h += dom.createHTML('td', {'class' : 'mceToolbarStart'}, dom.createHTML('span', null, '<!-- IE -->'));
}
}
c = 'mceToolbarEnd';
if (co.Button)
c += ' mceToolbarEndButton';
else if (co.SplitButton)
c += ' mceToolbarEndSplitButton';
else if (co.ListBox)
c += ' mceToolbarEndListBox';
h += dom.createHTML('td', {'class' : c}, dom.createHTML('span', null, '<!-- IE -->'));
return dom.createHTML('table', {id : t.id, 'class' : 'mceToolbar' + (s['class'] ? ' ' + s['class'] : ''), cellpadding : '0', cellspacing : '0', align : t.settings.align || ''}, '<tbody><tr>' + h + '</tr></tbody>');
}
/**#@-*/
});