You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jspwiki.apache.org by br...@apache.org on 2010/02/28 22:12:41 UTC
svn commit: r917294 [2/3] - in /incubator/jspwiki/trunk: ./ etc/ini/
src/WebContent/WEB-INF/classes/templates/ src/WebContent/scripts/
src/WebContent/scripts/wysiwyg/ src/WebContent/scripts/wysiwyg/images/
src/WebContent/templates/default/ src/WebConte...
Modified: incubator/jspwiki/trunk/src/WebContent/scripts/mootools-more.js
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/WebContent/scripts/mootools-more.js?rev=917294&r1=917293&r2=917294&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/WebContent/scripts/mootools-more.js (original)
+++ incubator/jspwiki/trunk/src/WebContent/scripts/mootools-more.js Sun Feb 28 21:12:40 2010
@@ -1,18 +1,51 @@
//MooTools More, <http://mootools.net/more>. Copyright (c) 2006-2009 Aaron Newton <http://clientcide.com/>, Valerio Proietti <http://mad4milk.net> & the MooTools team <http://mootools.net/developers>, MIT Style License.
+/*
+---
+
+script: More.js
+
+description: MooTools More
+
+license: MIT-style license
+
+authors:
+- Guillermo Rauch
+- Thomas Aylott
+- Scott Kyle
+
+requires:
+- core:1.2.4/MooTools
+
+provides: [MooTools.More]
+
+...
+*/
+
MooTools.More = {
- 'version': '1.2.3.1'
+ 'version': '1.2.4.4',
+ 'build': '6f6057dc645fdb7547689183b2311063bd653ddf'
};
/*
-Script: Fx.Elements.js
- Effect to change any number of CSS properties of any number of Elements.
+---
+
+script: Fx.Elements.js
+
+description: Effect to change any number of CSS properties of any number of Elements.
- License:
- MIT-style license.
+license: MIT-style license
- Authors:
- Valerio Proietti
+authors:
+- Valerio Proietti
+
+requires:
+- core:1.2.4/Fx.CSS
+- /MooTools.More
+
+provides: [Fx.Elements]
+
+...
*/
Fx.Elements = new Class({
@@ -58,42 +91,58 @@
});
/*
-Script: Fx.Accordion.js
- An Fx.Elements extension which allows you to easily create accordion type controls.
+---
+
+script: Fx.Accordion.js
- License:
- MIT-style license.
+description: An Fx.Elements extension which allows you to easily create accordion type controls.
- Authors:
- Valerio Proietti
+license: MIT-style license
+
+authors:
+- Valerio Proietti
+
+requires:
+- core:1.2.4/Element.Event
+- /Fx.Elements
+
+provides: [Fx.Accordion]
+
+...
*/
-var Accordion = Fx.Accordion = new Class({
+Fx.Accordion = new Class({
Extends: Fx.Elements,
options: {/*
onActive: $empty(toggler, section),
- onBackground: $empty(toggler, section),*/
+ onBackground: $empty(toggler, section),
+ fixedHeight: false,
+ fixedWidth: false,
+ */
display: 0,
show: false,
height: true,
width: false,
opacity: true,
- fixedHeight: false,
- fixedWidth: false,
- wait: false,
alwaysHide: false,
trigger: 'click',
- initialDisplayFx: true
+ initialDisplayFx: true,
+ returnHeightToAuto: true
},
initialize: function(){
- var params = Array.link(arguments, {'container': Element.type, 'options': Object.type, 'togglers': $defined, 'elements': $defined});
+ var params = Array.link(arguments, {
+ 'container': Element.type, //deprecated
+ 'options': Object.type,
+ 'togglers': $defined,
+ 'elements': $defined
+ });
this.parent(params.elements, params.options);
this.togglers = $$(params.togglers);
- this.container = document.id(params.container);
this.previous = -1;
+ this.internalChain = new Chain();
if (this.options.alwaysHide) this.options.wait = true;
if ($chk(this.options.show)){
this.options.display = false;
@@ -115,7 +164,9 @@
for (var fx in this.effects) el.setStyle(fx, 0);
}
}, this);
- if ($chk(this.options.display)) this.display(this.options.display, this.options.initialDisplayFx);
+ if ($chk(this.options.display) || this.options.initialDisplayFx === false) this.display(this.options.display, this.options.initialDisplayFx);
+ if (this.options.fixedHeight !== false) this.options.returnHeightToAuto = false;
+ this.addEvent('complete', this.internalChain.callChain.bind(this.internalChain));
},
addSection: function(toggler, element){
@@ -125,7 +176,9 @@
this.togglers.include(toggler);
this.elements.include(element);
var idx = this.togglers.indexOf(toggler);
- toggler.addEvent(this.options.trigger, this.display.bind(this, idx));
+ var displayer = this.display.bind(this, idx);
+ toggler.store('accordion:display', displayer);
+ toggler.addEvent(this.options.trigger, displayer);
if (this.options.height) element.setStyles({'padding-top': 0, 'border-top': 'none', 'padding-bottom': 0, 'border-bottom': 'none'});
if (this.options.width) element.setStyles({'padding-left': 0, 'border-left': 'none', 'padding-right': 0, 'border-right': 'none'});
element.fullOpacity = 1;
@@ -138,34 +191,104 @@
return this;
},
+ detach: function(){
+ this.togglers.each(function(toggler) {
+ toggler.removeEvent(this.options.trigger, toggler.retrieve('accordion:display'));
+ }, this);
+ },
+
display: function(index, useFx){
+ if (!this.check(index, useFx)) return this;
useFx = $pick(useFx, true);
+ if (this.options.returnHeightToAuto){
+ var prev = this.elements[this.previous];
+ if (prev && !this.selfHidden){
+ for (var fx in this.effects){
+ prev.setStyle(fx, prev[this.effects[fx]]);
+ }
+ }
+ }
index = ($type(index) == 'element') ? this.elements.indexOf(index) : index;
if ((this.timer && this.options.wait) || (index === this.previous && !this.options.alwaysHide)) return this;
this.previous = index;
var obj = {};
this.elements.each(function(el, i){
obj[i] = {};
- var hide = (i != index) || (this.options.alwaysHide && (el.offsetHeight > 0));
+ var hide;
+ if (i != index){
+ hide = true;
+ } else if (this.options.alwaysHide && ((el.offsetHeight > 0 && this.options.height) || el.offsetWidth > 0 && this.options.width)){
+ hide = true;
+ this.selfHidden = true;
+ }
this.fireEvent(hide ? 'background' : 'active', [this.togglers[i], el]);
for (var fx in this.effects) obj[i][fx] = hide ? 0 : el[this.effects[fx]];
}, this);
+ this.internalChain.chain(function(){
+ if (this.options.returnHeightToAuto && !this.selfHidden){
+ var el = this.elements[index];
+ if (el) el.setStyle('height', 'auto');
+ };
+ }.bind(this));
return useFx ? this.start(obj) : this.set(obj);
}
});
/*
-Script: Drag.js
- The base Drag Class. Can be used to drag and resize Elements using mouse events.
+ Compatibility with 1.2.0
+*/
+var Accordion = new Class({
+
+ Extends: Fx.Accordion,
+
+ initialize: function(){
+ this.parent.apply(this, arguments);
+ var params = Array.link(arguments, {'container': Element.type});
+ this.container = params.container;
+ },
- License:
- MIT-style license.
+ addSection: function(toggler, element, pos){
+ toggler = document.id(toggler);
+ element = document.id(element);
+ var test = this.togglers.contains(toggler);
+ var len = this.togglers.length;
+ if (len && (!test || pos)){
+ pos = $pick(pos, len - 1);
+ toggler.inject(this.togglers[pos], 'before');
+ element.inject(toggler, 'after');
+ } else if (this.container && !test){
+ toggler.inject(this.container);
+ element.inject(this.container);
+ }
+ return this.parent.apply(this, arguments);
+ }
+
+});
+
+/*
+---
+
+script: Drag.js
+
+description: The base Drag Class. Can be used to drag and resize Elements using mouse events.
+
+license: MIT-style license
+
+authors:
+- Valerio Proietti
+- Tom Occhinno
+- Jan Kassens
+
+requires:
+- core:1.2.4/Events
+- core:1.2.4/Options
+- core:1.2.4/Element.Event
+- core:1.2.4/Element.Style
+- /MooTools.More
+
+provides: [Drag]
- Authors:
- Valerio Proietti
- Tom Occhinno
- Jan Kassens
*/
var Drag = new Class({
@@ -187,6 +310,7 @@
handle: false,
invert: false,
preventDefault: false,
+ stopPropagation: false,
modifiers: {x: 'left', y: 'top'}
},
@@ -224,7 +348,9 @@
},
start: function(event){
+ if (event.rightClick) return;
if (this.options.preventDefault) event.preventDefault();
+ if (this.options.stopPropagation) event.stopPropagation();
this.mouse.start = event.page;
this.fireEvent('beforeStart', this.element);
var limit = this.options.limit;
@@ -274,8 +400,11 @@
}
}
if (this.options.grid[z]) this.value.now[z] -= ((this.value.now[z] - (this.limit[z][0]||0)) % this.options.grid[z]);
- if (this.options.style) this.element.setStyle(this.options.modifiers[z], this.value.now[z] + this.options.unit);
- else this.element[this.options.modifiers[z]] = this.value.now[z];
+ if (this.options.style) {
+ this.element.setStyle(this.options.modifiers[z], this.value.now[z] + this.options.unit);
+ } else {
+ this.element[this.options.modifiers[z]] = this.value.now[z];
+ }
}
this.fireEvent('drag', [this.element, event]);
},
@@ -312,16 +441,29 @@
/*
-Script: Drag.Move.js
- A Drag extension that provides support for the constraining of draggables to containers and droppables.
+---
+
+script: Drag.Move.js
+
+description: A Drag extension that provides support for the constraining of draggables to containers and droppables.
+
+license: MIT-style license
- License:
- MIT-style license.
+authors:
+- Valerio Proietti
+- Tom Occhinno
+- Jan Kassens
+- Aaron Newton
+- Scott Kyle
- Authors:
- Valerio Proietti
- Tom Occhinno
- Jan Kassens*/
+requires:
+- core:1.2.4/Element.Dimensions
+- /Drag
+
+provides: [Drag.Move]
+
+...
+*/
Drag.Move = new Class({
@@ -340,14 +482,20 @@
initialize: function(element, options){
this.parent(element, options);
+ element = this.element;
+
this.droppables = $$(this.options.droppables);
this.container = document.id(this.options.container);
- if (this.container && $type(this.container) != 'element') this.container = document.id(this.container.getDocument().body);
-
- var position = this.element.getStyle('position');
- if (position=='static') position = 'absolute';
- if ([this.element.getStyle('left'), this.element.getStyle('top')].contains('auto')) this.element.position(this.element.getPosition(this.element.offsetParent));
- this.element.setStyle('position', position);
+
+ if (this.container && $type(this.container) != 'element')
+ this.container = document.id(this.container.getDocument().body);
+
+ var styles = element.getStyles('left', 'top', 'position');
+ if (styles.left == 'auto' || styles.top == 'auto')
+ element.setPosition(element.getPosition(element.getOffsetParent()));
+
+ if (styles.position == 'static')
+ element.setStyle('position', 'absolute');
this.addEvent('start', this.checkDroppables, true);
@@ -355,42 +503,81 @@
},
start: function(event){
- if (this.container){
- var ccoo = this.container.getCoordinates(this.element.getOffsetParent()), cbs = {}, ems = {};
-
- ['top', 'right', 'bottom', 'left'].each(function(pad){
- cbs[pad] = this.container.getStyle('border-' + pad).toInt();
- ems[pad] = this.element.getStyle('margin-' + pad).toInt();
- }, this);
-
- var width = this.element.offsetWidth + ems.left + ems.right;
- var height = this.element.offsetHeight + ems.top + ems.bottom;
-
- if (this.options.includeMargins) {
- $each(ems, function(value, key) {
- ems[key] = 0;
- });
- }
- if (this.container == this.element.getOffsetParent()) {
- this.options.limit = {
- x: [0 - ems.left, ccoo.right - cbs.left - cbs.right - width + ems.right],
- y: [0 - ems.top, ccoo.bottom - cbs.top - cbs.bottom - height + ems.bottom]
- };
- } else {
- this.options.limit = {
- x: [ccoo.left + cbs.left - ems.left, ccoo.right - cbs.right - width + ems.right],
- y: [ccoo.top + cbs.top - ems.top, ccoo.bottom - cbs.bottom - height + ems.bottom]
- };
- }
-
- }
+ if (this.container) this.options.limit = this.calculateLimit();
+
if (this.options.precalculate){
- this.positions = this.droppables.map(function(el) {
+ this.positions = this.droppables.map(function(el){
return el.getCoordinates();
});
}
+
this.parent(event);
},
+
+ calculateLimit: function(){
+ var offsetParent = this.element.getOffsetParent(),
+ containerCoordinates = this.container.getCoordinates(offsetParent),
+ containerBorder = {},
+ elementMargin = {},
+ elementBorder = {},
+ containerMargin = {},
+ offsetParentPadding = {};
+
+ ['top', 'right', 'bottom', 'left'].each(function(pad){
+ containerBorder[pad] = this.container.getStyle('border-' + pad).toInt();
+ elementBorder[pad] = this.element.getStyle('border-' + pad).toInt();
+ elementMargin[pad] = this.element.getStyle('margin-' + pad).toInt();
+ containerMargin[pad] = this.container.getStyle('margin-' + pad).toInt();
+ offsetParentPadding[pad] = offsetParent.getStyle('padding-' + pad).toInt();
+ }, this);
+
+ var width = this.element.offsetWidth + elementMargin.left + elementMargin.right,
+ height = this.element.offsetHeight + elementMargin.top + elementMargin.bottom,
+ left = 0,
+ top = 0,
+ right = containerCoordinates.right - containerBorder.right - width,
+ bottom = containerCoordinates.bottom - containerBorder.bottom - height;
+
+ if (this.options.includeMargins){
+ left += elementMargin.left;
+ top += elementMargin.top;
+ } else {
+ right += elementMargin.right;
+ bottom += elementMargin.bottom;
+ }
+
+ if (this.element.getStyle('position') == 'relative'){
+ var coords = this.element.getCoordinates(offsetParent);
+ coords.left -= this.element.getStyle('left').toInt();
+ coords.top -= this.element.getStyle('top').toInt();
+
+ left += containerBorder.left - coords.left;
+ top += containerBorder.top - coords.top;
+ right += elementMargin.left - coords.left;
+ bottom += elementMargin.top - coords.top;
+
+ if (this.container != offsetParent){
+ left += containerMargin.left + offsetParentPadding.left;
+ top += (Browser.Engine.trident4 ? 0 : containerMargin.top) + offsetParentPadding.top;
+ }
+ } else {
+ left -= elementMargin.left;
+ top -= elementMargin.top;
+
+ if (this.container == offsetParent){
+ right -= containerBorder.left;
+ bottom -= containerBorder.top;
+ } else {
+ left += containerCoordinates.left + containerBorder.left;
+ top += containerCoordinates.top + containerBorder.top;
+ }
+ }
+
+ return {
+ x: [left, right],
+ y: [top, bottom]
+ };
+ },
checkAgainst: function(el, i){
el = (this.positions) ? this.positions[i] : el.getCoordinates();
@@ -433,14 +620,28 @@
/*
-Script: Color.js
- Class for creating and manipulating colors in JavaScript. Supports HSB -> RGB Conversions and vice versa.
+---
+
+script: Color.js
+
+description: Class for creating and manipulating colors in JavaScript. Supports HSB -> RGB Conversions and vice versa.
+
+license: MIT-style license
+
+authors:
+- Valerio Proietti
- License:
- MIT-style license.
+requires:
+- core:1.2.4/Array
+- core:1.2.4/String
+- core:1.2.4/Number
+- core:1.2.4/Hash
+- core:1.2.4/Function
+- core:1.2.4/$util
- Authors:
- Valerio Proietti
+provides: [Color]
+
+...
*/
var Color = new Native({
@@ -518,15 +719,16 @@
Array.implement({
rgbToHsb: function(){
- var red = this[0], green = this[1], blue = this[2];
- var hue, saturation, brightness;
- var max = Math.max(red, green, blue), min = Math.min(red, green, blue);
+ var red = this[0],
+ green = this[1],
+ blue = this[2],
+ hue = 0;
+ var max = Math.max(red, green, blue),
+ min = Math.min(red, green, blue);
var delta = max - min;
- brightness = max / 255;
- saturation = (max != 0) ? delta / max : 0;
- if (saturation == 0){
- hue = 0;
- } else {
+ var brightness = max / 255,
+ saturation = (max != 0) ? delta / max : 0;
+ if(saturation != 0) {
var rr = (max - red) / delta;
var gr = (max - green) / delta;
var br = (max - blue) / delta;
@@ -579,15 +781,26 @@
/*
-Script: Hash.Cookie.js
- Class for creating, reading, and deleting Cookies in JSON format.
+---
+
+script: Hash.Cookie.js
+
+description: Class for creating, reading, and deleting Cookies in JSON format.
+
+license: MIT-style license
+
+authors:
+- Valerio Proietti
+- Aaron Newton
+
+requires:
+- core:1.2.4/Cookie
+- core:1.2.4/JSON
+- /MooTools.More
- License:
- MIT-style license.
+provides: [Hash.Cookie]
- Authors:
- Valerio Proietti
- Aaron Newton
+...
*/
Hash.Cookie = new Class({
@@ -627,55 +840,77 @@
});
/*
-Script: Tips.js
- Class for creating nice tips that follow the mouse cursor when hovering an element.
+---
- License:
- MIT-style license.
+script: Tips.js
- Authors:
- Valerio Proietti
- Christoph Pojer
+description: Class for creating nice tips that follow the mouse cursor when hovering an element.
+
+license: MIT-style license
+
+authors:
+- Valerio Proietti
+- Christoph Pojer
+
+requires:
+- core:1.2.4/Options
+- core:1.2.4/Events
+- core:1.2.4/Element.Event
+- core:1.2.4/Element.Style
+- core:1.2.4/Element.Dimensions
+- /MooTools.More
+
+provides: [Tips]
+
+...
*/
-var Tips = new Class({
+(function(){
+
+var read = function(option, element){
+ return (option) ? ($type(option) == 'function' ? option(element) : element.get(option)) : '';
+};
+
+this.Tips = new Class({
Implements: [Events, Options],
options: {
- onShow: function(tip){
- tip.setStyle('visibility', 'visible');
+ /*
+ onAttach: $empty(element),
+ onDetach: $empty(element),
+ */
+ onShow: function(){
+ this.tip.setStyle('display', 'block');
},
- onHide: function(tip){
- tip.setStyle('visibility', 'hidden');
+ onHide: function(){
+ this.tip.setStyle('display', 'none');
},
title: 'title',
- text: function(el){
- return el.get('rel') || el.get('href');
+ text: function(element){
+ return element.get('rel') || element.get('href');
},
showDelay: 100,
hideDelay: 100,
- className: null,
+ className: 'tip-wrap',
offset: {x: 16, y: 16},
+ windowPadding: {x:0, y:0},
fixed: false
},
initialize: function(){
var params = Array.link(arguments, {options: Object.type, elements: $defined});
- if (params.options && params.options.offsets) params.options.offset = params.options.offsets;
this.setOptions(params.options);
- this.container = new Element('div', {'class': 'tip'});
- this.tip = this.getTip();
-
if (params.elements) this.attach(params.elements);
+ this.container = new Element('div', {'class': 'tip'});
},
- getTip: function(){
- return new Element('div', {
+ toElement: function(){
+ if (this.tip) return this.tip;
+
+ return this.tip = new Element('div', {
'class': this.options.className,
styles: {
- visibility: 'hidden',
- display: 'none',
position: 'absolute',
top: 0,
left: 0
@@ -688,81 +923,90 @@
},
attach: function(elements){
- var read = function(option, element){
- if (option == null) return '';
- return $type(option) == 'function' ? option(element) : element.get(option);
- };
$$(elements).each(function(element){
- var title = read(this.options.title, element);
+ var title = read(this.options.title, element),
+ text = read(this.options.text, element);
+
element.erase('title').store('tip:native', title).retrieve('tip:title', title);
- element.retrieve('tip:text', read(this.options.text, element));
-
+ element.retrieve('tip:text', text);
+ this.fireEvent('attach', [element]);
+
var events = ['enter', 'leave'];
if (!this.options.fixed) events.push('move');
-
+
events.each(function(value){
- element.addEvent('mouse' + value, element.retrieve('tip:' + value, this['element' + value.capitalize()].bindWithEvent(this, element)));
+ var event = element.retrieve('tip:' + value);
+ if (!event) event = this['element' + value.capitalize()].bindWithEvent(this, element);
+
+ element.store('tip:' + value, event).addEvent('mouse' + value, event);
}, this);
}, this);
-
+
return this;
},
detach: function(elements){
$$(elements).each(function(element){
['enter', 'leave', 'move'].each(function(value){
- element.removeEvent('mouse' + value, element.retrieve('tip:' + value) || $empty);
+ element.removeEvent('mouse' + value, element.retrieve('tip:' + value)).eliminate('tip:' + value);
});
-
- element.eliminate('tip:enter').eliminate('tip:leave').eliminate('tip:move');
-
- if ($type(this.options.title) == 'string' && this.options.title == 'title'){
+
+ this.fireEvent('detach', [element]);
+
+ if (this.options.title == 'title'){ // This is necessary to check if we can revert the title
var original = element.retrieve('tip:native');
if (original) element.set('title', original);
}
}, this);
-
+
return this;
},
elementEnter: function(event, element){
- $A(this.container.childNodes).each(Element.dispose);
-
+ this.container.empty();
+
['title', 'text'].each(function(value){
var content = element.retrieve('tip:' + value);
- if (!content) return;
-
- this[value + 'Element'] = new Element('div', {'class': 'tip-' + value}).inject(this.container);
- this.fill(this[value + 'Element'], content);
+ if (content) this.fill(new Element('div', {'class': 'tip-' + value}).inject(this.container), content);
}, this);
-
- this.timer = $clear(this.timer);
- this.timer = this.show.delay(this.options.showDelay, this, element);
- this.tip.setStyle('display', 'block');
- this.position((!this.options.fixed) ? event : {page: element.getPosition()});
+
+ $clear(this.timer);
+ this.timer = (function(){
+ this.show(this, element);
+ this.position((this.options.fixed) ? {page: element.getPosition()} : event);
+ }).delay(this.options.showDelay, this);
},
elementLeave: function(event, element){
$clear(this.timer);
- this.tip.setStyle('display', 'none');
this.timer = this.hide.delay(this.options.hideDelay, this, element);
+ this.fireForParent(event, element);
},
- elementMove: function(event){
+ fireForParent: function(event, element){
+ element = element.getParent();
+ if (!element || element == document.body) return;
+ if (element.retrieve('tip:enter')) element.fireEvent('mouseenter', event);
+ else this.fireForParent(event, element);
+ },
+
+ elementMove: function(event, element){
this.position(event);
},
position: function(event){
+ if (!this.tip) document.id(this);
+
var size = window.getSize(), scroll = window.getScroll(),
tip = {x: this.tip.offsetWidth, y: this.tip.offsetHeight},
props = {x: 'left', y: 'top'},
obj = {};
-
+
for (var z in props){
obj[props[z]] = event.page[z] + this.options.offset[z];
- if ((obj[props[z]] + tip[z] - scroll[z]) > size[z]) obj[props[z]] = event.page[z] - this.options.offset[z] - tip[z];
+ if ((obj[props[z]] + tip[z] - scroll[z]) > size[z] - this.options.windowPadding[z]) obj[props[z]] = event.page[z] - this.options.offset[z] - tip[z];
}
-
+
this.tip.setStyles(obj);
},
@@ -771,12 +1015,16 @@
else element.adopt(contents);
},
- show: function(el){
- this.fireEvent('show', [this.tip, el]);
+ show: function(element){
+ if (!this.tip) document.id(this);
+ this.fireEvent('show', [this.tip, element]);
},
- hide: function(el){
- this.fireEvent('hide', [this.tip, el]);
+ hide: function(element){
+ if (!this.tip) document.id(this);
+ this.fireEvent('hide', [this.tip, element]);
}
-});
\ No newline at end of file
+});
+
+})();
\ No newline at end of file
Added: incubator/jspwiki/trunk/src/WebContent/scripts/wysiwyg/MooEditable.Extras.js
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/WebContent/scripts/wysiwyg/MooEditable.Extras.js?rev=917294&view=auto
==============================================================================
--- incubator/jspwiki/trunk/src/WebContent/scripts/wysiwyg/MooEditable.Extras.js (added)
+++ incubator/jspwiki/trunk/src/WebContent/scripts/wysiwyg/MooEditable.Extras.js Sun Feb 28 21:12:40 2010
@@ -0,0 +1,61 @@
+/*
+Script: MooEditable.Extras.js
+ Extends MooEditable to include more (simple) toolbar buttons.
+
+License:
+ MIT-style license.
+*/
+
+MooEditable.Actions.extend({
+
+ formatBlock: {
+ title: 'Block Formatting',
+ type: 'menu-list',
+ options: {
+ list: [
+ {text: 'Paragraph', value: 'p'},
+ {text: 'Heading 1', value: 'h1'},
+ {text: 'Heading 2', value: 'h2'},
+ {text: 'Heading 3', value: 'h3'}
+ ]
+ },
+ states: {
+ tags: ['p', 'h1', 'h2', 'h3']
+ },
+ command: function(menulist, name){
+ var argument = '<' + name + '>';
+ this.execute('formatBlock', false, argument);
+ this.focus();
+ }
+ },
+
+ justifyleft:{
+ title: 'Align Left',
+ states: {
+ css: {'text-align': 'left'}
+ }
+ },
+
+ justifyright:{
+ title: 'Align Right',
+ states: {
+ css: {'text-align': 'right'}
+ }
+ },
+
+ justifycenter:{
+ title: 'Align Center',
+ states: {
+ tags: ['center'],
+ css: {'text-align': 'center'}
+ }
+ },
+
+ justifyfull:{
+ title: 'Align Justify',
+ states: {
+ css: {'text-align': 'justify'}
+ }
+ }
+
+});
Propchange: incubator/jspwiki/trunk/src/WebContent/scripts/wysiwyg/MooEditable.Extras.js
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/jspwiki/trunk/src/WebContent/scripts/wysiwyg/MooEditable.Group.js
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/WebContent/scripts/wysiwyg/MooEditable.Group.js?rev=917294&view=auto
==============================================================================
--- incubator/jspwiki/trunk/src/WebContent/scripts/wysiwyg/MooEditable.Group.js (added)
+++ incubator/jspwiki/trunk/src/WebContent/scripts/wysiwyg/MooEditable.Group.js Sun Feb 28 21:12:40 2010
@@ -0,0 +1,55 @@
+/*
+Script: MooEditable.Group.js
+ A MooEditable extension for having multiple MooEditable instances on a page controlled by one toolbar.
+
+License:
+ MIT-style license.
+*/
+
+MooEditable.Group = new Class({
+
+ Implements: [Options],
+
+ options: {
+ actions: 'bold italic underline strikethrough | insertunorderedlist insertorderedlist indent outdent | undo redo | createlink unlink | urlimage | toggleview'
+ },
+
+ initialize: function(toolbarEl, options){
+ this.setOptions(options);
+ this.actions = this.options.actions.clean().split(' ');
+ var self = this;
+ this.toolbar = new MooEditable.UI.Toolbar({
+ onItemAction: function(){
+ var args = $splat(arguments);
+ var item = args[0];
+ if (!self.activeEditor) return;
+ self.activeEditor.focus();
+ self.activeEditor.action(item.name, args);
+ if (self.activeEditor.mode == 'iframe') self.activeEditor.checkStates();
+ }
+ }).render(this.actions);
+ document.id(toolbarEl).adopt(this.toolbar);
+ },
+
+ add: function(textarea, options){
+ return this.activeEditor = new MooEditable.Group.Item(textarea, this, $merge({toolbar: false}, this.options, options));
+ }
+
+});
+
+
+MooEditable.Group.Item = new Class({
+
+ Extends: MooEditable,
+
+ initialize: function(textarea, group, options){
+ this.group = group;
+ this.parent(textarea, options);
+ var focus = function(){
+ this.group.activeEditor = this;
+ }.bind(this);
+ this.textarea.addEvent('focus', focus);
+ this.win.addEvent('focus', focus);
+ }
+
+});
\ No newline at end of file
Propchange: incubator/jspwiki/trunk/src/WebContent/scripts/wysiwyg/MooEditable.Group.js
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/jspwiki/trunk/src/WebContent/scripts/wysiwyg/MooEditable.UI.ButtonOverlay.js
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/WebContent/scripts/wysiwyg/MooEditable.UI.ButtonOverlay.js?rev=917294&view=auto
==============================================================================
--- incubator/jspwiki/trunk/src/WebContent/scripts/wysiwyg/MooEditable.UI.ButtonOverlay.js (added)
+++ incubator/jspwiki/trunk/src/WebContent/scripts/wysiwyg/MooEditable.UI.ButtonOverlay.js Sun Feb 28 21:12:40 2010
@@ -0,0 +1,95 @@
+/*
+Script: MooEditable.UI.ButtonOverlay.js
+ UI Class to create a button element with a popup overlay.
+
+License:
+ MIT-style license.
+
+Copyright:
+ Copyright (c) 2007-2009 [Lim Chee Aun](http://cheeaun.com).
+*/
+
+MooEditable.UI.ButtonOverlay = new Class({
+
+ Extends: MooEditable.UI.Button,
+
+ options: {
+ /*
+ onOpenOverlay: $empty,
+ onCloseOverlay: $empty,
+ */
+ overlayHTML: '',
+ overlayClass: '',
+ overlaySize: {x: 150, y: 'auto'},
+ overlayContentClass: ''
+ },
+
+ initialize: function(options){
+ this.parent(options);
+ this.render();
+ this.el.addClass('mooeditable-ui-buttonOverlay');
+ this.renderOverlay(this.options.overlayHTML);
+ },
+
+ renderOverlay: function(html){
+ var self = this;
+ this.overlay = new Element('div', {
+ 'class': 'mooeditable-ui-button-overlay ' + self.name + '-overlay ' + self.options.overlayClass,
+ html: '<div class="overlay-content ' + self.options.overlayContentClass + '">' + html + '</div>',
+ tabindex: 0,
+ styles: {
+ left: '-999em',
+ position: 'absolute',
+ width: self.options.overlaySize.x,
+ height: self.options.overlaySize.y
+ },
+ events: {
+ mousedown: self.clickOverlay.bind(self),
+ focus: self.openOverlay.bind(self),
+ blur: self.closeOverlay.bind(self)
+ }
+ }).inject(document.body).store('MooEditable.UI.ButtonOverlay', this);
+ this.overlayVisible = false;
+ },
+
+ openOverlay: function(){
+ if (this.overlayVisible) return;
+ this.overlayVisible = true;
+ this.activate();
+ this.fireEvent('openOverlay', this);
+ return this;
+ },
+
+ closeOverlay: function(){
+ if (!this.overlayVisible) return;
+ this.overlay.setStyle('left', '-999em');
+ this.overlayVisible = false;
+ this.deactivate();
+ this.fireEvent('closeOverlay', this);
+ return this;
+ },
+
+ clickOverlay: function(e){
+ if (e.target == this.overlay || e.target.parentNode == this.overlay) return;
+ e.preventDefault();
+ this.action(e);
+ this.overlay.blur();
+ },
+
+ click: function(e){
+ e.preventDefault();
+ if (this.disabled) return;
+ if (this.overlayVisible){
+ this.overlay.blur();
+ return;
+ } else {
+ var coords = this.el.getCoordinates();
+ this.overlay.setStyles({
+ top: coords.bottom,
+ left: coords.left
+ });
+ this.overlay.focus();
+ }
+ }
+
+});
\ No newline at end of file
Propchange: incubator/jspwiki/trunk/src/WebContent/scripts/wysiwyg/MooEditable.UI.ButtonOverlay.js
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/jspwiki/trunk/src/WebContent/scripts/wysiwyg/MooEditable.UI.MenuList.js
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/WebContent/scripts/wysiwyg/MooEditable.UI.MenuList.js?rev=917294&view=auto
==============================================================================
--- incubator/jspwiki/trunk/src/WebContent/scripts/wysiwyg/MooEditable.UI.MenuList.js (added)
+++ incubator/jspwiki/trunk/src/WebContent/scripts/wysiwyg/MooEditable.UI.MenuList.js Sun Feb 28 21:12:40 2010
@@ -0,0 +1,109 @@
+/*
+Script: MooEditable.UI.MenuList.js
+ UI Class to create a menu list (select) element.
+
+License:
+ MIT-style license.
+
+Copyright:
+ Copyright (c) 2007-2009 [Lim Chee Aun](http://cheeaun.com).
+*/
+
+MooEditable.UI.MenuList = new Class({
+
+ Implements: [Events, Options],
+
+ options: {
+ /*
+ onAction: $empty,
+ */
+ title: '',
+ name: '',
+ 'class': '',
+ list: []
+ },
+
+ initialize: function(options){
+ this.setOptions(options);
+ this.name = this.options.name;
+ this.render();
+ },
+
+ toElement: function(){
+ return this.el;
+ },
+
+ render: function(){
+ var self = this;
+ var html = '';
+ this.options.list.each(function(item){
+ html += '<option value="{value}">{text}</option>'.substitute(item);
+ });
+ this.el = new Element('select', {
+ 'class': self.options['class'],
+ title: self.options.title,
+ html: html,
+ events: {
+ change: self.change.bind(self)
+ }
+ });
+
+ this.disabled = false;
+
+ // add hover effect for IE
+ if (Browser.Engine.trident) this.el.addEvents({
+ mouseenter: function(e){ this.addClass('hover'); },
+ mouseleave: function(e){ this.removeClass('hover'); }
+ });
+
+ return this;
+ },
+
+ change: function(e){
+ e.preventDefault();
+ if (this.disabled) return;
+ var name = e.target.value;
+ this.action(name);
+ },
+
+ action: function(){
+ this.fireEvent('action', [this].concat($A(arguments)));
+ },
+
+ enable: function(){
+ if (!this.disabled) return;
+ this.disabled = false;
+ this.el.set('disabled', false).removeClass('disabled').set({
+ disabled: false,
+ opacity: 1
+ });
+ return this;
+ },
+
+ disable: function(){
+ if (this.disabled) return;
+ this.disabled = true;
+ this.el.set('disabled', true).addClass('disabled').set({
+ disabled: true,
+ opacity: 0.4
+ });
+ return this;
+ },
+
+ activate: function(value){
+ if (this.disabled) return;
+ var index = 0;
+ if (value) this.options.list.each(function(item, i){
+ if (item.value == value) index = i;
+ });
+ this.el.selectedIndex = index;
+ return this;
+ },
+
+ deactivate: function(){
+ this.el.selectedIndex = 0;
+ this.el.removeClass('onActive');
+ return this;
+ }
+
+});
\ No newline at end of file
Propchange: incubator/jspwiki/trunk/src/WebContent/scripts/wysiwyg/MooEditable.UI.MenuList.js
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/jspwiki/trunk/src/WebContent/scripts/wysiwyg/MooEditable.js
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/WebContent/scripts/wysiwyg/MooEditable.js?rev=917294&view=auto
==============================================================================
--- incubator/jspwiki/trunk/src/WebContent/scripts/wysiwyg/MooEditable.js (added)
+++ incubator/jspwiki/trunk/src/WebContent/scripts/wysiwyg/MooEditable.js Sun Feb 28 21:12:40 2010
@@ -0,0 +1,1203 @@
+/*
+Script: MooEditable.js
+ Class for creating a WYSIWYG editor, for contentEditable-capable browsers.
+
+License:
+ MIT-style license.
+
+Copyright:
+ Copyright (c) 2007-2009 [Lim Chee Aun](http://cheeaun.com).
+
+Build: %build%
+
+Credits:
+ - Code inspired by Stefan's work [Safari Supports Content Editing!](http://www.xs4all.nl/~hhijdra/stefan/ContentEditable.html) from [safari gets contentEditable](http://walkah.net/blog/walkah/safari-gets-contenteditable)
+ - Main reference from Peter-Paul Koch's [execCommand compatibility](http://www.quirksmode.org/dom/execCommand.html)
+ - Some ideas and code inspired by [TinyMCE](http://tinymce.moxiecode.com/)
+ - Some functions inspired by Inviz's [Most tiny wysiwyg you ever seen](http://forum.mootools.net/viewtopic.php?id=746), [mooWyg (Most tiny WYSIWYG 2.0)](http://forum.mootools.net/viewtopic.php?id=5740)
+ - Some regex from Cameron Adams's [widgEditor](http://widgeditor.googlecode.com/)
+ - Some code from Juan M Martinez's [jwysiwyg](http://jwysiwyg.googlecode.com/)
+ - Some reference from MoxieForge's [PunyMCE](http://punymce.googlecode.com/)
+ - IE support referring Robert Bredlau's [Rich Text Editing](http://www.rbredlau.com/drupal/node/6)
+ - Tango icons from the [Tango Desktop Project](http://tango.freedesktop.org/)
+ - Additional Tango icons from Jimmacs' [Tango OpenOffice](http://www.gnome-look.org/content/show.php/Tango+OpenOffice?content=54799)
+*/
+
+var MooEditable = new Class({
+
+ Implements: [Events, Options],
+
+ options: {
+ toolbar: true,
+ cleanup: true,
+ paragraphise: true,
+ xhtml : true,
+ semantics : true,
+ actions: 'bold italic underline strikethrough | insertunorderedlist insertorderedlist indent outdent | undo redo | createlink unlink | urlimage | toggleview',
+ handleSubmit: true,
+ handleLabel: true,
+ baseCSS: 'html{ height: 100%; cursor: text } body{ font-family: sans-serif; border: 0; }',
+ extraCSS: '',
+ externalCSS: '',
+ html: '<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><style>{BASECSS} {EXTRACSS}</style>{EXTERNALCSS}</head><body>{CONTENT}</body></html>'
+ },
+
+ initialize: function(el, options){
+ this.setOptions(options);
+ this.textarea = document.id(el);
+ this.textarea.store('MooEditable', this);
+ this.actions = this.options.actions.clean().split(' ');
+ this.keys = {};
+ this.dialogs = {};
+ this.actions.each(function(action){
+ var act = MooEditable.Actions[action];
+ if (!act) return;
+ if (act.options){
+ var key = act.options.shortcut;
+ if (key) this.keys[key] = action;
+ }
+ if (act.dialogs){
+ $each(act.dialogs, function(dialog, name){
+ dialog = dialog.attempt(this);
+ dialog.name = action + ':' + name;
+ if ($type(this.dialogs[action]) != 'object') this.dialogs[action] = {};
+ this.dialogs[action][name] = dialog;
+ }, this);
+ }
+ if (act.events){
+ $each(act.events, function(fn, event){
+ this.addEvent(event, fn);
+ }, this);
+ }
+ }.bind(this));
+ this.render();
+ },
+
+ toElement: function(){
+ return this.textarea;
+ },
+
+ render: function(){
+ var self = this;
+
+ // Dimensions
+ var dimensions = this.textarea.getSize();
+
+ // Build the container
+ this.container = new Element('div', {
+ id: (this.textarea.id) ? this.textarea.id + '-mooeditable-container' : null,
+ 'class': 'mooeditable-container',
+ styles: {
+ width: dimensions.x
+ }
+ });
+
+ // Override all textarea styles
+ this.textarea.addClass('mooeditable-textarea').setStyle('height', dimensions.y);
+
+ // Build the iframe
+ this.iframe = new IFrame({
+ 'class': 'mooeditable-iframe',
+ styles: {
+ height: dimensions.y
+ }
+ });
+
+ this.toolbar = new MooEditable.UI.Toolbar({
+ onItemAction: function(){
+ var args = $splat(arguments);
+ var item = args[0];
+ self.action(item.name, args);
+ }
+ });
+ this.attach.delay(1, this);
+
+ // Update the event for textarea's corresponding labels
+ if (this.options.handleLabel && this.textarea.id) $$('label[for="'+this.textarea.id+'"]').addEvent('click', function(e){
+ if (self.mode != 'iframe') return;
+ e.preventDefault();
+ self.focus();
+ });
+
+ // Update & cleanup content before submit
+ if (this.options.handleSubmit){
+ this.form = this.textarea.getParent('form');
+ if (!this.form) return;
+ this.form.addEvent('submit', function(){
+ if (self.mode == 'iframe') self.saveContent();
+ });
+ }
+
+ this.fireEvent('render', this);
+ },
+
+ attach: function(){
+ var self = this;
+
+ // Assign view mode
+ this.mode = 'iframe';
+
+ // Editor iframe state
+ this.editorDisabled = false;
+
+ // Put textarea inside container
+ this.container.wraps(this.textarea);
+
+ this.textarea.setStyle('display', 'none');
+
+ this.iframe.setStyle('display', '').inject(this.textarea, 'before');
+
+ $each(this.dialogs, function(action, name){
+ $each(action, function(dialog){
+ document.id(dialog).inject(self.iframe, 'before');
+ var range;
+ dialog.addEvents({
+ open: function(){
+ range = self.selection.getRange();
+ self.editorDisabled = true;
+ self.toolbar.disable(name);
+ self.fireEvent('dialogOpen', this);
+ },
+ close: function(){
+ self.toolbar.enable();
+ self.editorDisabled = false;
+ self.focus();
+ if (range) self.selection.setRange(range);
+ self.fireEvent('dialogClose', this);
+ }
+ });
+ });
+ });
+
+ // contentWindow and document references
+ this.win = this.iframe.contentWindow;
+ this.doc = this.win.document;
+
+ // Build the content of iframe
+ var docHTML = this.options.html.substitute({
+ BASECSS: this.options.baseCSS,
+ EXTRACSS: this.options.extraCSS,
+ EXTERNALCSS: (this.options.externalCSS) ? '<link rel="stylesheet" href="' + this.options.externalCSS + '">': '',
+ CONTENT: this.cleanup(this.textarea.get('value'))
+ });
+ this.doc.open();
+ this.doc.write(docHTML);
+ this.doc.close();
+
+ // Turn on Design Mode
+ // IE fired load event twice if designMode is set
+ (Browser.Engine.trident) ? this.doc.body.contentEditable = true : this.doc.designMode = 'On';
+
+ // Mootoolize window, document and body
+ if (!this.win.$family) new Window(this.win);
+ if (!this.doc.$family) new Document(this.doc);
+ document.id(this.doc.body);
+
+ // Bind all events
+ this.doc.addEvents({
+ mouseup: this.editorMouseUp.bind(this),
+ mousedown: this.editorMouseDown.bind(this),
+ contextmenu: this.editorContextMenu.bind(this),
+ click: this.editorClick.bind(this),
+ dbllick: this.editorDoubleClick.bind(this),
+ keypress: this.editorKeyPress.bind(this),
+ keyup: this.editorKeyUp.bind(this),
+ keydown: this.editorKeyDown.bind(this)
+ });
+ this.textarea.addEvent('keypress', this.textarea.retrieve('mooeditable:textareaKeyListener', this.keyListener.bind(this)));
+
+ // Fix window focus event not firing on Firefox 2
+ if (Browser.Engine.gecko && Browser.Engine.version == 18) this.doc.addEvent('focus', function(){
+ self.win.fireEvent('focus').focus();
+ });
+
+ // styleWithCSS, not supported in IE and Opera
+ if (!(/trident|presto/i).test(Browser.Engine.name)){
+ var styleCSS = function(){
+ self.execute('styleWithCSS', false, false);
+ self.doc.removeEvent('focus', styleCSS);
+ };
+ this.win.addEvent('focus', styleCSS);
+ }
+
+ if (this.options.toolbar){
+ document.id(this.toolbar).inject(this.container, 'top');
+ this.toolbar.render(this.actions);
+ }
+
+ this.selection = new MooEditable.Selection(this.win);
+
+ this.fireEvent('attach', this);
+
+ return this;
+ },
+
+ detach: function(){
+ this.saveContent();
+ this.textarea.setStyle('display', '').removeClass('mooeditable-textarea').inject(this.container, 'before');
+ this.textarea.removeEvent('keypress', this.textarea.retrieve('mooeditable:textareaKeyListener'));
+ this.container.dispose();
+ this.fireEvent('detach', this);
+ return this;
+ },
+
+ editorMouseUp: function(e){
+ if (this.editorDisabled){
+ e.stop();
+ return;
+ }
+
+ if (this.options.toolbar) this.checkStates();
+
+ this.fireEvent('editorMouseUp', e);
+ },
+
+ editorMouseDown: function(e){
+ if (this.editorDisabled){
+ e.stop();
+ return;
+ }
+
+ this.fireEvent('editorMouseDown', e);
+ },
+
+ editorContextMenu: function(e){
+ if (this.editorDisabled){
+ e.stop();
+ return;
+ }
+
+ this.fireEvent('editorContextMenu', e);
+ },
+
+ editorClick: function(e){
+ // make images selectable and draggable in Safari
+ if (Browser.Engine.webkit){
+ var el = e.target;
+ if (el.get('tag') == 'img'){
+ this.selection.selectNode(el);
+ }
+ }
+
+ this.fireEvent('editorClick', e);
+ },
+
+ editorDoubleClick: function(e){
+ this.fireEvent('editorDoubleClick', e);
+ },
+
+ editorKeyPress: function(e){
+ if (this.editorDisabled){
+ e.stop();
+ return;
+ }
+
+ this.keyListener(e);
+
+ this.fireEvent('editorKeyPress', e);
+ },
+
+ editorKeyUp: function(e){
+ if (this.editorDisabled){
+ e.stop();
+ return;
+ }
+
+ if (this.options.toolbar) this.checkStates();
+
+ this.fireEvent('editorKeyUp', e);
+ },
+
+ editorKeyDown: function(e){
+ if (this.editorDisabled){
+ e.stop();
+ return;
+ }
+
+ if (e.key == 'enter'){
+ if (this.options.paragraphise){
+ if (e.shift && Browser.Engine.webkit){
+ var s = this.selection;
+ var r = s.getRange();
+
+ // Insert BR element
+ var br = this.doc.createElement('br');
+ r.insertNode(br);
+
+ // Place caret after BR
+ r.setStartAfter(br);
+ r.setEndAfter(br);
+ s.setRange(r);
+
+ // Could not place caret after BR then insert an nbsp entity and move the caret
+ if (s.getSelection().focusNode == br.previousSibling){
+ var nbsp = this.doc.createTextNode('\u00a0');
+ var p = br.parentNode;
+ var ns = br.nextSibling;
+ (ns) ? p.insertBefore(nbsp, ns) : p.appendChild(nbsp);
+ s.selectNode(nbsp);
+ s.collapse(1);
+ }
+
+ // Scroll to new position, scrollIntoView can't be used due to bug: http://bugs.webkit.org/show_bug.cgi?id=16117
+ this.win.scrollTo(0, Element.getOffsets(s.getRange().startContainer).y);
+
+ e.preventDefault();
+ } else if (Browser.Engine.gecko || Browser.Engine.webkit){
+ var node = this.selection.getNode();
+ var blockEls = /^(H[1-6]|P|DIV|ADDRESS|PRE|FORM|TABLE|LI|OL|UL|TD|CAPTION|BLOCKQUOTE|CENTER|DL|DT|DD)$/;
+ var isBlock = node.getParents().include(node).some(function(el){
+ return el.nodeName.test(blockEls);
+ });
+ if (!isBlock) this.execute('insertparagraph');
+ }
+ } else {
+ if (Browser.Engine.trident){
+ var r = this.selection.getRange();
+ var node = this.selection.getNode();
+ if (r && node.get('tag') != 'li'){
+ this.selection.insertContent('<br>');
+ this.selection.collapse(false);
+ }
+ e.preventDefault();
+ }
+ }
+ }
+
+ this.fireEvent('editorKeyDown', e);
+ },
+
+ keyListener: function(e){
+ var key = (Browser.Platform.mac) ? e.meta : e.control;
+ if (!key || !this.keys[e.key]) return;
+ e.preventDefault();
+ var item = this.toolbar.getItem(this.keys[e.key]);
+ item.action(e);
+ },
+
+ focus: function(){
+ // needs the delay to get focus working
+ (function(){
+ (this.mode == 'iframe' ? this.win : this.textarea).focus();
+ this.fireEvent('focus', this);
+ }).bind(this).delay(10);
+ return this;
+ },
+
+ action: function(command, args){
+ var action = MooEditable.Actions[command];
+ if (action.command && $type(action.command) == 'function'){
+ action.command.run(args, this);
+ } else {
+ this.focus();
+ this.execute(command, false, args);
+ if (this.mode == 'iframe') this.checkStates();
+ }
+ },
+
+ execute: function(command, param1, param2){
+ if (this.busy) return;
+ this.busy = true;
+ this.doc.execCommand(command, param1, param2);
+ this.saveContent();
+ this.busy = false;
+ return false;
+ },
+
+ toggleView: function(){
+ this.fireEvent('beforeToggleView', this);
+ if (this.mode == 'textarea'){
+ this.mode = 'iframe';
+ this.iframe.setStyle('display', '');
+ this.setContent(this.textarea.value);
+ this.textarea.setStyle('display', 'none');
+ } else {
+ this.saveContent();
+ this.mode = 'textarea';
+ this.textarea.setStyle('display', '');
+ this.iframe.setStyle('display', 'none');
+ }
+ this.fireEvent('toggleView', this);
+ this.focus();
+ return this;
+ },
+
+ getContent: function(){
+ return this.cleanup(this.doc.body.get('html'));
+ },
+
+ setContent: function(newContent){
+ this.doc.body.set('html', newContent);
+ return this;
+ },
+
+ saveContent: function(){
+ if (this.mode == 'iframe') this.textarea.set('value', this.getContent());
+ return this;
+ },
+
+ checkStates: function(){
+ this.actions.each(function(action){
+ var item = this.toolbar.getItem(action);
+ if (!item) return;
+ item.deactivate();
+
+ var states = MooEditable.Actions[action]['states'];
+ if (!states) return;
+
+ var el = this.selection.getNode();
+ if (!el) return;
+
+ // custom checkState
+ if ($type(states) == 'function'){
+ states.attempt(el, item);
+ return;
+ }
+
+ try{
+ if (this.doc.queryCommandState(action)){
+ item.activate();
+ return;
+ }
+ } catch(e) {}
+
+ if (states.tags){
+ do {
+ if ($type(el) != 'element') break;
+ var tag = el.tagName.toLowerCase();
+ if (states.tags.contains(tag)){
+ item.activate(tag);
+ break;
+ }
+ }
+ while (el = el.parentNode);
+ }
+
+ if (states.css){
+ var blockEls = /^(H[1-6]|P|DIV|ADDRESS|PRE|FORM|TABLE|LI|OL|UL|TD|CAPTION|BLOCKQUOTE|CENTER|DL|DT|DD)$/;
+ do {
+ if ($type(el) != 'element') break;
+ var found = false;
+ for (var prop in states.css){
+ var css = states.css[prop];
+ if (document.id(el).getStyle(prop).contains(css)){
+ item.activate(css);
+ found = true;
+ }
+ }
+ if (found || el.tagName.test(blockEls)) break;
+ }
+ while (el = el.parentNode);
+ }
+ }.bind(this));
+ },
+
+ cleanup: function(source){
+ if (!this.options.cleanup) return source.trim();
+
+ do {
+ var oSource = source;
+
+ // Webkit cleanup
+ source = source.replace(/<br class\="webkit-block-placeholder">/gi, "<br />");
+ source = source.replace(/<span class="Apple-style-span">(.*)<\/span>/gi, '$1');
+ source = source.replace(/ class="Apple-style-span"/gi, '');
+ source = source.replace(/<span style="">/gi, '');
+
+ // Remove padded paragraphs
+ source = source.replace(/<p>\s*<br ?\/?>\s*<\/p>/gi, '<p>\u00a0</p>');
+ source = source.replace(/<p>( |\s)*<\/p>/gi, '<p>\u00a0</p>');
+ if (!this.options.semantics){
+ source = source.replace(/\s*<br ?\/?>\s*<\/p>/gi, '</p>');
+ }
+
+ // Replace improper BRs (only if XHTML : true)
+ if (this.options.xhtml){
+ source = source.replace(/<br>/gi, "<br />");
+ }
+
+ if (this.options.semantics){
+ //remove divs from <li>
+ if (Browser.Engine.trident){
+ source = source.replace(/<li>\s*<div>(.+?)<\/div><\/li>/g, '<li>$1</li>');
+ }
+ //remove stupid apple divs
+ if (Browser.Engine.webkit){
+ source = source.replace(/^([\w\s]+.*?)<div>/i, '<p>$1</p><div>');
+ source = source.replace(/<div>(.+?)<\/div>/ig, '<p>$1</p>');
+ }
+
+ //<p> tags around a list will get moved to after the list
+ if (['gecko', 'presto', 'webkit'].contains(Browser.Engine.name)){
+ //not working properly in safari?
+ source = source.replace(/<p>[\s\n]*(<(?:ul|ol)>.*?<\/(?:ul|ol)>)(.*?)<\/p>/ig, '$1<p>$2</p>');
+ source = source.replace(/<\/(ol|ul)>\s*(?!<(?:p|ol|ul|img).*?>)((?:<[^>]*>)?\w.*)$/g, '</$1><p>$2</p>');
+ }
+
+ source = source.replace(/<br[^>]*><\/p>/g, '</p>'); //remove <br>'s that end a paragraph here.
+ source = source.replace(/<p>\s*(<img[^>]+>)\s*<\/p>/ig, '$1\n'); //if a <p> only contains <img>, remove the <p> tags
+
+ //format the source
+ source = source.replace(/<p([^>]*)>(.*?)<\/p>(?!\n)/g, '<p$1>$2</p>\n'); //break after paragraphs
+ source = source.replace(/<\/(ul|ol|p)>(?!\n)/g, '</$1>\n'); //break after </p></ol></ul> tags
+ source = source.replace(/><li>/g, '>\n\t<li>'); //break and indent <li>
+ source = source.replace(/([^\n])<\/(ol|ul)>/g, '$1\n</$2>'); //break before </ol></ul> tags
+ source = source.replace(/([^\n])<img/ig, '$1\n<img'); //move images to their own line
+ source = source.replace(/^\s*$/g, ''); //delete empty lines in the source code (not working in opera)
+ }
+
+ // Remove leading and trailing BRs
+ source = source.replace(/<br ?\/?>$/gi, '');
+ source = source.replace(/^<br ?\/?>/gi, '');
+
+ // Remove useless BRs
+ source = source.replace(/><br ?\/?>/gi, '>');
+
+ // Remove BRs right before the end of blocks
+ source = source.replace(/<br ?\/?>\s*<\/(h1|h2|h3|h4|h5|h6|li|p)/gi, '</$1');
+
+ // Semantic conversion
+ source = source.replace(/<span style="font-weight: bold;">(.*)<\/span>/gi, '<strong>$1</strong>');
+ source = source.replace(/<span style="font-style: italic;">(.*)<\/span>/gi, '<em>$1</em>');
+ source = source.replace(/<b\b[^>]*>(.*?)<\/b[^>]*>/gi, '<strong>$1</strong>');
+ source = source.replace(/<i\b[^>]*>(.*?)<\/i[^>]*>/gi, '<em>$1</em>');
+ source = source.replace(/<u\b[^>]*>(.*?)<\/u[^>]*>/gi, '<span style="text-decoration: underline;">$1</span>');
+
+ // Replace uppercase element names with lowercase
+ source = source.replace(/<[^> ]*/g, function(match){return match.toLowerCase();});
+
+ // Replace uppercase attribute names with lowercase
+ source = source.replace(/<[^>]*>/g, function(match){
+ match = match.replace(/ [^=]+=/g, function(match2){return match2.toLowerCase();});
+ return match;
+ });
+
+ // Put quotes around unquoted attributes
+ source = source.replace(/<[^>]*>/g, function(match){
+ match = match.replace(/( [^=]+=)([^"][^ >]*)/g, "$1\"$2\"");
+ return match;
+ });
+
+ //make img tags xhtml compatable
+ // if (this.options.xhtml){
+ // source = source.replace(/(<(?:img|input)[^/>]*)>/g, '$1 />');
+ // }
+
+ //remove double <p> tags and empty <p> tags
+ source = source.replace(/<p>(?:\s*)<p>/g, '<p>');
+ source = source.replace(/<\/p>\s*<\/p>/g, '</p>');
+ source = source.replace(/<p>\W*<\/p>/g, '');
+
+ // Final trim
+ source = source.trim();
+ }
+ while (source != oSource);
+
+ return source;
+ }
+
+});
+
+MooEditable.Selection = new Class({
+
+ initialize: function(win){
+ this.win = win;
+ },
+
+ getSelection: function(){
+ this.win.focus();
+ return (this.win.getSelection) ? this.win.getSelection() : this.win.document.selection;
+ },
+
+ getRange: function(){
+ var s = this.getSelection();
+
+ if (!s) return null;
+
+ try {
+ return s.rangeCount > 0 ? s.getRangeAt(0) : (s.createRange ? s.createRange() : null);
+ } catch(e) {
+ // IE bug when used in frameset
+ return this.doc.body.createTextRange();
+ }
+ },
+
+ setRange: function(range){
+ if (range.select){
+ $try(function(){
+ range.select();
+ });
+ } else {
+ var s = this.getSelection();
+ if (s.addRange){
+ s.removeAllRanges();
+ s.addRange(range);
+ }
+ }
+ },
+
+ selectNode: function(node, collapse){
+ var r = this.getRange();
+ var s = this.getSelection();
+
+ if (r.moveToElementText){
+ $try(function(){
+ r.moveToElementText(node);
+ r.select();
+ });
+ } else if (s.addRange){
+ collapse ? r.selectNodeContents(node) : r.selectNode(node);
+ s.removeAllRanges();
+ s.addRange(r);
+ } else {
+ s.setBaseAndExtent(node, 0, node, 1);
+ }
+
+ return node;
+ },
+
+ isCollapsed: function(){
+ var r = this.getRange();
+ if (r.item) return false;
+ return r.boundingWidth == 0 || this.getSelection().isCollapsed;
+ },
+
+ collapse: function(toStart){
+ var r = this.getRange();
+ var s = this.getSelection();
+
+ if (r.select){
+ r.collapse(toStart);
+ r.select();
+ } else {
+ toStart ? s.collapseToStart() : s.collapseToEnd();
+ }
+ },
+
+ getContent: function(){
+ var r = this.getRange();
+ var body = new Element('body');
+
+ if (this.isCollapsed()) return '';
+
+ if (r.cloneContents){
+ body.appendChild(r.cloneContents());
+ } else if ($defined(r.item) || $defined(r.htmlText)){
+ body.set('html', r.item ? r.item(0).outerHTML : r.htmlText);
+ } else {
+ body.set('html', r.toString());
+ }
+
+ var content = body.get('html');
+ return content;
+ },
+
+ getText : function(){
+ var r = this.getRange();
+ var s = this.getSelection();
+
+ return this.isCollapsed() ? '' : r.text || s.toString();
+ },
+
+ getNode: function(){
+ var r = this.getRange();
+
+ if (!Browser.Engine.trident){
+ var el = null;
+
+ if (r){
+ el = r.commonAncestorContainer;
+
+ // Handle selection a image or other control like element such as anchors
+ if (!r.collapsed)
+ if (r.startContainer == r.endContainer)
+ if (r.startOffset - r.endOffset < 2)
+ if (r.startContainer.hasChildNodes())
+ el = r.startContainer.childNodes[r.startOffset];
+
+ while ($type(el) != 'element') el = el.parentNode;
+ }
+
+ return document.id(el);
+ }
+
+ return document.id(r.item ? r.item(0) : r.parentElement());
+ },
+
+ insertContent: function(content){
+ if (Browser.Engine.trident){
+ var r = this.getRange();
+ r.pasteHTML(content);
+ r.collapse(false);
+ r.select();
+ } else {
+ this.win.document.execCommand('insertHTML', false, content);
+ }
+ }
+
+});
+
+MooEditable.UI = {};
+
+MooEditable.UI.Toolbar= new Class({
+
+ Implements: [Events, Options],
+
+ options: {
+ /*
+ onItemAction: $empty,
+ */
+ 'class': ''
+ },
+
+ initialize: function(options){
+ this.setOptions(options);
+ this.el = new Element('div', {'class': 'mooeditable-ui-toolbar ' + this.options['class']});
+ this.items = {};
+ this.content = null;
+ },
+
+ toElement: function(){
+ return this.el;
+ },
+
+ render: function(actions){
+ if (this.content){
+ this.el.adopt(this.content);
+ } else {
+ this.content = actions.map(function(action){
+ return (action == '|') ? this.addSeparator() : this.addItem(action);
+ }.bind(this));
+ }
+ return this;
+ },
+
+ addItem: function(action){
+ var self = this;
+ var act = MooEditable.Actions[action];
+ if (!act) return;
+ var type = act.type || 'button';
+ var options = act.options || {};
+ var item = new MooEditable.UI[type.camelCase().capitalize()]($extend(options, {
+ name: action,
+ 'class': action + '-item toolbar-item',
+ title: act.title,
+ onAction: self.itemAction.bind(self)
+ }));
+ this.items[action] = item;
+ document.id(item).inject(this.el);
+ return item;
+ },
+
+ getItem: function(action){
+ return this.items[action];
+ },
+
+ addSeparator: function(){
+ return new Element('span', {'class': 'toolbar-separator'}).inject(this.el);
+ },
+
+ itemAction: function(){
+ this.fireEvent('itemAction', arguments);
+ },
+
+ disable: function(except){
+ $each(this.items, function(item){
+ (item.name == except) ? item.activate() : item.deactivate().disable();
+ });
+ return this;
+ },
+
+ enable: function(){
+ $each(this.items, function(item){
+ item.enable();
+ });
+ return this;
+ },
+
+ show: function(){
+ this.el.setStyle('display', '');
+ return this;
+ },
+
+ hide: function(){
+ this.el.setStyle('display', 'none');
+ return this;
+ }
+
+});
+
+MooEditable.UI.Button = new Class({
+
+ Implements: [Events, Options],
+
+ options: {
+ /*
+ onAction: $empty,
+ */
+ title: '',
+ name: '',
+ text: 'Button',
+ 'class': '',
+ shortcut: '',
+ mode: 'icon'
+ },
+
+ initialize: function(options){
+ this.setOptions(options);
+ this.name = this.options.name;
+ this.render();
+ },
+
+ toElement: function(){
+ return this.el;
+ },
+
+ render: function(){
+ var self = this;
+ var key = (Browser.Platform.mac) ? 'Cmd' : 'Ctrl';
+ var shortcut = (this.options.shortcut) ? ' ( ' + key + '+' + this.options.shortcut.toUpperCase() + ' )' : '';
+ var text = this.options.title || name;
+ var title = text + shortcut;
+ this.el = new Element('button', {
+ 'class': 'mooeditable-ui-button ' + self.options['class'],
+ title: title,
+ html: '<span class="button-icon"></span><span class="button-text">' + text + '</span>',
+ events: {
+ click: self.click.bind(self),
+ mousedown: function(e){ e.preventDefault(); }
+ }
+ });
+ if (this.options.mode != 'icon') this.el.addClass('mooeditable-ui-button-' + this.options.mode);
+
+ this.active = false;
+ this.disabled = false;
+
+ // add hover effect for IE
+ if (Browser.Engine.trident) this.el.addEvents({
+ mouseenter: function(e){ this.addClass('hover'); },
+ mouseleave: function(e){ this.removeClass('hover'); }
+ });
+
+ return this;
+ },
+
+ click: function(e){
+ e.preventDefault();
+ if (this.disabled) return;
+ this.action(e);
+ },
+
+ action: function(){
+ this.fireEvent('action', [this].concat($A(arguments)));
+ },
+
+ enable: function(){
+ if (this.active) this.el.removeClass('onActive');
+ if (!this.disabled) return;
+ this.disabled = false;
+ this.el.removeClass('disabled').set({
+ disabled: false,
+ opacity: 1
+ });
+ return this;
+ },
+
+ disable: function(){
+ if (this.disabled) return;
+ this.disabled = true;
+ this.el.addClass('disabled').set({
+ disabled: true,
+ opacity: 0.4
+ });
+ return this;
+ },
+
+ activate: function(){
+ if (this.disabled) return;
+ this.active = true;
+ this.el.addClass('onActive');
+ return this;
+ },
+
+ deactivate: function(){
+ this.active = false;
+ this.el.removeClass('onActive');
+ return this;
+ }
+
+});
+
+MooEditable.UI.Dialog = new Class({
+
+ Implements: [Events, Options],
+
+ options:{
+ /*
+ onOpen: $empty,
+ onClose: $empty,
+ */
+ 'class': '',
+ contentClass: ''
+ },
+
+ initialize: function(html, options){
+ this.setOptions(options);
+ this.html = html;
+
+ var self = this;
+ this.el = new Element('div', {
+ 'class': 'mooeditable-ui-dialog ' + self.options['class'],
+ html: '<div class="dialog-content ' + self.options.contentClass + '">' + html + '</div>',
+ styles: {
+ 'display': 'none'
+ },
+ events: {
+ click: self.click.bind(self)
+ }
+ });
+ },
+
+ toElement: function(){
+ return this.el;
+ },
+
+ click: function(){
+ this.fireEvent('click', arguments);
+ return this;
+ },
+
+ open: function(){
+ this.el.setStyle('display', '');
+ this.fireEvent('open', this);
+ return this;
+ },
+
+ close: function(){
+ this.el.setStyle('display', 'none');
+ this.fireEvent('close', this);
+ return this;
+ }
+
+});
+
+MooEditable.UI.AlertDialog = function(alertText){
+ if (!alertText) return;
+ var html = alertText + ' <button class="dialog-ok-button">OK</button>';
+ return new MooEditable.UI.Dialog(html, {
+ 'class': 'mooeditable-alert-dialog',
+ onOpen: function(){
+ var button = this.el.getElement('.dialog-ok-button');
+ (function(){
+ button.focus();
+ }).delay(10);
+ },
+ onClick: function(e){
+ e.preventDefault();
+ if (e.target.tagName.toLowerCase() != 'button') return;
+ if (document.id(e.target).hasClass('dialog-ok-button')) this.close();
+ }
+ });
+};
+
+MooEditable.UI.PromptDialog = function(questionText, answerText, fn){
+ if (!questionText) return;
+ var html = '<label class="dialog-label">' + questionText
+ + ' <input type="text" class="text dialog-input" value="' + answerText + '">'
+ + '</label> <button class="dialog-button dialog-ok-button">OK</button>'
+ + '<button class="dialog-button dialog-cancel-button">Cancel</button>';
+ return new MooEditable.UI.Dialog(html, {
+ 'class': 'mooeditable-prompt-dialog',
+ onOpen: function(){
+ var input = this.el.getElement('.dialog-input');
+ (function(){
+ input.focus();
+ input.select();
+ }).delay(10);
+ },
+ onClick: function(e){
+ e.preventDefault();
+ if (e.target.tagName.toLowerCase() != 'button') return;
+ var button = document.id(e.target);
+ var input = this.el.getElement('.dialog-input');
+ if (button.hasClass('dialog-cancel-button')){
+ input.set('value', answerText);
+ this.close();
+ } else if (button.hasClass('dialog-ok-button')){
+ var answer = input.get('value');
+ input.set('value', answerText);
+ this.close();
+ if (fn) fn.attempt(answer, this);
+ }
+ }
+ });
+};
+
+MooEditable.Actions = new Hash({
+
+ bold: {
+ title: 'Bold',
+ options: {
+ shortcut: 'b'
+ },
+ states: {
+ tags: ['b', 'strong'],
+ css: {'font-weight': 'bold'}
+ }
+ },
+
+ italic: {
+ title: 'Italic',
+ options: {
+ shortcut: 'i'
+ },
+ states: {
+ tags: ['i', 'em'],
+ css: {'font-style': 'italic'}
+ }
+ },
+
+ underline: {
+ title: 'Underline',
+ options: {
+ shortcut: 'u'
+ },
+ states: {
+ tags: ['u'],
+ css: {'text-decoration': 'underline'}
+ }
+ },
+
+ strikethrough: {
+ title: 'Strikethrough',
+ options: {
+ shortcut: 's'
+ },
+ states: {
+ tags: ['s', 'strike'],
+ css: {'text-decoration': 'line-through'}
+ }
+ },
+
+ insertunorderedlist: {
+ title: 'Unordered List',
+ states: {
+ tags: ['ul']
+ }
+ },
+
+ insertorderedlist: {
+ title: 'Ordered List',
+ states: {
+ tags: ['ol']
+ }
+ },
+
+ indent: {
+ title: 'Indent',
+ states: {
+ tags: ['blockquote']
+ }
+ },
+
+ outdent: {
+ title: 'Outdent'
+ },
+
+ undo: {
+ title: 'Undo',
+ options: {
+ shortcut: 'z'
+ }
+ },
+
+ redo: {
+ title: 'Redo',
+ options: {
+ shortcut: 'y'
+ }
+ },
+
+ unlink: {
+ title: 'Remove Hyperlink'
+ },
+
+ createlink: {
+ title: 'Add Hyperlink',
+ options: {
+ shortcut: 'l'
+ },
+ states: {
+ tags: ['a']
+ },
+ dialogs: {
+ alert: MooEditable.UI.AlertDialog.pass('Please select the text you wish to hyperlink.'),
+ prompt: function(editor){
+ return MooEditable.UI.PromptDialog('Enter URL', 'http://', function(url){
+ editor.execute('createlink', false, url.trim());
+ });
+ }
+ },
+ command: function(){
+ if (this.selection.isCollapsed()){
+ this.dialogs.createlink.alert.open();
+ } else {
+ var text = this.selection.getText();
+ var url = /^(https?|ftp|rmtp|mms):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(:(\d+))?\/?/i;
+ var prompt = this.dialogs.createlink.prompt;
+ if (url.test(text)) prompt.el.getElement('.mooeditable-dialog-input').set('value', text);
+ prompt.open();
+ }
+ }
+ },
+
+ urlimage: {
+ title: 'Add Image',
+ options: {
+ shortcut: 'm'
+ },
+ dialogs: {
+ prompt: function(editor){
+ return MooEditable.UI.PromptDialog('Enter image URL', 'http://', function(url){
+ editor.execute("insertimage", false, url.trim());
+ });
+ }
+ },
+ command: function(){
+ this.dialogs.urlimage.prompt.open();
+ }
+ },
+
+ toggleview: {
+ title: 'Toggle View',
+ command: function(){
+ (this.mode == 'textarea') ? this.toolbar.enable() : this.toolbar.disable('toggleview');
+ this.toggleView();
+ }
+ }
+
+});
+
+Element.Properties.mooeditable = {
+
+ set: function(options){
+ return this.eliminate('mooeditable').store('mooeditable:options', options);
+ },
+
+ get: function(options){
+ if (options || !this.retrieve('mooeditable')){
+ if (options || !this.retrieve('mooeditable:options')) this.set('mooeditable', options);
+ this.store('mooeditable', new MooEditable(this, this.retrieve('mooeditable:options')));
+ }
+ return this.retrieve('mooeditable');
+ }
+
+};
+
+Element.implement({
+
+ mooEditable: function(options){
+ return this.get('mooeditable', options);
+ }
+
+});
\ No newline at end of file
Propchange: incubator/jspwiki/trunk/src/WebContent/scripts/wysiwyg/MooEditable.js
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/jspwiki/trunk/src/WebContent/scripts/wysiwyg/MooEditableSilkTheme.css
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/WebContent/scripts/wysiwyg/MooEditableSilkTheme.css?rev=917294&view=auto
==============================================================================
--- incubator/jspwiki/trunk/src/WebContent/scripts/wysiwyg/MooEditableSilkTheme.css (added)
+++ incubator/jspwiki/trunk/src/WebContent/scripts/wysiwyg/MooEditableSilkTheme.css Sun Feb 28 21:12:40 2010
@@ -0,0 +1,73 @@
+/*
+ A change to the original MooEditable style
+
+ * Famfamfam Silk Iconset
+ * Darker gray color for mouse over selections
+ * Rounded corners for buttons and overlays (only supported on WebKit and FireFox)
+
+ Usage:
+ Include MooEditable.SilkTheme.css to overwrite the default settings
+
+ <link rel="stylesheet" type="text/css" href="../../Assets/MooEditable/MooEditable.css">
+ <link rel="stylesheet" type="text/css" href="../../Assets/MooEditable/MooEditable.Extras.css">
+ <link rel="stylesheet" type="text/css" href="../../Assets/MooEditable/MooEditable.SilkTheme.css">
+
+
+ Author: Olivier Refalo
+ */
+
+
+.mooeditable-ui-toolbar .mooeditable-ui-button .button-icon{
+ background: transparent url(images/mooeditable-toolbarbuttons-silk.png) no-repeat 0 -8px;
+}
+
+.mooeditable-ui-toolbar .bold-item .button-icon{ background-position: 0 -16px; }
+.mooeditable-ui-toolbar .createlink-item .button-icon{ background-position: 0 -32px; }
+.mooeditable-ui-toolbar .indent-item .button-icon{ background-position: 0 -48px; }
+.mooeditable-ui-toolbar .insertorderedlist-item .button-icon{ background-position: 0 -64px; }
+.mooeditable-ui-toolbar .insertunorderedlist-item .button-icon{ background-position: 0 -80px; }
+.mooeditable-ui-toolbar .italic-item .button-icon{ background-position: 0 -96px; }
+.mooeditable-ui-toolbar .outdent-item .button-icon{ background-position: 0 -176px; }
+.mooeditable-ui-toolbar .redo-item .button-icon{ background-position: 0 -208px; }
+.mooeditable-ui-toolbar .strikethrough-item .button-icon{ background-position: 0 -224px; }
+.mooeditable-ui-toolbar .toggleview-item .button-icon{ background-position: 0 -240px; }
+.mooeditable-ui-toolbar .underline-item .button-icon{ background-position: 0 -256px; }
+.mooeditable-ui-toolbar .undo-item .button-icon{ background-position: 0 -272px; }
+.mooeditable-ui-toolbar .unlink-item .button-icon{ background-position: 0 -288px; }
+.mooeditable-ui-toolbar .urlimage-item .button-icon{ background-position: 0 -304px; }
+.mooeditable-ui-toolbar .forecolor-item .button-icon{background-position: 0 -192px;}
+.mooeditable-ui-toolbar .smiley-item .button-icon{
+ background: transparent url(Smiley/smile.png) no-repeat top left;
+}
+
+.mooeditable-ui-toolbar .justifycenter-item .button-icon,
+.mooeditable-ui-toolbar .justifyright-item .button-icon,
+.mooeditable-ui-toolbar .justifyfull-item .button-icon,
+.mooeditable-ui-toolbar .justifyleft-item .button-icon{
+ background-image: url(images/mooeditable-toolbarbuttons-silk.png);
+}
+.mooeditable-ui-toolbar .justifycenter-item .button-icon{ background-position: 0 -112px; }
+.mooeditable-ui-toolbar .justifyfull-item .button-icon{ background-position: 0 -128px; }
+.mooeditable-ui-toolbar .justifyleft-item .button-icon{ background-position: 0 -144px; }
+.mooeditable-ui-toolbar .justifyright-item .button-icon{ background-position: 0 -160px; }
+
+.mooeditable-ui-toolbar .mooeditable-ui-button:hover,
+.mooeditable-ui-toolbar .mooeditable-ui-button.hover{
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ border-radius: 3px;
+}
+
+.mooeditable-ui-button-overlay{
+ -webkit-border-radius: 5px;
+ -moz-border-radius: 5px;
+ border-radius: 5px;
+}
+
+.mooeditable-ui-toolbar .mooeditable-ui-button.active,
+.mooeditable-ui-toolbar .mooeditable-ui-button.onActive{
+ background-color: #bbb;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ border-radius: 3px;
+}
Propchange: incubator/jspwiki/trunk/src/WebContent/scripts/wysiwyg/MooEditableSilkTheme.css
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/jspwiki/trunk/src/WebContent/scripts/wysiwyg/images/mooeditable-toolbarbuttons-silk.png
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/WebContent/scripts/wysiwyg/images/mooeditable-toolbarbuttons-silk.png?rev=917294&view=auto
==============================================================================
Binary file - no diff available.
Propchange: incubator/jspwiki/trunk/src/WebContent/scripts/wysiwyg/images/mooeditable-toolbarbuttons-silk.png
------------------------------------------------------------------------------
svn:executable = *
Propchange: incubator/jspwiki/trunk/src/WebContent/scripts/wysiwyg/images/mooeditable-toolbarbuttons-silk.png
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: incubator/jspwiki/trunk/src/WebContent/templates/default/AttachmentTab.jsp
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/WebContent/templates/default/AttachmentTab.jsp?rev=917294&view=auto
==============================================================================
--- incubator/jspwiki/trunk/src/WebContent/templates/default/AttachmentTab.jsp (added)
+++ incubator/jspwiki/trunk/src/WebContent/templates/default/AttachmentTab.jsp Sun Feb 28 21:12:40 2010
@@ -0,0 +1,159 @@
+<%--
+ JSPWiki - a JSP-based WikiWiki clone.
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+--%>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
+<%@ taglib uri="http://jakarta.apache.org/jspwiki.tld" prefix="wiki" %>
+<%@ taglib uri="http://stripes.sourceforge.net/stripes.tld" prefix="s" %>
+<%@ page import="org.apache.wiki.*" %>
+<%@ page import="javax.servlet.jsp.jstl.fmt.*" %>
+<%@ page import="org.apache.wiki.action.WikiContextFactory" %>
+<%@ page import="org.apache.wiki.util.TextUtil" %>
+<%@ page import="org.apache.wiki.api.WikiPage" %>
+<%@ page import="org.apache.wiki.content.jcr.JCRWikiPage" %>
+<%@ page import="java.text.SimpleDateFormat" %>
+<%@ page errorPage="${templates['Error.jsp']}" %>
+<%
+ int MAXATTACHNAMELENGTH = 30;
+ WikiContext c = WikiContextFactory.findContext( pageContext );
+ String progressId = c.getEngine().getProgressManager().getNewProgressIdentifier();
+
+ int attCount = c.getEngine().getAttachmentManager().listAttachments(c.getPage()).size();
+ String attTitle = LocaleSupport.getLocalizedMessage(pageContext, "attach.tab");
+ if( attCount != 0 ) attTitle += " (" + attCount + ")";
+%>
+<wiki:TabbedSection defaultTab="attach">
+
+ <wiki:Tab id="pagecontent" titleKey="view.tab" accesskey="v" url="Wiki.jsp?page=${wikiActionBean.page.name}"/>
+
+ <wiki:Tab id="attach" title="<%= attTitle %>" accesskey="a">
+ <div id="addattachment">
+ <h3><fmt:message key="attach.add" /></h3>
+ <wiki:Permission permission="upload">
+ <s:form beanclass="org.apache.wiki.action.AttachmentActionBean" class="wikiform" id="uploadform" acceptcharset="UTF-8">
+ <s:param name="progressid" value="<%=progressId%>" />
+ <s:param name="page" value="${wikiActionBean.page.name}" />
+ <table>
+ <tr>
+ <td colspan="2"><div class="formhelp"><fmt:message key="attach.add.info" /></div></td>
+ </tr>
+ <tr>
+ <td colspan="2"><s:errors field="newAttachments" /></td>
+ </tr>
+ <tr>
+ <td ><s:label for="attachfile" name="attach.add.selectfile" /></td>
+ <td><s:file name="newAttachments[0]" id="attachfile0" /></td>
+ </tr>
+ <tr>
+ <td><s:label for="attachnote" name="attach.add.changenote" /></td>
+ <td><s:text name="changenote" id="attachnote" maxlength="80" size="60" /></td>
+ </tr>
+
+ <tr>
+ <td></td>
+ <td>
+ <%-- FIXME localisation nok --%>
+ <s:submit name="upload" id="upload" />
+ <div id="progressbar"><div class="ajaxprogress"></div></div>
+ </td>
+ </tr>
+
+ </table>
+ </s:form>
+ </wiki:Permission>
+ <wiki:Permission permission="!upload">
+ <div class="formhelp"><fmt:message key="attach.add.permission" /></div>
+ </wiki:Permission>
+ </div>
+
+ <wiki:HasAttachments>
+
+ <h3><fmt:message key="attach.list" /></h3>
+
+ <%--<small><fmt:message key="attach.listsubtitle"/></small>--%>
+
+ <wiki:Permission permission="delete">
+ <%-- hidden delete form --%>
+ </wiki:Permission>
+
+ <div class="zebra-table">
+ <div class="slimbox-image sortable">
+ <table class="wikitable">
+ <tr>
+ <th><fmt:message key="info.attachment.type" /></th>
+ <th><fmt:message key="info.attachment.name" /></th>
+ <th><fmt:message key="info.size" /></th>
+ <th><fmt:message key="info.version" /></th>
+ <th><fmt:message key="info.date" /></th>
+ <th><fmt:message key="info.author" /></th>
+ <wiki:Permission permission="delete"><th><fmt:message key="info.actions" /></th></wiki:Permission>
+ <th class="changenote"><fmt:message key="info.changenote" /></th>
+ </tr>
+
+ <wiki:AttachmentsIterator id="att">
+ <%
+ String name = att.getFileName();
+ String sname = name;
+ if( sname.length() > MAXATTACHNAMELENGTH ) sname = sname.substring(0,MAXATTACHNAMELENGTH) + "...";
+
+ String mimetype = att.getContentType().replace('/','-');
+
+ java.util.Date modified = new SimpleDateFormat(JCRWikiPage.DATEFORMAT_ISO8601_2000).parse(att.getAttribute(JCRWikiPage.ATTR_CREATED).toString());
+ %>
+ <tr>
+ <%-- The 'title' attribute is used to sort empty cells --%>
+ <td title="<%= att.getContentType() %>"><div class="mime <%= mimetype %>" /></td>
+ <td><wiki:LinkTo title="<%= name %>"><%= sname %></wiki:LinkTo></td>
+ <td style="white-space:nowrap;text-align:right;">
+ <fmt:formatNumber value='<%=Double.toString(att.getSize()/1000.0)%>' maxFractionDigits='1' minFractionDigits='1' /> <fmt:message key="info.kilobytes" />
+ </td>
+ <td style="text-align:center;">
+ <a href="<wiki:PageInfoLink format='url' />" title="<fmt:message key='attach.moreinfo.title' />"><wiki:PageVersion/></a>
+ </td>
+ <td jspwiki:sortvalue="<%= modified.getTime() %>">
+ <fmt:formatDate value="<%= modified %>" pattern="${prefs.TimeFormat}" timeZone="${prefs.TimeZone}" />
+ </td>
+ <td style="white-space:nowrap;" ><wiki:Author/></td>
+ <wiki:Permission permission="delete">
+ <td>
+ <input type="button" value="<fmt:message key='attach.delete' />" src="<wiki:Link format='url' context='<%=WikiContext.DELETE%>' />" onclick="$('deleteForm').setProperty('action',this.src); $('delete-all').click();" />
+ </td>
+ </wiki:Permission>
+ <td class="changenote">
+<%
+ //FIXME: should probably also become a JCRWikiPage attriute.
+ String changeNote = TextUtil.replaceEntities((String)att.getAttribute(WikiPage.CHANGENOTE));
+ if( changeNote != null ) {
+ %><%=changeNote%><%
+ }
+%>
+ </td>
+ </tr>
+ </wiki:AttachmentsIterator>
+
+ </table>
+ </div>
+ </div>
+
+ </wiki:HasAttachments>
+ </wiki:Tab>
+
+ <wiki:Tab id="info" titleKey="info.tab" url="PageInfo.jsp?page=${wikiActionBean.page.name}" accesskey="i" />
+
+</wiki:TabbedSection>
Added: incubator/jspwiki/trunk/src/WebContent/templates/default/DefaultLayout.jsp
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/WebContent/templates/default/DefaultLayout.jsp?rev=917294&view=auto
==============================================================================
--- incubator/jspwiki/trunk/src/WebContent/templates/default/DefaultLayout.jsp (added)
+++ incubator/jspwiki/trunk/src/WebContent/templates/default/DefaultLayout.jsp Sun Feb 28 21:12:40 2010
@@ -0,0 +1,195 @@
+<%--
+ JSPWiki - a JSP-based WikiWiki clone.
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+--%>
+<%@ taglib uri="http://jakarta.apache.org/jspwiki.tld" prefix="wiki" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
+<%@ taglib uri="http://stripes.sourceforge.net/stripes.tld" prefix="s" %>
+<%@ page import="org.apache.wiki.WikiContext" %>
+<%@ page import="org.apache.wiki.action.WikiContextFactory" %>
+<%--
+ This file contains the default layout used by all JSPWiki 3 pages.
+ The default layout contains the HTML doctype declaration, header,
+ and page layout. It can be customized in the following ways:
+
+ 1) Top-level JSPs can define default components, as defined by
+ Stripes <s:layout-component name="foo"> elements. Named components
+ that can be overridden include:
+
+ headTitle : The HTML page title, which will be rendered
+ in the <title> element. Default=wiki: pagename
+ stylesheet : Link tags to external stylesheets. Default=blank
+ inlinecss : Inline stylesheets. Default=blank
+ script : JavaScript <script> elements. Default=blank
+ jslocalizedstrings : Localized scripts for JavaScript
+ functions. Default=blank
+ jsfunction : JavaScript functions. Default=blank
+ headMetaRobots : Search engine options. Default=noindex,nofollow
+ content : The page contents. Default=blank
+
+ 2) DefaultLayout injects additional JSPs that are meant to be
+ customized. These include:
+
+ localheader.jsp : A "local header" that can contain company logos
+ or other markup. Default=blank
+
+--%>
+<s:layout-definition>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>
+ <%--
+
+ Title: by default, use the "view page" title
+ --%>
+ <s:layout-component name="headTitle">
+ <fmt:message key="view.title.view">
+ <fmt:param><wiki:Variable var="ApplicationName" /></fmt:param>
+ <fmt:param><wiki:PageName/></fmt:param>
+ </fmt:message>
+ </s:layout-component>
+ </title>
+ <%--
+
+ CSS stylesheets
+ --%>
+ <link rel="stylesheet" media="screen, projection, print" type="text/css" href="<wiki:Link format='url' templatefile='jspwiki.css' />" />
+ <%-- put this at the top, to avoid double load when not yet cached --%>
+ <%--
+ <link rel="stylesheet" type="text/css" media="print" href="<wiki:Link format='url' templatefile='jspwiki_print.css' />" />
+ <link rel="alternate stylesheet" type="text/css" href="<wiki:Link format='url' templatefile='jspwiki_print.css' />" title="Print friendly" />
+ --%>
+ <link rel="alternate stylesheet" type="text/css" href="<wiki:Link format='url' templatefile='jspwiki.css' />" title="Standard" />
+ <s:layout-component name="stylesheet" />
+ <s:layout-component name="inlinecss" />
+ <%--
+
+ Links to favicon and common pages
+ --%>
+ <link rel="search" href="<wiki:LinkTo format='url' page='FindPage' />" title='Search ${wikiEngine.applicationName}' />
+ <link rel="help" href="<wiki:LinkTo format='url' page='TextFormattingRules' />" title="Help" />
+ <link rel="start" href="<wiki:LinkTo format='url' page='${wikiEngine.frontPage}' />" title="Front page" />
+ <link rel="shortcut icon" type="image/x-icon" href="<wiki:Link format='url' jsp='images/favicon.ico' />" />
+ <%-- ie6 needs next line --%>
+ <link rel="icon" type="image/x-icon" href="<wiki:Link format='url' jsp='favicon.ico' />" />
+ <%--
+
+ Support for the universal edit button
+ (www.universaleditbutton.org)
+ --%>
+ <wiki:CheckRequestContext context='view|info|diff|upload'>
+ <wiki:Permission permission="edit">
+ <wiki:PageType type="page">
+ <link rel="alternate" type="application/x-wiki" href="<wiki:EditLink format='url' />" title="<fmt:message key='actions.edit.title' />" />
+ </wiki:PageType>
+ </wiki:Permission>
+ </wiki:CheckRequestContext>
+ <%--
+
+ JavaScript
+
+ <script src="http://ajax.googleapis.com/ajax/libs/mootools/1.2.3/mootools-yui-compressed.js"></script>
+ --%>
+ <script type="text/javascript" src="<wiki:Link format='url' jsp='scripts/mootools-core.js' />"></script>
+ <script type="text/javascript" src="<wiki:Link format='url' jsp='scripts/mootools-more.js' />"></script>
+
+ <script type="text/javascript" src="<wiki:Link format='url' jsp='scripts/prettify.js' />"></script>
+ <script type="text/javascript" src="<wiki:Link format='url' jsp='scripts/jspwiki-common.js' />"></script>
+ <script type="text/javascript" src="<wiki:Link format='url' jsp='scripts/jspwiki-slimbox.js' />"></script>
+ <script type="text/javascript" src="<wiki:Link format='url' jsp='scripts/jspwiki-commonstyles.js' />"></script>
+ <s:layout-component name="script" />
+ <%--
+
+ JavaScript: localized strings and functions
+ --%>
+ <script type="text/javascript">//<![CDATA[
+ /* Localized javascript strings: LocalizedStrings[] */
+ <%-- DELETEME
+ <s:layout-component name="jslocalizedstrings" />
+ <s:layout-component name="jsfunction" />
+ --%>
+ <wiki:IncludeResources type="jslocalizedstrings"/>
+ <wiki:IncludeResources type="jsfunction"/>
+ //]]></script>
+ <%--
+
+ Skins: extra stylesheets, extra javascript
+
+ --%>
+ <c:if test='${(!empty prefs.Skin) && (prefs.Skin!="PlainVanilla") }'>
+ <link rel="stylesheet" type="text/css" media="screen, projection, print" href="<wiki:Link format='url' templatefile='skins/${prefs.Skin}/skin.css' />" />
+ <script type="text/javascript" src="<wiki:Link format='url' templatefile='skins/${prefs.Skin}/skin.js' />"></script>
+ </c:if>
+ <%--
+
+ Meta tags
+ --%>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <meta name="wikiContext" content='${wikiContext.requestContext}' />
+ <meta name="wikiBaseUrl" content='<wiki:BaseURL/>' />
+ <meta name="wikiPageUrl" content='<wiki:Link format="url" page="#$%"/>' />
+ <meta name="wikiEditUrl" content='<wiki:EditLink format="url" />' />
+ <meta name="wikiJsonUrl" content='<%= WikiContextFactory.findContext(pageContext).getURL( WikiContext.NONE, "JSON-RPC" ) %>' /><%--unusual pagename--%>
+ <meta name="wikiPageName" content='<wiki:Variable var="pagename" />' /><%--pagename without blanks--%>
+ <meta name="wikiUserName" content='<wiki:UserName/>' />
+ <meta name="wikiTemplateUrl" content='<wiki:Link format="url" templatefile="" />' />
+ <meta name="wikiApplicationName" content='${wikiEngine.applicationName}' />
+ <%--
+
+ Search engines: by default, page is not indexed or followed
+ --%>
+ <s:layout-component name="headMetaRobots">
+ <meta name="robots" content="noindex,nofollow" />
+ </s:layout-component>
+ <%--
+
+ RSS Feed discovery
+ --%>
+ <wiki:FeedDiscovery/>
+
+ <wiki:Include page="localheader.jsp" />
+
+
+ </head>
+
+ <body class="${wikiContext.requestContext}">
+
+ <div id="wikibody" class="${prefs.Orientation} ${prefs.Fullscreen} ">
+
+ <wiki:Include page="Header.jsp" />
+
+ <div id="content">
+ <div id="page">
+ <wiki:Include page="PageActionsTop.jsp" />
+ <s:layout-component name="content" />
+ <wiki:Include page="PageActionsBottom.jsp" />
+ </div>
+ <wiki:Include page="Favorites.jsp" />
+ </div>
+
+ <wiki:Include page="Footer.jsp" />
+
+ </div>
+ </body>
+
+</html>
+
+</s:layout-definition>