right-rails 1.2.2 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +7 -0
- data/README.rdoc +1 -1
- data/Rakefile +1 -1
- data/init.rb +1 -0
- data/lib/generators/right_rails/right_rails_generator.rb +15 -6
- data/lib/right_rails.rb +1 -1
- data/lib/right_rails/controller_extensions.rb +28 -15
- data/lib/right_rails/helpers/misc.rb +38 -38
- data/lib/right_rails/helpers/rails.rb +50 -7
- data/lib/rjs_renderer.rb +26 -0
- data/spec/lib/right_rails/controller_extensions_spec.rb +25 -14
- data/spec/lib/right_rails/helpers/forms_spec.rb +6 -6
- data/spec/lib/right_rails/helpers/rails_spec.rb +44 -45
- data/vendor/assets/images/rightjs-ui/rte.png +0 -0
- data/vendor/assets/javascripts/right-safe-src.js +2 -2
- data/vendor/assets/javascripts/right-safe.js +2 -2
- data/vendor/assets/javascripts/right-src.js +386 -100
- data/vendor/assets/javascripts/right.js +2 -2
- data/vendor/assets/javascripts/right/calendar-src.js +19 -3
- data/vendor/assets/javascripts/right/calendar.js +2 -2
- data/vendor/assets/javascripts/right/colorpicker-src.js +59 -20
- data/vendor/assets/javascripts/right/colorpicker.js +2 -2
- data/vendor/assets/javascripts/right/i18n/de.js +43 -42
- data/vendor/assets/javascripts/right/i18n/es.js +1 -0
- data/vendor/assets/javascripts/right/i18n/fi.js +1 -0
- data/vendor/assets/javascripts/right/i18n/fr.js +1 -0
- data/vendor/assets/javascripts/right/i18n/hu.js +1 -0
- data/vendor/assets/javascripts/right/i18n/it.js +1 -0
- data/vendor/assets/javascripts/right/i18n/jp.js +1 -0
- data/vendor/assets/javascripts/right/i18n/lt.js +96 -0
- data/vendor/assets/javascripts/right/i18n/nl.js +1 -0
- data/vendor/assets/javascripts/right/i18n/pt-br.js +1 -0
- data/vendor/assets/javascripts/right/i18n/ru.js +1 -0
- data/vendor/assets/javascripts/right/i18n/ua.js +1 -0
- data/vendor/assets/javascripts/right/jquerysh-src.js +4 -4
- data/vendor/assets/javascripts/right/jquerysh.js +2 -2
- data/vendor/assets/javascripts/right/rails-src.js +51 -15
- data/vendor/assets/javascripts/right/rails.js +2 -2
- data/vendor/assets/javascripts/right/resizable-src.js +11 -11
- data/vendor/assets/javascripts/right/rte-src.js +33 -13
- data/vendor/assets/javascripts/right/rte.js +2 -2
- data/vendor/assets/javascripts/right/slider-src.js +137 -28
- data/vendor/assets/javascripts/right/slider.js +2 -2
- metadata +24 -126
- data/generators/right_rails/right_rails_generator.rb +0 -46
- data/generators/right_rails/templates/iframed.html.erb +0 -10
- data/generators/right_scaffold/right_scaffold_generator.rb +0 -53
- data/generators/right_scaffold/templates/controller.rb +0 -99
- data/generators/right_scaffold/templates/helper.rb +0 -2
- data/generators/right_scaffold/templates/layout.html.erb +0 -18
- data/generators/right_scaffold/templates/style.css +0 -54
- data/generators/right_scaffold/templates/view__form.html.erb +0 -16
- data/generators/right_scaffold/templates/view__item.html.erb +0 -13
- data/generators/right_scaffold/templates/view_edit.html.erb +0 -6
- data/generators/right_scaffold/templates/view_index.html.erb +0 -9
- data/generators/right_scaffold/templates/view_new.html.erb +0 -5
- data/generators/right_scaffold/templates/view_show.html.erb +0 -10
- data/lib/generators/right_rails/templates/iframed.html.erb +0 -10
- data/public/images/rightjs-ui/colorpicker.png +0 -0
- data/public/images/rightjs-ui/resizable.png +0 -0
- data/public/images/rightjs-ui/rte.png +0 -0
- data/public/javascripts/right-olds-src.js +0 -652
- data/public/javascripts/right-olds.js +0 -9
- data/public/javascripts/right-safe-src.js +0 -68
- data/public/javascripts/right-safe.js +0 -7
- data/public/javascripts/right-src.js +0 -6014
- data/public/javascripts/right.js +0 -7
- data/public/javascripts/right/autocompleter-src.js +0 -625
- data/public/javascripts/right/autocompleter.js +0 -7
- data/public/javascripts/right/billboard-src.js +0 -564
- data/public/javascripts/right/billboard.js +0 -7
- data/public/javascripts/right/calendar-src.js +0 -1464
- data/public/javascripts/right/calendar.js +0 -7
- data/public/javascripts/right/casting-src.js +0 -183
- data/public/javascripts/right/casting.js +0 -7
- data/public/javascripts/right/colorpicker-src.js +0 -981
- data/public/javascripts/right/colorpicker.js +0 -7
- data/public/javascripts/right/dialog-src.js +0 -768
- data/public/javascripts/right/dialog.js +0 -7
- data/public/javascripts/right/dnd-src.js +0 -591
- data/public/javascripts/right/dnd.js +0 -7
- data/public/javascripts/right/effects-src.js +0 -508
- data/public/javascripts/right/effects.js +0 -7
- data/public/javascripts/right/i18n/de.js +0 -95
- data/public/javascripts/right/i18n/en-us.js +0 -11
- data/public/javascripts/right/i18n/es.js +0 -95
- data/public/javascripts/right/i18n/fi.js +0 -96
- data/public/javascripts/right/i18n/fr.js +0 -95
- data/public/javascripts/right/i18n/hu.js +0 -100
- data/public/javascripts/right/i18n/it.js +0 -95
- data/public/javascripts/right/i18n/jp.js +0 -99
- data/public/javascripts/right/i18n/nl.js +0 -95
- data/public/javascripts/right/i18n/pt-br.js +0 -95
- data/public/javascripts/right/i18n/ru.js +0 -95
- data/public/javascripts/right/i18n/ua.js +0 -99
- data/public/javascripts/right/in-edit-src.js +0 -373
- data/public/javascripts/right/in-edit.js +0 -7
- data/public/javascripts/right/jquerysh-src.js +0 -362
- data/public/javascripts/right/jquerysh.js +0 -7
- data/public/javascripts/right/json-src.js +0 -147
- data/public/javascripts/right/json.js +0 -7
- data/public/javascripts/right/keys-src.js +0 -87
- data/public/javascripts/right/keys.js +0 -7
- data/public/javascripts/right/lightbox-src.js +0 -931
- data/public/javascripts/right/lightbox.js +0 -7
- data/public/javascripts/right/rails-src.js +0 -402
- data/public/javascripts/right/rails.js +0 -7
- data/public/javascripts/right/rater-src.js +0 -384
- data/public/javascripts/right/rater.js +0 -7
- data/public/javascripts/right/resizable-src.js +0 -465
- data/public/javascripts/right/resizable.js +0 -7
- data/public/javascripts/right/rte-src.js +0 -2685
- data/public/javascripts/right/rte.js +0 -7
- data/public/javascripts/right/selectable-src.js +0 -725
- data/public/javascripts/right/selectable.js +0 -7
- data/public/javascripts/right/sizzle-src.js +0 -1132
- data/public/javascripts/right/sizzle.js +0 -7
- data/public/javascripts/right/slider-src.js +0 -395
- data/public/javascripts/right/slider.js +0 -7
- data/public/javascripts/right/sortable-src.js +0 -430
- data/public/javascripts/right/sortable.js +0 -7
- data/public/javascripts/right/table-src.js +0 -176
- data/public/javascripts/right/table.js +0 -7
- data/public/javascripts/right/tabs-src.js +0 -1157
- data/public/javascripts/right/tabs.js +0 -7
- data/public/javascripts/right/tags-src.js +0 -745
- data/public/javascripts/right/tags.js +0 -7
- data/public/javascripts/right/tooltips-src.js +0 -331
- data/public/javascripts/right/tooltips.js +0 -7
- data/public/javascripts/right/uploader-src.js +0 -302
- data/public/javascripts/right/uploader.js +0 -7
@@ -1,7 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* RightJS-UI Resizable v2.2.3
|
3
|
-
* http://rightjs.org/ui/resizable
|
4
|
-
*
|
5
|
-
* Copyright (C) 2010-2011 Nikolay Nemshilov
|
6
|
-
*/
|
7
|
-
var Resizable=RightJS.Resizable=function(a,b){function c(a,c){c||(c=a,a="DIV");var d=new b.Class(b.Element.Wrappers[a]||b.Element,{initialize:function(c,d){this.key=c;var e=[{"class":"rui-"+c}];this instanceof b.Input||this instanceof b.Form||e.unshift(a),this.$super.apply(this,e),b.isString(d)&&(d=b.$(d)),d instanceof b.Element&&(this._=d._,"$listeners"in d&&(d.$listeners=d.$listeners),d={}),this.setOptions(d,this);return b.Wrapper.Cache[b.$uid(this._)]=this},setOptions:function(a,c){c&&(a=b.Object.merge(a,(new Function("return "+(c.get("data-"+this.key)||"{}")))())),a&&b.Options.setOptions.call(this,b.Object.merge(this.options,a));return this}}),e=new b.Class(d,c);b.Observer.createShortcuts(e.prototype,e.EVENTS||b([]));return e}var d=b,e=b.$,f=b.$w,g=b.$E,h=b.Class,i=b.Element,j=new c({extend:{version:"2.2.3",EVENTS:f("resize start release"),Options:{direction:null,minWidth:null,maxWidth:null,minHeight:null,maxHeight:null}},initialize:function(a,b){this.$super("resizable",this.old_inst=e(a)).setOptions(b),this.options.direction?this.addClass("rui-resizable-"+this.options.direction):this.addClass("rui-resizable"),this.content=this.first(".rui-resizable-content")||g("div",{"class":"rui-resizable-content"}).insert(this.children()).insertTo(this),this.handle=this.first(".rui-resizable-handle")||g("div",{"class":"rui-resizable-handle"}).insertTo(this),this.content.setWidth(this.size().x-parseInt(this.getStyle("borderLeftWidth"),10)-parseInt(this.getStyle("borderRightWidth"),10)),this.options.direction!=="left"&&this.options.direction!=="right"&&this.content.setHeight(this.size().y-parseInt(this.getStyle("borderTopWidth"),10)-parseInt(this.getStyle("borderBottomWidth"),10))},destroy:function(){this.removeClass("rui-resizable").removeClass("rui-resizable-top").removeClass("rui-resizable-left").removeClass("rui-resizable-right").removeClass("rui-resizable-bottom").insert(this.content._.childNodes),this.content.remove(),this.handle.remove(),this.old_inst&&(Wrapper.Cache[$uid(this._)]=this.old_inst);return this},setOptions:function(a,b){a=a||{},f("top left right bottom").each(function(b){this.hasClass("rui-resizable-"+b)&&(a.direction=b)},this);return this.$super(a,b)},start:function(a){this.prevSizes=this.size(),this.prevEvPos=a.position(),this.contXDiff=this.size().x-this.content.size().x,this.contYDiff=this.size().y-this.content.size().y,f("minWidth maxWidth minHeight maxHeight").each(function(a){this[a]=this.findDim(a)},this);return this.fire("start",{original:a})},track:function(a){var b=a.position(),c=this.prevEvPos,d=this.handle.dimensions(),e=this.prevSizes,f=e.x,g=e.y,h=c.x-b.x,i=c.y-b.y,j=this.minWidth,k=this.maxWidth,l=this.minHeight,m=this.maxHeight,n=this.options,o=n.direction;f+=(o==="left"?1:-1)*h,g+=(o==="top"?1:-1)*i,f<j&&(f=j),f>k&&(f=k),g<l&&(g=l),g>m&&(g=m),e.x!==f&&o!=="top"&&o!=="bottom"&&this.setWidth(f),e.y!==g&&o!=="left"&&o!=="right"&&this.setHeight(g);if(f==j||f==k)b.x=d.left+d.width/2;if(g==l||g==m)b.y=d.top+d.height/2;this.prevEvPos=b,this.prevSizes=this.size(),this.fire("resize",{original:a})},setWidth:function(a){this.content.setWidth(a-this.contXDiff);return this.$super(a)},setHeight:function(a){this.content.setHeight(a-this.contYDiff);return this.$super(a)},release:function(a){return this.fire("release",{original:a})},findDim:function(a){var b=this.options[a]||this.getStyle(a);if(b&&/\d+/.test(b)&&parseFloat(b)>0){var c=d(a).include("Width")?"width":"height",e=(this._dummy||(this._dummy=g("div",{style:"visibility:hidden;z-index:-1"}))).setStyle(c,b).insertTo(this,"before"),f=e._["offset"+d(c).capitalize()];e.remove();return f}}});e(a).on({mousedown:function(a){var b=a.find(".rui-resizable-handle");if(b){var c=b.parent();c instanceof j||(c=new j(c)),j.current=c.start(a.stop())}},mousemove:function(a){var b=j.current;b&&b.track(a)},mouseup:function(a){var b=j.current;b&&(b.release(a),j.current=null)}}),e(window).onBlur(function(a){var b=j.current;b&&(b.release(a),j.current=null)}),i.include({makeResizable:function(a){return new j(this,a)},undoResizable:function(){this instanceof j&&this.destroy();return this}}),"Draggable"in b&&b.Draggable.include({dragStart:function(a){a.target.hasClass("rui-resizable-handle")||this.$super(a)}});var k=a.createElement("style"),l=a.createTextNode(".rui-resizable,.rui-resizable-top,.rui-resizable-left,.rui-resizable-right,.rui-resizable-bottom,.rui-resizable-content .rui-resizable-handle{margin:0;padding:0;overflow:none;border:none;background:none;width:auto;height:auto;min-width:none;max-width:none;min-height:none;max-height:none}.rui-resizable,.rui-resizable-top,.rui-resizable-left,.rui-resizable-right,.rui-resizable-bottom{position:relative;min-width:8em;min-height:8em;border:1px solid #DDD}.rui-resizable-content{overflow:auto;padding:.5em;position:relative}.rui-resizable-handle{position:absolute;background-image:url(/images/rightjs-ui/resizable.png);background-repeat:no-repeat;background-color:#DDD;cursor:move}.rui-resizable .rui-resizable-handle{right:0;bottom:0;background-position:-2px -2px;background-color:transparent;width:16px;height:16px}.rui-resizable-top .rui-resizable-handle,.rui-resizable-bottom .rui-resizable-handle{height:8px;width:100%;background-position:center -26px;cursor:row-resize}.rui-resizable-left .rui-resizable-handle,.rui-resizable-right .rui-resizable-handle{top:0px;width:8px;height:100%;background-position:-26px center;cursor:col-resize}.rui-resizable-top .rui-resizable-content{padding-top:1em}.rui-resizable-top .rui-resizable-handle{top:0}.rui-resizable-bottom .rui-resizable-content{padding-bottom:1em}.rui-resizable-bottom .rui-resizable-handle{bottom:0}.rui-resizable-left .rui-resizable-content{padding-left:1em}.rui-resizable-left .rui-resizable-handle{left:0}.rui-resizable-right .rui-resizable-content{padding-right:1em}.rui-resizable-right .rui-resizable-handle{right:0}");k.type="text/css",a.getElementsByTagName("head")[0].appendChild(k),k.styleSheet?k.styleSheet.cssText=l.nodeValue:k.appendChild(l);return j}(document,RightJS)
|
@@ -1,2685 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* RightJS-UI RTE v2.2.0
|
3
|
-
* http://rightjs.org/ui/rte
|
4
|
-
*
|
5
|
-
* Copyright (C) 2010-2011 Nikolay Nemshilov
|
6
|
-
*/
|
7
|
-
var Rte = RightJS.Rte = (function(RightJS, document, window) {
|
8
|
-
/**
|
9
|
-
* This module defines the basic widgets constructor
|
10
|
-
* it creates an abstract proxy with the common functionality
|
11
|
-
* which then we reuse and override in the actual widgets
|
12
|
-
*
|
13
|
-
* Copyright (C) 2010-2011 Nikolay Nemshilov
|
14
|
-
*/
|
15
|
-
|
16
|
-
/**
|
17
|
-
* The widget units constructor
|
18
|
-
*
|
19
|
-
* @param String tag-name or Object methods
|
20
|
-
* @param Object methods
|
21
|
-
* @return Widget wrapper
|
22
|
-
*/
|
23
|
-
function Widget(tag_name, methods) {
|
24
|
-
if (!methods) {
|
25
|
-
methods = tag_name;
|
26
|
-
tag_name = 'DIV';
|
27
|
-
}
|
28
|
-
|
29
|
-
/**
|
30
|
-
* An Abstract Widget Unit
|
31
|
-
*
|
32
|
-
* Copyright (C) 2010 Nikolay Nemshilov
|
33
|
-
*/
|
34
|
-
var AbstractWidget = new RightJS.Class(RightJS.Element.Wrappers[tag_name] || RightJS.Element, {
|
35
|
-
/**
|
36
|
-
* The common constructor
|
37
|
-
*
|
38
|
-
* @param Object options
|
39
|
-
* @param String optional tag name
|
40
|
-
* @return void
|
41
|
-
*/
|
42
|
-
initialize: function(key, options) {
|
43
|
-
this.key = key;
|
44
|
-
var args = [{'class': 'rui-' + key}];
|
45
|
-
|
46
|
-
// those two have different constructors
|
47
|
-
if (!(this instanceof RightJS.Input || this instanceof RightJS.Form)) {
|
48
|
-
args.unshift(tag_name);
|
49
|
-
}
|
50
|
-
this.$super.apply(this, args);
|
51
|
-
|
52
|
-
if (RightJS.isString(options)) {
|
53
|
-
options = RightJS.$(options);
|
54
|
-
}
|
55
|
-
|
56
|
-
// if the options is another element then
|
57
|
-
// try to dynamically rewrap it with our widget
|
58
|
-
if (options instanceof RightJS.Element) {
|
59
|
-
this._ = options._;
|
60
|
-
if ('$listeners' in options) {
|
61
|
-
options.$listeners = options.$listeners;
|
62
|
-
}
|
63
|
-
options = {};
|
64
|
-
}
|
65
|
-
this.setOptions(options, this);
|
66
|
-
|
67
|
-
return (RightJS.Wrapper.Cache[RightJS.$uid(this._)] = this);
|
68
|
-
},
|
69
|
-
|
70
|
-
// protected
|
71
|
-
|
72
|
-
/**
|
73
|
-
* Catches the options
|
74
|
-
*
|
75
|
-
* @param Object user-options
|
76
|
-
* @param Element element with contextual options
|
77
|
-
* @return void
|
78
|
-
*/
|
79
|
-
setOptions: function(options, element) {
|
80
|
-
if (element) {
|
81
|
-
options = RightJS.Object.merge(options, new Function("return "+(
|
82
|
-
element.get('data-'+ this.key) || '{}'
|
83
|
-
))());
|
84
|
-
}
|
85
|
-
|
86
|
-
if (options) {
|
87
|
-
RightJS.Options.setOptions.call(this, RightJS.Object.merge(this.options, options));
|
88
|
-
}
|
89
|
-
|
90
|
-
return this;
|
91
|
-
}
|
92
|
-
});
|
93
|
-
|
94
|
-
/**
|
95
|
-
* Creating the actual widget class
|
96
|
-
*
|
97
|
-
*/
|
98
|
-
var Klass = new RightJS.Class(AbstractWidget, methods);
|
99
|
-
|
100
|
-
// creating the widget related shortcuts
|
101
|
-
RightJS.Observer.createShortcuts(Klass.prototype, Klass.EVENTS || RightJS([]));
|
102
|
-
|
103
|
-
return Klass;
|
104
|
-
}
|
105
|
-
|
106
|
-
|
107
|
-
/**
|
108
|
-
* RTE's initialization script
|
109
|
-
*
|
110
|
-
* Copyright (C) 2010-2011 Nikolay Nemshilov
|
111
|
-
*/
|
112
|
-
|
113
|
-
var R = RightJS,
|
114
|
-
$ = RightJS.$,
|
115
|
-
$$ = RightJS.$$,
|
116
|
-
$w = RightJS.$w,
|
117
|
-
$E = RightJS.$E,
|
118
|
-
$A = RightJS.$A,
|
119
|
-
isArray = RightJS.isArray,
|
120
|
-
RegExp = RightJS.RegExp,
|
121
|
-
Class = RightJS.Class,
|
122
|
-
Element = RightJS.Element,
|
123
|
-
Input = RightJS.Input;
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
/**
|
129
|
-
* The Right Text Editor
|
130
|
-
*
|
131
|
-
* Copyright (C) 2010-2011 Nikolay Nemshilov
|
132
|
-
*/
|
133
|
-
var Rte = new Widget({
|
134
|
-
|
135
|
-
extend: {
|
136
|
-
version: '2.2.0',
|
137
|
-
|
138
|
-
EVENTS: $w('change focus blur'),
|
139
|
-
|
140
|
-
// checking if the 'contentEditable' feature is supported at all
|
141
|
-
supported: 'contentEditable' in document.createElement('div'),
|
142
|
-
|
143
|
-
Options: {
|
144
|
-
toolbar: 'small', // toolbar, the name or an array of your own
|
145
|
-
|
146
|
-
autoresize: true, // automatically resize the editor's height to fit the text
|
147
|
-
|
148
|
-
showToolbar: true, // show the toolbar
|
149
|
-
showStatus: true, // show the status bar
|
150
|
-
|
151
|
-
videoSize: '425x344', // flash-video blocks default size
|
152
|
-
|
153
|
-
cssRule: 'textarea[data-rte]'
|
154
|
-
},
|
155
|
-
|
156
|
-
// predefined toolbars set
|
157
|
-
Toolbars: {
|
158
|
-
small: ['Bold Italic Underline Strike Ttext|Cut Copy Paste|Header Code Quote|Link Image Video|Source'],
|
159
|
-
basic: [
|
160
|
-
'Save Clear|Cut Copy Paste|Bold Italic Underline Strike Ttext|Left Center Right Justify',
|
161
|
-
'Undo Redo|Header Code Quote|Link Image Video|Dotlist Numlist|Indent Outdent|Source'
|
162
|
-
],
|
163
|
-
extra: [
|
164
|
-
'Save Clear|Cut Copy Paste|Bold Italic Underline Strike Ttext|Left Center Right Justify',
|
165
|
-
'Undo Redo|Header Code Quote|Link Image Video|Subscript Superscript|Dotlist Numlist|Indent Outdent',
|
166
|
-
'Format|Fontname Fontsize|Forecolor Backcolor|Source'
|
167
|
-
]
|
168
|
-
},
|
169
|
-
|
170
|
-
Tools: {}, // the index of available tools will be here
|
171
|
-
|
172
|
-
// the keyboard bindings
|
173
|
-
Shortcuts: {
|
174
|
-
Bold: 'b',
|
175
|
-
Italic: 'i',
|
176
|
-
Underline: 'u',
|
177
|
-
// Ttext: 't',
|
178
|
-
Header: 'h',
|
179
|
-
Link: 'l',
|
180
|
-
Cut: 'x',
|
181
|
-
Copy: 'c',
|
182
|
-
Paste: 'v',
|
183
|
-
Undo: 'z',
|
184
|
-
Redo: 'shift+z',
|
185
|
-
Source: 'e',
|
186
|
-
// Quote: 'q',
|
187
|
-
Code: 'p',
|
188
|
-
Save: 's'
|
189
|
-
},
|
190
|
-
|
191
|
-
// tags used by default with formatting tools
|
192
|
-
Tags: {
|
193
|
-
Bold: 'b',
|
194
|
-
Italic: 'i',
|
195
|
-
Underline: 'u',
|
196
|
-
Strike: 's',
|
197
|
-
Ttext: 'tt',
|
198
|
-
Code: 'pre',
|
199
|
-
Quote: 'blockquote',
|
200
|
-
Header: 'h2'
|
201
|
-
},
|
202
|
-
|
203
|
-
// the formatting options, you can use simply tag names
|
204
|
-
// or you can also specify tag + class like 'div.blue'
|
205
|
-
Formats: {
|
206
|
-
'h1': 'Header 1',
|
207
|
-
'h2': 'Header 2',
|
208
|
-
'h3': 'Header 3',
|
209
|
-
'h4': 'Header 4',
|
210
|
-
'p': 'Paragraph',
|
211
|
-
'pre': 'Preformatted',
|
212
|
-
'blockquote': 'Blockquote',
|
213
|
-
'tt': 'Typetext',
|
214
|
-
'address': 'Address'
|
215
|
-
},
|
216
|
-
|
217
|
-
// the font-name options
|
218
|
-
FontNames: {
|
219
|
-
'Andale Mono': 'andale mono,times',
|
220
|
-
'Arial': 'arial,helvetica,sans-serif',
|
221
|
-
'Arial Black': 'arial black,avant garde',
|
222
|
-
'Book Antiqua': 'book antiqua,palatino',
|
223
|
-
'Comic Sans MS': 'comic sans ms,sans-serif',
|
224
|
-
'Courier New': 'courier new,courier',
|
225
|
-
'Georgia': 'georgia,palatino',
|
226
|
-
'Helvetica': 'helvetica',
|
227
|
-
'Impact': 'impact,chicago',
|
228
|
-
'Symbol': 'symbol',
|
229
|
-
'Tahoma': 'tahoma,arial,helvetica,sans-serif',
|
230
|
-
'Terminal': 'terminal,monaco',
|
231
|
-
'Times New Roman': 'times new roman,times',
|
232
|
-
'Trebuchet MS': 'trebuchet ms,geneva',
|
233
|
-
'Verdana': 'verdana,geneva',
|
234
|
-
'Webdings': 'webdings',
|
235
|
-
'Wingdings': 'wingdings,zapf dingbats'
|
236
|
-
},
|
237
|
-
|
238
|
-
// the font-size options
|
239
|
-
FontSizes: '6pt 7pt 8pt 9pt 10pt 11pt 12pt 14pt 18pt 24pt 36pt',
|
240
|
-
|
241
|
-
Videos: [
|
242
|
-
// supported swf video resources
|
243
|
-
[/(http:\/\/.*?youtube\.[a-z]+)\/watch\?v=([^&]+)/, '$1/v/$2'],
|
244
|
-
[/(http:\/\/video.google.com)\/videoplay\?docid=([^&]+)/, '$1/googleplayer.swf?docId=$2'],
|
245
|
-
[/(http:\/\/vimeo\.[a-z]+)\/([0-9]+).*?/, '$1/moogaloop.swf?clip_id=$2']
|
246
|
-
],
|
247
|
-
|
248
|
-
i18n: {
|
249
|
-
Clear: 'Clear',
|
250
|
-
Save: 'Save',
|
251
|
-
Source: 'Source',
|
252
|
-
Bold: 'Bold',
|
253
|
-
Italic: 'Italic',
|
254
|
-
Underline: 'Underline',
|
255
|
-
Strike: 'Strike through',
|
256
|
-
Ttext: 'Typetext',
|
257
|
-
Header: 'Header',
|
258
|
-
Cut: 'Cut',
|
259
|
-
Copy: 'Copy',
|
260
|
-
Paste: 'Paste',
|
261
|
-
Left: 'Left',
|
262
|
-
Center: 'Center',
|
263
|
-
Right: 'Right',
|
264
|
-
Justify: 'Justify',
|
265
|
-
Undo: 'Undo',
|
266
|
-
Redo: 'Redo',
|
267
|
-
Code: 'Code block',
|
268
|
-
Quote: 'Block quote',
|
269
|
-
Link: 'Add link',
|
270
|
-
Image: 'Insert image',
|
271
|
-
Video: 'Insert video',
|
272
|
-
Dotlist: 'List with dots',
|
273
|
-
Numlist: 'List with numbers',
|
274
|
-
Indent: 'Indent',
|
275
|
-
Outdent: 'Outdent',
|
276
|
-
Forecolor: 'Text color',
|
277
|
-
Backcolor: 'Background color',
|
278
|
-
Select: 'Select',
|
279
|
-
Remove: 'Remove',
|
280
|
-
Format: 'Format',
|
281
|
-
Fontname: 'Font name',
|
282
|
-
Fontsize: 'Size',
|
283
|
-
Subscript: 'Subscript',
|
284
|
-
Superscript: 'Superscript',
|
285
|
-
UrlAddress: 'URL Address'
|
286
|
-
},
|
287
|
-
|
288
|
-
current: null
|
289
|
-
},
|
290
|
-
|
291
|
-
/**
|
292
|
-
* Basic constructor
|
293
|
-
*
|
294
|
-
* @param Input textarea reference
|
295
|
-
* @param Object additional options
|
296
|
-
* @return void
|
297
|
-
*/
|
298
|
-
initialize: function(textarea, options) {
|
299
|
-
this
|
300
|
-
.$super('rte', {})
|
301
|
-
.setOptions(options, textarea)
|
302
|
-
.append(
|
303
|
-
this.toolbar = new Rte.Toolbar(this),
|
304
|
-
this.editor = new Rte.Editor(this),
|
305
|
-
this.status = new Rte.Status(this)
|
306
|
-
);
|
307
|
-
|
308
|
-
if (!this.options.showToolbar) {
|
309
|
-
this.toolbar.hide();
|
310
|
-
}
|
311
|
-
|
312
|
-
if (!this.options.showStatus) {
|
313
|
-
this.status.hide();
|
314
|
-
}
|
315
|
-
|
316
|
-
if (textarea) {
|
317
|
-
this.assignTo(textarea);
|
318
|
-
}
|
319
|
-
|
320
|
-
this.undoer = new Rte.Undoer(this);
|
321
|
-
this.selection = new Rte.Selection(this);
|
322
|
-
|
323
|
-
// updating the initial state
|
324
|
-
this.selection.exec('styleWithCss', false);
|
325
|
-
this.status.update();
|
326
|
-
},
|
327
|
-
|
328
|
-
/**
|
329
|
-
* Sets the value
|
330
|
-
*
|
331
|
-
* @param String value
|
332
|
-
* @return Rte this
|
333
|
-
*/
|
334
|
-
setValue: function(value) {
|
335
|
-
if (this.textarea) {
|
336
|
-
this.textarea.value(value);
|
337
|
-
}
|
338
|
-
this.editor.update(value);
|
339
|
-
return this;
|
340
|
-
},
|
341
|
-
|
342
|
-
/**
|
343
|
-
* Returns the current value
|
344
|
-
*
|
345
|
-
* @return String current value
|
346
|
-
*/
|
347
|
-
getValue: function() {
|
348
|
-
return this.editor._.innerHTML;
|
349
|
-
},
|
350
|
-
|
351
|
-
/**
|
352
|
-
* Bidirectional method to set/get the value
|
353
|
-
*
|
354
|
-
* @param String value
|
355
|
-
* @return Rte this or String value
|
356
|
-
*/
|
357
|
-
value: function(value) {
|
358
|
-
return this[value === undefined ? 'getValue' : 'setValue'](value);
|
359
|
-
},
|
360
|
-
|
361
|
-
/**
|
362
|
-
* Disables the editor
|
363
|
-
*
|
364
|
-
* @return Rte this
|
365
|
-
*/
|
366
|
-
disable: function() {
|
367
|
-
this.disabled = true;
|
368
|
-
return this.addClass('rui-rte-disabled');
|
369
|
-
},
|
370
|
-
|
371
|
-
/**
|
372
|
-
* Enables the editor
|
373
|
-
*
|
374
|
-
* @return Rte this
|
375
|
-
*/
|
376
|
-
enable: function() {
|
377
|
-
this.disabled = false;
|
378
|
-
return this.removeClass('rui-rte-disabled');
|
379
|
-
},
|
380
|
-
|
381
|
-
/**
|
382
|
-
* Puts the focus into the editor
|
383
|
-
*
|
384
|
-
* @return Rte this
|
385
|
-
*/
|
386
|
-
focus: function() {
|
387
|
-
if (Rte.current !== this) {
|
388
|
-
Rte.current = this;
|
389
|
-
this.editor.focus();
|
390
|
-
}
|
391
|
-
|
392
|
-
return this;
|
393
|
-
},
|
394
|
-
|
395
|
-
/**
|
396
|
-
* Looses focus from the editor
|
397
|
-
*
|
398
|
-
* @return Rte this
|
399
|
-
*/
|
400
|
-
blur: function() {
|
401
|
-
Rte.current = null;
|
402
|
-
|
403
|
-
this.editor.blur();
|
404
|
-
|
405
|
-
return this;
|
406
|
-
},
|
407
|
-
|
408
|
-
/**
|
409
|
-
* Assigns this Rte to work with this textarea
|
410
|
-
*
|
411
|
-
* @param mixed textarea reference
|
412
|
-
* @return Rte this
|
413
|
-
*/
|
414
|
-
assignTo: function(element) {
|
415
|
-
var textarea = $(element),
|
416
|
-
size = textarea.size();
|
417
|
-
|
418
|
-
// displaying self only if the 'contentEditable' feature is supported
|
419
|
-
// otherwise keeping original textarea where it is
|
420
|
-
if (Rte.supported) {
|
421
|
-
this.insertTo(textarea.setStyle(
|
422
|
-
'position:absolute;left:-9999em;'
|
423
|
-
), 'before');
|
424
|
-
|
425
|
-
this.editor.resize(size);
|
426
|
-
this.setWidth(size.x);
|
427
|
-
|
428
|
-
if (this.options.autoresize) {
|
429
|
-
this.editor.setStyle({
|
430
|
-
minHeight: size.y + 'px',
|
431
|
-
height: 'auto'
|
432
|
-
});
|
433
|
-
}
|
434
|
-
} else {
|
435
|
-
textarea.setStyle('visibility:visible');
|
436
|
-
}
|
437
|
-
|
438
|
-
this.setValue(textarea.value());
|
439
|
-
this.onChange(function() {
|
440
|
-
textarea._.value = this.editor._.innerHTML;
|
441
|
-
});
|
442
|
-
|
443
|
-
this.textarea = textarea;
|
444
|
-
|
445
|
-
return this;
|
446
|
-
}
|
447
|
-
|
448
|
-
});
|
449
|
-
|
450
|
-
/**
|
451
|
-
* Rte's toolbar unit
|
452
|
-
*
|
453
|
-
* Copyright (C) 2010 Nikolay Nemshilov
|
454
|
-
*/
|
455
|
-
Rte.Toolbar = new Class(Element, {
|
456
|
-
|
457
|
-
initialize: function(rte) {
|
458
|
-
this.$super('div', {'class': 'rui-rte-toolbar'});
|
459
|
-
|
460
|
-
this.rte = rte;
|
461
|
-
rte.tools = {};
|
462
|
-
|
463
|
-
var options = rte.options, toolbar = options.toolbar;
|
464
|
-
|
465
|
-
R(Rte.Toolbars[toolbar] || (isArray(toolbar) ? toolbar : [toolbar])).each(function(line_s) {
|
466
|
-
var line = $E('div', {'class': 'line'}).insertTo(this);
|
467
|
-
|
468
|
-
R(line_s.split('|')).each(function(bar_s) {
|
469
|
-
if (!R(bar_s).blank()) {
|
470
|
-
var bar = $E('div', {'class': 'bar'}).insertTo(line);
|
471
|
-
|
472
|
-
R(bar_s.split(' ')).each(function(tool) {
|
473
|
-
tool = R(tool).capitalize();
|
474
|
-
bar.insert(new Rte.Tools[tool](rte));
|
475
|
-
});
|
476
|
-
}
|
477
|
-
});
|
478
|
-
}, this);
|
479
|
-
|
480
|
-
// adding hidden undo/redo tools if they are not on the toolbar
|
481
|
-
// so that the undoer kicked in on the keybindings
|
482
|
-
rte.tools.Undo || new Rte.Tools.Undo(rte);
|
483
|
-
rte.tools.Redo || new Rte.Tools.Redo(rte);
|
484
|
-
},
|
485
|
-
|
486
|
-
/**
|
487
|
-
* Finds a tool for the keyboard event
|
488
|
-
*
|
489
|
-
* @param {Event} event
|
490
|
-
* @return {Rte.Tool} wired tool or false
|
491
|
-
*/
|
492
|
-
shortcut: function(event) {
|
493
|
-
var raw = event._, key, tool;
|
494
|
-
|
495
|
-
for (key in this.rte.tools) {
|
496
|
-
tool = this.rte.tools[key];
|
497
|
-
|
498
|
-
if (tool.shortcut === raw.keyCode && tool.shiftKey === raw.shiftKey) {
|
499
|
-
return tool;
|
500
|
-
}
|
501
|
-
}
|
502
|
-
|
503
|
-
return null;
|
504
|
-
}
|
505
|
-
|
506
|
-
});
|
507
|
-
|
508
|
-
/**
|
509
|
-
* The actual Editor unit for the Rte
|
510
|
-
*
|
511
|
-
* Copyright (C) 2010 Nikolay Nemshilov
|
512
|
-
*/
|
513
|
-
Rte.Editor = new Class(Element, {
|
514
|
-
|
515
|
-
/**
|
516
|
-
* Basic constructor
|
517
|
-
*
|
518
|
-
* @param Rte rte
|
519
|
-
* @return void
|
520
|
-
*/
|
521
|
-
initialize: function(rte) {
|
522
|
-
// IE won't allow us to set 'contenteditable' progarmatically
|
523
|
-
// so we put it as a textual content and then find it manually
|
524
|
-
this.$super(rte
|
525
|
-
.append('<div contenteditable="true" class="rui-rte-editor"></div>')
|
526
|
-
.first('div.rui-rte-editor')._
|
527
|
-
);
|
528
|
-
|
529
|
-
this.rte = rte;
|
530
|
-
|
531
|
-
this.on({
|
532
|
-
focus: this._focus,
|
533
|
-
blur: this._blur,
|
534
|
-
mouseup: this._mouseup,
|
535
|
-
keypress: this._keypress,
|
536
|
-
keydown: this._keydown,
|
537
|
-
keyup: this._keyup
|
538
|
-
});
|
539
|
-
},
|
540
|
-
|
541
|
-
/**
|
542
|
-
* Updates the editor's content
|
543
|
-
*
|
544
|
-
* @param String text
|
545
|
-
* @return Rte.Editor this
|
546
|
-
*/
|
547
|
-
update: function(text) {
|
548
|
-
this.$super(text);
|
549
|
-
return this;
|
550
|
-
},
|
551
|
-
|
552
|
-
/**
|
553
|
-
* puts focus on the editing area
|
554
|
-
*
|
555
|
-
* @return Rte.Editor this
|
556
|
-
*/
|
557
|
-
focus: function() {
|
558
|
-
this._.focus();
|
559
|
-
return this;
|
560
|
-
},
|
561
|
-
|
562
|
-
/**
|
563
|
-
* removes focus out of the editing area
|
564
|
-
*
|
565
|
-
* @return Rte.Editor this
|
566
|
-
*/
|
567
|
-
blur: function() {
|
568
|
-
this._.blur();
|
569
|
-
return this;
|
570
|
-
},
|
571
|
-
|
572
|
-
/**
|
573
|
-
* Removes the element from the editor, placing all its content
|
574
|
-
* in its place
|
575
|
-
*
|
576
|
-
* @param raw dom element
|
577
|
-
* @return void
|
578
|
-
*/
|
579
|
-
removeElement: function(element) {
|
580
|
-
if (element !== null) {
|
581
|
-
var parent = element.parentNode;
|
582
|
-
while (element.firstChild) {
|
583
|
-
parent.insertBefore(element.firstChild, element);
|
584
|
-
}
|
585
|
-
parent.removeChild(element);
|
586
|
-
}
|
587
|
-
},
|
588
|
-
|
589
|
-
// protected
|
590
|
-
|
591
|
-
_focus: function() {
|
592
|
-
this.rte.selection.restore();
|
593
|
-
this.rte.status.update();
|
594
|
-
this.rte.focused = true;
|
595
|
-
},
|
596
|
-
|
597
|
-
_blur: function() {
|
598
|
-
this.rte.focused = false;
|
599
|
-
this.rte.status.update();
|
600
|
-
},
|
601
|
-
|
602
|
-
_mouseup: function() {
|
603
|
-
this._focus();
|
604
|
-
},
|
605
|
-
|
606
|
-
_keypress: function(event) {
|
607
|
-
if (this.__stopped) {
|
608
|
-
event.stop();
|
609
|
-
}
|
610
|
-
},
|
611
|
-
|
612
|
-
_keydown: function(event) {
|
613
|
-
var raw = event._, stopped = false, tool;
|
614
|
-
|
615
|
-
if (raw.metaKey || raw.ctrlKey) {
|
616
|
-
if ((tool = this.rte.toolbar.shortcut(event))) {
|
617
|
-
tool.call(event);
|
618
|
-
}
|
619
|
-
|
620
|
-
stopped = event.stopped;
|
621
|
-
}
|
622
|
-
|
623
|
-
// an internal marker to lock the 'keypress' event later on
|
624
|
-
this.__stopped = stopped;
|
625
|
-
},
|
626
|
-
|
627
|
-
_keyup: function(event) {
|
628
|
-
switch (event.keyCode) {
|
629
|
-
case 37: // arrow
|
630
|
-
case 38: // arrow
|
631
|
-
case 39: // arrow
|
632
|
-
case 40: // arrow
|
633
|
-
this.rte.status.update();
|
634
|
-
break;
|
635
|
-
|
636
|
-
default:
|
637
|
-
// watching the typing pauses to fire 'change' events
|
638
|
-
var rte = this.rte, editor = this._;
|
639
|
-
|
640
|
-
if (this._timer !== false) { window.clearTimeout(this._timer); }
|
641
|
-
|
642
|
-
this._timer = window.setTimeout(function() {
|
643
|
-
if (rte.__old_value !== editor.innerHTML) {
|
644
|
-
rte.__old_value = editor.innerHTML;
|
645
|
-
rte.fire('change');
|
646
|
-
}
|
647
|
-
}, this._delay);
|
648
|
-
}
|
649
|
-
},
|
650
|
-
|
651
|
-
_timer: false,
|
652
|
-
_delay: 400
|
653
|
-
|
654
|
-
});
|
655
|
-
|
656
|
-
/**
|
657
|
-
* The Rte's status bar block
|
658
|
-
*
|
659
|
-
* Copyright (C) 2010-2011 Nikolay Nemshilov
|
660
|
-
*/
|
661
|
-
Rte.Status = new Class(Element, {
|
662
|
-
|
663
|
-
/**
|
664
|
-
* Basic constructor
|
665
|
-
*
|
666
|
-
* @param Rte
|
667
|
-
* @return void
|
668
|
-
*/
|
669
|
-
initialize: function(rte) {
|
670
|
-
this.$super('div', {'class': 'rui-rte-status'});
|
671
|
-
this.rte = rte;
|
672
|
-
this.nodes = [];
|
673
|
-
this.tags = [];
|
674
|
-
|
675
|
-
this.onMousedown(this._mousedown);
|
676
|
-
},
|
677
|
-
|
678
|
-
/**
|
679
|
-
* Updates the current status
|
680
|
-
*
|
681
|
-
* @return Rte.Status this
|
682
|
-
*/
|
683
|
-
update: function() {
|
684
|
-
this._findNodes();
|
685
|
-
this._checkTools();
|
686
|
-
|
687
|
-
return this.$super(this.nodes.map(function(node, index) {
|
688
|
-
var name = node.tagName.toLowerCase();
|
689
|
-
|
690
|
-
if (node.id) {
|
691
|
-
name += "#"+ node.id;
|
692
|
-
}
|
693
|
-
|
694
|
-
if (node.className) {
|
695
|
-
name += "."+ node.className;
|
696
|
-
}
|
697
|
-
|
698
|
-
return '<a href="" data-index="'+ index +
|
699
|
-
'" onclick="return false;" title="'+
|
700
|
-
Rte.i18n.Select +
|
701
|
-
'">'+ name +'</a>';
|
702
|
-
|
703
|
-
}).join(' › '));
|
704
|
-
},
|
705
|
-
|
706
|
-
/**
|
707
|
-
* Finds an element in the current status stack
|
708
|
-
*
|
709
|
-
* @param String tag name
|
710
|
-
* @param Object optional attributes
|
711
|
-
* @return raw element or null if nothing found
|
712
|
-
*/
|
713
|
-
findElement: function(tag, attributes) {
|
714
|
-
if (tag) {
|
715
|
-
for (var i = this.nodes.length - 1, key, match; i > -1; i--) {
|
716
|
-
if (this.nodes[i].tagName === tag) {
|
717
|
-
match = true;
|
718
|
-
|
719
|
-
for (key in attributes) {
|
720
|
-
if (attributes[key] instanceof RegExp) {
|
721
|
-
match &= attributes[key].test(this.nodes[i].getAttribute(key));
|
722
|
-
} else {
|
723
|
-
match &= this.nodes[i].getAttribute(key) == attributes[key];
|
724
|
-
}
|
725
|
-
}
|
726
|
-
|
727
|
-
if (match) {
|
728
|
-
return this.nodes[i];
|
729
|
-
}
|
730
|
-
}
|
731
|
-
}
|
732
|
-
}
|
733
|
-
|
734
|
-
return null;
|
735
|
-
},
|
736
|
-
|
737
|
-
// protected
|
738
|
-
|
739
|
-
// runs the tools check
|
740
|
-
_checkTools: function() {
|
741
|
-
var tools = this.rte.tools, key;
|
742
|
-
for (key in tools) {
|
743
|
-
tools[key].check();
|
744
|
-
}
|
745
|
-
},
|
746
|
-
|
747
|
-
// finds the nodes from the current selection to the bottom
|
748
|
-
_findNodes: function() {
|
749
|
-
var node = this.rte.selection.element(),
|
750
|
-
editor = this.rte.editor._,
|
751
|
-
rte = this.rte._,
|
752
|
-
nodes = [],
|
753
|
-
tags = [];
|
754
|
-
|
755
|
-
this.nodes = [];
|
756
|
-
this.tags = [];
|
757
|
-
|
758
|
-
while (node && node !== rte) {
|
759
|
-
if (node.tagName) { // skipping the textual nodes
|
760
|
-
nodes.unshift(node);
|
761
|
-
tags.unshift(node.tagName);
|
762
|
-
}
|
763
|
-
|
764
|
-
node = node.parentNode;
|
765
|
-
|
766
|
-
if (node === editor) {
|
767
|
-
this.nodes = nodes;
|
768
|
-
this.tags = tags;
|
769
|
-
break;
|
770
|
-
}
|
771
|
-
}
|
772
|
-
},
|
773
|
-
|
774
|
-
// catches the mousedown on the links
|
775
|
-
_mousedown: function(event) {
|
776
|
-
var link = event.target;
|
777
|
-
|
778
|
-
if (link._.tagName === 'A') {
|
779
|
-
event.stop();
|
780
|
-
var index = link.get('data-index').toInt(),
|
781
|
-
node = this.nodes[index];
|
782
|
-
|
783
|
-
this.rte.selection.wrap(node);
|
784
|
-
}
|
785
|
-
}
|
786
|
-
|
787
|
-
});
|
788
|
-
|
789
|
-
/**
|
790
|
-
* Custom undo/redo manager
|
791
|
-
*
|
792
|
-
* The basic trouble is that the native undo manager
|
793
|
-
* dosn't support manual changes in the editable block
|
794
|
-
* plus it lacks an ability to save some things under IE
|
795
|
-
*
|
796
|
-
* So we manage our undo/redo states manually by whatching
|
797
|
-
* the 'change' event in the RTE instance
|
798
|
-
*
|
799
|
-
* Copyright (C) 2010-2011 Nikolay Nemshilov
|
800
|
-
*/
|
801
|
-
Rte.Undoer = new Class({
|
802
|
-
|
803
|
-
/**
|
804
|
-
* Basic constructor
|
805
|
-
*
|
806
|
-
* @param Rte rte
|
807
|
-
* @return void
|
808
|
-
*/
|
809
|
-
initialize: function(rte) {
|
810
|
-
this.rte = rte;
|
811
|
-
|
812
|
-
function save() { this.undoer.save(); }
|
813
|
-
this.rte.on({ focus: save, change: save });
|
814
|
-
|
815
|
-
this.clear();
|
816
|
-
},
|
817
|
-
|
818
|
-
/**
|
819
|
-
* Clears up the undo history
|
820
|
-
*
|
821
|
-
* @return void
|
822
|
-
*/
|
823
|
-
clear: function() {
|
824
|
-
this.stash = [];
|
825
|
-
this.index = -1;
|
826
|
-
},
|
827
|
-
|
828
|
-
/**
|
829
|
-
* Checks if there are undo steps
|
830
|
-
*
|
831
|
-
* @return boolean check result
|
832
|
-
*/
|
833
|
-
hasUndo: function() {
|
834
|
-
return this.stash.length > 0 && this.index > 0;
|
835
|
-
},
|
836
|
-
|
837
|
-
/**
|
838
|
-
* Checks if there are redo steps
|
839
|
-
*
|
840
|
-
* @return boolean check result
|
841
|
-
*/
|
842
|
-
hasRedo: function() {
|
843
|
-
return (this.stash.length - this.index) > 1;
|
844
|
-
},
|
845
|
-
|
846
|
-
/**
|
847
|
-
* Moves the history one step back
|
848
|
-
*
|
849
|
-
* @return void
|
850
|
-
*/
|
851
|
-
undo: function() {
|
852
|
-
if (this.hasUndo()) {
|
853
|
-
this.set(-- this.index);
|
854
|
-
}
|
855
|
-
},
|
856
|
-
|
857
|
-
/**
|
858
|
-
* Moves the histor one step forward
|
859
|
-
*
|
860
|
-
* @return void
|
861
|
-
*/
|
862
|
-
redo: function() {
|
863
|
-
if (this.hasRedo()) {
|
864
|
-
this.set(++ this.index);
|
865
|
-
}
|
866
|
-
},
|
867
|
-
|
868
|
-
/**
|
869
|
-
* Sets the history to the given step
|
870
|
-
*
|
871
|
-
* @param Integer step index
|
872
|
-
*/
|
873
|
-
set: function(index) {
|
874
|
-
if (this.stash[this.index]) {
|
875
|
-
this.rte.editor.update(this.stash[this.index]);
|
876
|
-
this.rte.selection.restore();
|
877
|
-
}
|
878
|
-
},
|
879
|
-
|
880
|
-
/**
|
881
|
-
* Saves the current state of the editor
|
882
|
-
*
|
883
|
-
* @param Event the RTE's 'change' event with the 'tool' reference
|
884
|
-
* @return void
|
885
|
-
*/
|
886
|
-
save: function(event) {
|
887
|
-
var tool = event && event.tool,
|
888
|
-
tools = this.rte.tools,
|
889
|
-
html, html1, html2;
|
890
|
-
|
891
|
-
if (!tool || (tool !== tools.Undo && tool !== tools.Redo)) {
|
892
|
-
this.rte.selection.store();
|
893
|
-
|
894
|
-
html = this.rte.editor._.innerHTML;
|
895
|
-
|
896
|
-
// stripping off the selection markers
|
897
|
-
html1 = html
|
898
|
-
.replace(SELECTION_START_RE, '')
|
899
|
-
.replace(SELECTION_END_RE, '');
|
900
|
-
|
901
|
-
html2 = (this.stash[this.index]||'')
|
902
|
-
.replace(SELECTION_START_RE, '')
|
903
|
-
.replace(SELECTION_END_RE, '');
|
904
|
-
|
905
|
-
if (html1 !== html2) {
|
906
|
-
// cutting loose possible redo steps
|
907
|
-
this.stash.length = this.index + 1;
|
908
|
-
this.stash.push(html);
|
909
|
-
this.index = this.stash.length - 1;
|
910
|
-
|
911
|
-
tools.Undo.check();
|
912
|
-
tools.Redo.check();
|
913
|
-
}
|
914
|
-
|
915
|
-
this.rte.selection.restore();
|
916
|
-
}
|
917
|
-
}
|
918
|
-
|
919
|
-
});
|
920
|
-
|
921
|
-
/**
|
922
|
-
* This class handles the selection ranges
|
923
|
-
*
|
924
|
-
* Copyright (C) 2010-2011 Nikolay Nemshilov
|
925
|
-
*/
|
926
|
-
Rte.Selection = new Class({
|
927
|
-
|
928
|
-
/**
|
929
|
-
* Basic constructor
|
930
|
-
*
|
931
|
-
* @param Rte rte
|
932
|
-
* @return void
|
933
|
-
*/
|
934
|
-
initialize: function(rte) {
|
935
|
-
this.rte = rte;
|
936
|
-
},
|
937
|
-
|
938
|
-
/**
|
939
|
-
* gets/sets the current range object
|
940
|
-
*
|
941
|
-
* @param {Range} to set
|
942
|
-
* @return TextRange range
|
943
|
-
*/
|
944
|
-
range: function(range) {
|
945
|
-
var selection = window.getSelection && window.getSelection();
|
946
|
-
|
947
|
-
if (range) {
|
948
|
-
if (selection) { // w3c
|
949
|
-
selection.removeAllRanges();
|
950
|
-
selection.addRange(range);
|
951
|
-
} else if (range._) { // IE
|
952
|
-
range._.select();
|
953
|
-
}
|
954
|
-
|
955
|
-
} else {
|
956
|
-
try {
|
957
|
-
range = selection.getRangeAt(0); // FF, Opera, IE9
|
958
|
-
} catch (e) {
|
959
|
-
try {
|
960
|
-
range = document.createRange(); // WebKit
|
961
|
-
} catch (ee) {
|
962
|
-
range = new IERangeEmulator(); // Old IE
|
963
|
-
}
|
964
|
-
}
|
965
|
-
|
966
|
-
return range;
|
967
|
-
}
|
968
|
-
},
|
969
|
-
|
970
|
-
/**
|
971
|
-
* Returns the dom-node that's currently in focus
|
972
|
-
*
|
973
|
-
* @return raw dom-element
|
974
|
-
*/
|
975
|
-
element: function() {
|
976
|
-
var range = this.range(), node = range.commonAncestorContainer;
|
977
|
-
|
978
|
-
// if there is a selection, trying those
|
979
|
-
if (!range.collapsed) {
|
980
|
-
if (
|
981
|
-
range.startContainer === node &&
|
982
|
-
range.startOffset - range.endOffset < 2 &&
|
983
|
-
range.startContainer.hasChildNodes()
|
984
|
-
) {
|
985
|
-
node = range.startContainer.childNodes[range.startOffset];
|
986
|
-
}
|
987
|
-
}
|
988
|
-
|
989
|
-
node = node && node.nodeType === 3 ? node.parentNode : node;
|
990
|
-
|
991
|
-
return node || null;
|
992
|
-
},
|
993
|
-
|
994
|
-
/**
|
995
|
-
* Puts current selection over the given raw dom-node
|
996
|
-
*
|
997
|
-
* @param raw dom-node
|
998
|
-
* @return void
|
999
|
-
*/
|
1000
|
-
wrap: function(node) {
|
1001
|
-
var range = this.range();
|
1002
|
-
range.selectNode(node);
|
1003
|
-
this.range(range);
|
1004
|
-
},
|
1005
|
-
|
1006
|
-
/**
|
1007
|
-
* Returns the selection text
|
1008
|
-
*
|
1009
|
-
* @return String selection text
|
1010
|
-
*/
|
1011
|
-
text: function() {
|
1012
|
-
return this.range().toString();
|
1013
|
-
},
|
1014
|
-
|
1015
|
-
/**
|
1016
|
-
* Cheks if the selection is empty
|
1017
|
-
*
|
1018
|
-
* @return boolean check result
|
1019
|
-
*/
|
1020
|
-
empty: function() {
|
1021
|
-
return this.text() === '';
|
1022
|
-
},
|
1023
|
-
|
1024
|
-
/**
|
1025
|
-
* Returns the HTML content of the selection
|
1026
|
-
*
|
1027
|
-
* @return String html content
|
1028
|
-
*/
|
1029
|
-
html: function() {
|
1030
|
-
var range = this.range(), tmp, fragment;
|
1031
|
-
|
1032
|
-
if (range._) {
|
1033
|
-
return range._.htmlText;
|
1034
|
-
} else {
|
1035
|
-
tmp = document.createElement('div');
|
1036
|
-
fragment = range.cloneContents();
|
1037
|
-
|
1038
|
-
while (fragment.firstChild) {
|
1039
|
-
tmp.appendChild(fragment.firstChild);
|
1040
|
-
}
|
1041
|
-
|
1042
|
-
return tmp.innerHTML;
|
1043
|
-
}
|
1044
|
-
},
|
1045
|
-
|
1046
|
-
/**
|
1047
|
-
* executes a command on this editing area
|
1048
|
-
*
|
1049
|
-
* @param String command name
|
1050
|
-
* @param mixed command value
|
1051
|
-
* @return void
|
1052
|
-
*/
|
1053
|
-
exec: function(command, value) {
|
1054
|
-
try {
|
1055
|
-
// it throws errors in some cases in the non-design mode
|
1056
|
-
document.execCommand(command, false, value);
|
1057
|
-
} catch(e) {
|
1058
|
-
// emulating insert html under IE
|
1059
|
-
if (command === 'inserthtml') {
|
1060
|
-
this.range()._.pasteHTML(value);
|
1061
|
-
}
|
1062
|
-
}
|
1063
|
-
},
|
1064
|
-
|
1065
|
-
/**
|
1066
|
-
* Saves the selection by inserting special SPAN elements
|
1067
|
-
* in places where the selection starts and ends so that
|
1068
|
-
* it could be restored later, even if the editor innerHTML
|
1069
|
-
* property was manipulated directly
|
1070
|
-
*
|
1071
|
-
* @return {Rte.Selection} this
|
1072
|
-
*/
|
1073
|
-
store: function() {
|
1074
|
-
var range = this.range();
|
1075
|
-
|
1076
|
-
// reclonning the data so it wasn't lost on changes
|
1077
|
-
range = {
|
1078
|
-
startContainer: range.startContainer,
|
1079
|
-
startOffset: range.startOffset,
|
1080
|
-
endContainer: range.endContainer,
|
1081
|
-
endOffset: range.endOffset,
|
1082
|
-
collapsed: range.collapsed
|
1083
|
-
};
|
1084
|
-
|
1085
|
-
/**
|
1086
|
-
* Places the selection markers into the editor's structure
|
1087
|
-
*
|
1088
|
-
* @param String name 'end' or 'start'
|
1089
|
-
* @return void
|
1090
|
-
*/
|
1091
|
-
function place_marker(name) {
|
1092
|
-
var node = range[name + 'Container'],
|
1093
|
-
offset = range[name + 'Offset'],
|
1094
|
-
marker = document.createElement('span'),
|
1095
|
-
parent = node.parentNode,
|
1096
|
-
text = node.nodeValue,
|
1097
|
-
ending = document.createTextNode((''+text).substr(offset));
|
1098
|
-
|
1099
|
-
marker.setAttribute('rrte-'+name, '1');
|
1100
|
-
|
1101
|
-
function insert_after(content, anchor) {
|
1102
|
-
if (anchor.nextSibling) {
|
1103
|
-
anchor.parentNode.insertBefore(content, anchor.nextSibling);
|
1104
|
-
} else {
|
1105
|
-
anchor.parentNode.appendChild(content);
|
1106
|
-
}
|
1107
|
-
}
|
1108
|
-
|
1109
|
-
if (node.nodeType === 3) { // text-node
|
1110
|
-
if (offset === 0) {
|
1111
|
-
parent.insertBefore(marker,
|
1112
|
-
// in case both of the markers are at the beginning of
|
1113
|
-
// the same node, the 'end' marker will be already there
|
1114
|
-
// and we will need to insert the 'start' one before it.
|
1115
|
-
name === 'start' && range.collapsed ? node.previousSibling : node
|
1116
|
-
);
|
1117
|
-
} else if (offset === text.length) {
|
1118
|
-
insert_after(marker, node);
|
1119
|
-
} else { // splitting the text node in two
|
1120
|
-
node.nodeValue = text.substr(0, offset);
|
1121
|
-
insert_after(ending, node);
|
1122
|
-
parent.insertBefore(marker, ending);
|
1123
|
-
}
|
1124
|
-
|
1125
|
-
} else if (node.nodeType === 1) { // elements
|
1126
|
-
if (offset === 0) {
|
1127
|
-
if (node.firstChild) {
|
1128
|
-
node.insertBefore(marker, node.firstChild);
|
1129
|
-
} else if (node.hasChildNodes()) {
|
1130
|
-
node.appendChild(marker);
|
1131
|
-
}
|
1132
|
-
} else if (offset === node.childNodes.length) {
|
1133
|
-
node.appendChild(marker);
|
1134
|
-
} else {
|
1135
|
-
node.insertBefore(marker, node.childNodes[offset]);
|
1136
|
-
}
|
1137
|
-
}
|
1138
|
-
}
|
1139
|
-
|
1140
|
-
// NOTE: the 'end' should be before the 'start' in case both of them
|
1141
|
-
// are in the same node, so that the offest didn't shift after
|
1142
|
-
// we insert the marker nodes
|
1143
|
-
place_marker('end');
|
1144
|
-
place_marker('start');
|
1145
|
-
},
|
1146
|
-
|
1147
|
-
/**
|
1148
|
-
* Restores the selection by previously placed
|
1149
|
-
* special SPAN elements and removes them afterwards
|
1150
|
-
*
|
1151
|
-
* @return {Rte.Selection} this
|
1152
|
-
*/
|
1153
|
-
restore: function() {
|
1154
|
-
var elements = $A(this.rte.editor._.getElementsByTagName('span')),
|
1155
|
-
i=0, method, parent, offset, range = this.range();
|
1156
|
-
|
1157
|
-
for (; i < elements.length; i++) {
|
1158
|
-
method = elements[i].getAttribute('rrte-start') ? 'setStart' :
|
1159
|
-
elements[i].getAttribute('rrte-end') ? 'setEnd' : false;
|
1160
|
-
|
1161
|
-
if (method) {
|
1162
|
-
parent = elements[i].parentNode;
|
1163
|
-
|
1164
|
-
if (range._) {
|
1165
|
-
range[method](elements[i]);
|
1166
|
-
} else {
|
1167
|
-
offset = IER_getIndex(elements[i]);
|
1168
|
-
range[method](parent, offset);
|
1169
|
-
}
|
1170
|
-
|
1171
|
-
parent.removeChild(elements[i]);
|
1172
|
-
}
|
1173
|
-
}
|
1174
|
-
|
1175
|
-
this.range(range);
|
1176
|
-
}
|
1177
|
-
});
|
1178
|
-
|
1179
|
-
var
|
1180
|
-
|
1181
|
-
SELECTION_START_MARKER = '<span rrte-start="1"></span>',
|
1182
|
-
SELECTION_END_MARKER = '<span rrte-end="1"></span>',
|
1183
|
-
SELECTION_START_RE = new RegExp(RegExp.escape(SELECTION_START_MARKER), 'i'),
|
1184
|
-
SELECTION_END_RE = new RegExp(RegExp.escape(SELECTION_END_MARKER), 'i');
|
1185
|
-
|
1186
|
-
|
1187
|
-
/**
|
1188
|
-
* W3C ranges API emulator for the old IE browsers
|
1189
|
-
*
|
1190
|
-
* Based on the `InternetExplorerRange` implementation
|
1191
|
-
* from the http://mozile.mozdev.org project
|
1192
|
-
* by James A. Overton <james@overton.ca>
|
1193
|
-
*
|
1194
|
-
* Originally licensed under MPL/GPL2/LGPL2 licenses
|
1195
|
-
*
|
1196
|
-
* Copyrgiht (C) 2011 Nikolay Nemshilov
|
1197
|
-
*/
|
1198
|
-
var IERangeEmulator = new Class({
|
1199
|
-
|
1200
|
-
// standard w3c attributes
|
1201
|
-
collapsed: null,
|
1202
|
-
startContainer: null,
|
1203
|
-
startOffset: null,
|
1204
|
-
endContainer: null,
|
1205
|
-
endOffset: null,
|
1206
|
-
commonAncestorContainer: null,
|
1207
|
-
|
1208
|
-
/**
|
1209
|
-
* Basic constructor
|
1210
|
-
*
|
1211
|
-
* @return void
|
1212
|
-
*/
|
1213
|
-
initialize: function() {
|
1214
|
-
this._ = document.selection.createRange();
|
1215
|
-
|
1216
|
-
if (document.selection.type === 'Control') {
|
1217
|
-
this.startContainer = this.endContainer = this.commonAncestorContainer = this._(0);
|
1218
|
-
this.startOffset = this.endOffset = 0;
|
1219
|
-
} else {
|
1220
|
-
//startPoint
|
1221
|
-
var range = this._.duplicate();
|
1222
|
-
range.collapse(true);
|
1223
|
-
range = IER_getPosition(range);
|
1224
|
-
|
1225
|
-
this.startContainer = range.node;
|
1226
|
-
this.startOffset = range.offset;
|
1227
|
-
|
1228
|
-
//endPoint
|
1229
|
-
range = this._.duplicate();
|
1230
|
-
range.collapse(false);
|
1231
|
-
range = IER_getPosition(range);
|
1232
|
-
|
1233
|
-
this.endContainer = range.node;
|
1234
|
-
this.endOffset = range.offset;
|
1235
|
-
|
1236
|
-
// the rest of the properties
|
1237
|
-
IER_commonAncestorContainer(this);
|
1238
|
-
}
|
1239
|
-
|
1240
|
-
IER_collapsed(this);
|
1241
|
-
},
|
1242
|
-
|
1243
|
-
/**
|
1244
|
-
* Sets the starting point for the range
|
1245
|
-
*
|
1246
|
-
* @param {Node} node
|
1247
|
-
* @param {Number} offset
|
1248
|
-
* @return void
|
1249
|
-
*/
|
1250
|
-
setStart: function(node, offset) {
|
1251
|
-
var range = this._.duplicate();
|
1252
|
-
|
1253
|
-
range.moveToElementText(node);
|
1254
|
-
range.collapse(true);
|
1255
|
-
|
1256
|
-
this._.setEndPoint('StartToStart', range);
|
1257
|
-
|
1258
|
-
this.startContainer = node;
|
1259
|
-
this.startOffset = offset;
|
1260
|
-
|
1261
|
-
if (this.endContainer === null && this.endOffset === null) {
|
1262
|
-
this.endContainer = node;
|
1263
|
-
this.endOffset = offset;
|
1264
|
-
}
|
1265
|
-
|
1266
|
-
IER_commonAncestorContainer(this);
|
1267
|
-
IER_collapsed(this);
|
1268
|
-
},
|
1269
|
-
|
1270
|
-
/**
|
1271
|
-
* Setting the end point for the range
|
1272
|
-
*
|
1273
|
-
* @param {Node} node
|
1274
|
-
* @param {Number} offset
|
1275
|
-
* @return void
|
1276
|
-
*/
|
1277
|
-
setEnd: function (node, offset) {
|
1278
|
-
var range = this._.duplicate();
|
1279
|
-
|
1280
|
-
range.moveToElementText(node);
|
1281
|
-
range.collapse(true);
|
1282
|
-
|
1283
|
-
this._.setEndPoint('EndToEnd', range);
|
1284
|
-
|
1285
|
-
this.endContainer = node;
|
1286
|
-
this.endOffset = offset;
|
1287
|
-
|
1288
|
-
if (this.startContainer === null && this.startOffset === null) {
|
1289
|
-
this.startContainer = node;
|
1290
|
-
this.startOffset = offset;
|
1291
|
-
}
|
1292
|
-
|
1293
|
-
IER_commonAncestorContainer(this);
|
1294
|
-
IER_collapsed(this);
|
1295
|
-
},
|
1296
|
-
|
1297
|
-
/**
|
1298
|
-
* Wrapps the range around the given node
|
1299
|
-
*
|
1300
|
-
* @param {Node} node
|
1301
|
-
* @return void
|
1302
|
-
*/
|
1303
|
-
selectNode: function (node) {
|
1304
|
-
this._.moveToElementText(node);
|
1305
|
-
},
|
1306
|
-
|
1307
|
-
/**
|
1308
|
-
* Selection text emulation
|
1309
|
-
*
|
1310
|
-
* @return {String} text
|
1311
|
-
*/
|
1312
|
-
toString: function() {
|
1313
|
-
return ''+ this._.text;
|
1314
|
-
}
|
1315
|
-
});
|
1316
|
-
|
1317
|
-
|
1318
|
-
//////////////////////////////////////////////////////////////////////////////
|
1319
|
-
// Some private methods for the IERangeEmaulator
|
1320
|
-
//////////////////////////////////////////////////////////////////////////////
|
1321
|
-
|
1322
|
-
|
1323
|
-
/**
|
1324
|
-
* Finds the standard node/offset pair out of the
|
1325
|
-
* IE range object
|
1326
|
-
*
|
1327
|
-
* @param {TextRange} ie text range object
|
1328
|
-
* @return {Object} 'node' and 'offset' pairs
|
1329
|
-
*/
|
1330
|
-
function IER_getPosition(original_range) {
|
1331
|
-
var element = original_range.parentElement(),
|
1332
|
-
range, range_size, direction, node, node_size;
|
1333
|
-
|
1334
|
-
range = document.body.createTextRange();
|
1335
|
-
range.moveToElementText(element);
|
1336
|
-
range.setEndPoint("EndToStart", original_range);
|
1337
|
-
|
1338
|
-
range_size = range.text.length;
|
1339
|
-
|
1340
|
-
// Choose Direction
|
1341
|
-
if (range_size < element.innerText.length / 2) {
|
1342
|
-
direction = 1;
|
1343
|
-
node = element.firstChild;
|
1344
|
-
} else {
|
1345
|
-
direction = -1;
|
1346
|
-
node = element.lastChild;
|
1347
|
-
range.moveToElementText(element);
|
1348
|
-
range.setEndPoint("StartToStart", original_range);
|
1349
|
-
range_size = range.text.length;
|
1350
|
-
}
|
1351
|
-
|
1352
|
-
// Loop through child nodes
|
1353
|
-
while (node) {
|
1354
|
-
switch (node.nodeType) {
|
1355
|
-
case 3: // text-node
|
1356
|
-
node_size = node.data.length;
|
1357
|
-
if(node_size < range_size) {
|
1358
|
-
range_size -= node_size;
|
1359
|
-
|
1360
|
-
if (direction === 1) {
|
1361
|
-
range.moveStart("character", range_size);
|
1362
|
-
} else {
|
1363
|
-
range.moveEnd("character", -range_size);
|
1364
|
-
}
|
1365
|
-
|
1366
|
-
} else {
|
1367
|
-
return direction === 1 ?
|
1368
|
-
{node: node, offset: range_size} :
|
1369
|
-
{node: node, offset: node_size - range_size};
|
1370
|
-
}
|
1371
|
-
break;
|
1372
|
-
|
1373
|
-
case 1: // element-node
|
1374
|
-
node_size = node.innerText.length;
|
1375
|
-
|
1376
|
-
if (direction === 1) {
|
1377
|
-
range.moveStart("character", node_size);
|
1378
|
-
} else {
|
1379
|
-
range.moveEnd("character", -node_size);
|
1380
|
-
}
|
1381
|
-
|
1382
|
-
range_size = range_size - node_size;
|
1383
|
-
break;
|
1384
|
-
}
|
1385
|
-
|
1386
|
-
node = direction === 1 ? node.nextSibling : node.previousSibling;
|
1387
|
-
}
|
1388
|
-
|
1389
|
-
// The TextRange was not found. Return a reasonable value instead.
|
1390
|
-
return {node: element, offset: 0};
|
1391
|
-
}
|
1392
|
-
|
1393
|
-
/**
|
1394
|
-
* Assigns a suitable `commonAncestorContainer` property for the range
|
1395
|
-
*
|
1396
|
-
* @param {IERangeEmulator} range
|
1397
|
-
* @return void
|
1398
|
-
*/
|
1399
|
-
function IER_commonAncestorContainer(range) {
|
1400
|
-
range.commonAncestorContainer = range._.parentElement();
|
1401
|
-
}
|
1402
|
-
|
1403
|
-
/**
|
1404
|
-
* Sets the `collapsed` property for the range
|
1405
|
-
*
|
1406
|
-
* @param {IERangeEmulator} range
|
1407
|
-
* return void
|
1408
|
-
*/
|
1409
|
-
function IER_collapsed(range) {
|
1410
|
-
range.collapsed =
|
1411
|
-
range.startContainer === range.endContainer &&
|
1412
|
-
range.startOffset === range.endOffset;
|
1413
|
-
}
|
1414
|
-
|
1415
|
-
/**
|
1416
|
-
* Finds out the node's index among it's siblings
|
1417
|
-
*
|
1418
|
-
* @param {Node} node
|
1419
|
-
* @return {Number} index
|
1420
|
-
*/
|
1421
|
-
function IER_getIndex(node) {
|
1422
|
-
var index = 0;
|
1423
|
-
|
1424
|
-
while ((node = node.previousSibling)) {
|
1425
|
-
index ++;
|
1426
|
-
}
|
1427
|
-
|
1428
|
-
return index;
|
1429
|
-
}
|
1430
|
-
|
1431
|
-
|
1432
|
-
/**
|
1433
|
-
* The basic tools class
|
1434
|
-
*
|
1435
|
-
* Copyright (C) 2010-2011 Nikolay Nemshilov
|
1436
|
-
*/
|
1437
|
-
Rte.Tool = new Class(Element, {
|
1438
|
-
|
1439
|
-
block: true, // should the 'keypress' event be blocked
|
1440
|
-
blip: false, // whether it should be highlighted when used
|
1441
|
-
changes: true, // if this tool should fire 'change' on the rte
|
1442
|
-
|
1443
|
-
shortuct: null, // the shortuct key-code
|
1444
|
-
shiftKey: false, // if it should trigger with a shift-key only
|
1445
|
-
|
1446
|
-
/**
|
1447
|
-
* Basic constructor
|
1448
|
-
*
|
1449
|
-
* @param Rte rte reference
|
1450
|
-
* @return Rte.Tool this
|
1451
|
-
*/
|
1452
|
-
initialize: function(rte) {
|
1453
|
-
var name;
|
1454
|
-
|
1455
|
-
// searching for the tool-name
|
1456
|
-
for (name in Rte.Tools) {
|
1457
|
-
if (Rte.Tools[name] === this.constructor) { break; }
|
1458
|
-
}
|
1459
|
-
|
1460
|
-
this.name = name;
|
1461
|
-
this.shortcut = this.shortcut || Rte.Shortcuts[name];
|
1462
|
-
|
1463
|
-
this.$super('div', {
|
1464
|
-
'html': '<div class="icon"></div>', // <- icon container
|
1465
|
-
'class': 'tool '+ name.toLowerCase(),
|
1466
|
-
'title': (Rte.i18n[name] || name) + (
|
1467
|
-
this.shortcut ? " ("+ this.shortcut + ")" : ""
|
1468
|
-
)
|
1469
|
-
});
|
1470
|
-
|
1471
|
-
// registering the tool
|
1472
|
-
this.rte = rte;
|
1473
|
-
rte.tools[name] = this;
|
1474
|
-
|
1475
|
-
// hooking up the shortcuts
|
1476
|
-
this.shortcut = this.shortcut && this.shortcut.toLowerCase();
|
1477
|
-
this.shiftKey = this.shortcut && this.shortcut.indexOf('shift') > -1;
|
1478
|
-
this.shortcut = this.shortcut && this.shortcut.toUpperCase().charCodeAt(this.shortcut.length - 1);
|
1479
|
-
|
1480
|
-
// connecting the mousedown the way that the editor din't loose the focus
|
1481
|
-
this.onMousedown(function(e) {
|
1482
|
-
e.stop(); this.mousedown();
|
1483
|
-
});
|
1484
|
-
|
1485
|
-
// allowing some nice chains in the subclass
|
1486
|
-
return this;
|
1487
|
-
},
|
1488
|
-
|
1489
|
-
// those three methods should be implemented in subclasses
|
1490
|
-
exec: function() { }, /// the actual process
|
1491
|
-
active: function() { return false; }, // all tools not active by default
|
1492
|
-
enabled: function() { return true; }, // all tools enabled by default
|
1493
|
-
|
1494
|
-
/**
|
1495
|
-
* The entry point for all the tools, if you need to call a tool,
|
1496
|
-
* call this method. __DON'T CALL__ the #exec method directly!
|
1497
|
-
*
|
1498
|
-
* @param {Event} 'keydown' event
|
1499
|
-
* @return void
|
1500
|
-
*/
|
1501
|
-
call: function(event) {
|
1502
|
-
if (!this.disabled) {
|
1503
|
-
if (event && this.block) { event.stop(); }
|
1504
|
-
|
1505
|
-
this.exec();
|
1506
|
-
this.rte.status.update();
|
1507
|
-
this.rte.fire('change', {tool: this});
|
1508
|
-
|
1509
|
-
if (this.blip) { this.highlight(); }
|
1510
|
-
}
|
1511
|
-
},
|
1512
|
-
|
1513
|
-
/**
|
1514
|
-
* Checks the command's status
|
1515
|
-
*
|
1516
|
-
* @return void
|
1517
|
-
*/
|
1518
|
-
check: function() {
|
1519
|
-
this._.className = this._.className.replace(' disabled', '');
|
1520
|
-
this.disabled = false;
|
1521
|
-
|
1522
|
-
if ((this.name === 'Source' || this.rte.srcMode !== true) && this.enabled()) {
|
1523
|
-
this._.className = this._.className.replace(' active', '');
|
1524
|
-
if (this.active()) {
|
1525
|
-
this._.className += ' active';
|
1526
|
-
}
|
1527
|
-
|
1528
|
-
} else {
|
1529
|
-
this._.className += ' disabled';
|
1530
|
-
this.disabled = true;
|
1531
|
-
}
|
1532
|
-
},
|
1533
|
-
|
1534
|
-
/**
|
1535
|
-
* Replacing the highlight method with some css stuff instead of an Fx
|
1536
|
-
*
|
1537
|
-
* @return Rte.Tool this
|
1538
|
-
*/
|
1539
|
-
highlight: function() {
|
1540
|
-
R(this.addClass('highlight').removeClass).bind(this, 'highlight').delay(100);
|
1541
|
-
},
|
1542
|
-
|
1543
|
-
// protected
|
1544
|
-
|
1545
|
-
// mousedown event receiver (might be replaced in subclasses)
|
1546
|
-
mousedown: function() {
|
1547
|
-
this.call();
|
1548
|
-
}
|
1549
|
-
|
1550
|
-
});
|
1551
|
-
|
1552
|
-
/**
|
1553
|
-
* Native command related abstract tool
|
1554
|
-
*
|
1555
|
-
* Copyright (C) 2010-2011 Nikolay Nemshilov
|
1556
|
-
*/
|
1557
|
-
Rte.Tool.Command = new Class(Rte.Tool, {
|
1558
|
-
command: null, // execCommand name
|
1559
|
-
value: null, // execCommand value
|
1560
|
-
|
1561
|
-
/**
|
1562
|
-
* calling the command exec
|
1563
|
-
*
|
1564
|
-
* @return void
|
1565
|
-
*/
|
1566
|
-
exec: function() {
|
1567
|
-
this.rte.selection.exec(this.command, this.value);
|
1568
|
-
},
|
1569
|
-
|
1570
|
-
/**
|
1571
|
-
* Checks if the command is enabled at all
|
1572
|
-
*
|
1573
|
-
* @return boolean check result
|
1574
|
-
*/
|
1575
|
-
enabled: function() {
|
1576
|
-
try {
|
1577
|
-
return document.queryCommandEnabled(this.command);
|
1578
|
-
} catch(e) {
|
1579
|
-
return false;
|
1580
|
-
}
|
1581
|
-
},
|
1582
|
-
|
1583
|
-
/**
|
1584
|
-
* Queries if the command is in active state
|
1585
|
-
*
|
1586
|
-
* @return boolean check result
|
1587
|
-
*/
|
1588
|
-
active: function() {
|
1589
|
-
try { // copy/paste commands cause errors under FF by default
|
1590
|
-
return this.value === null ?
|
1591
|
-
document.queryCommandState(this.command) :
|
1592
|
-
document.queryCommandValue(this.command) == this.value;
|
1593
|
-
} catch(e) {
|
1594
|
-
return false;
|
1595
|
-
}
|
1596
|
-
}
|
1597
|
-
});
|
1598
|
-
|
1599
|
-
/**
|
1600
|
-
* Text formatting specific abstract tool
|
1601
|
-
*
|
1602
|
-
* Copyright (C) 2010-2011 Nikolay Nemshilov
|
1603
|
-
*/
|
1604
|
-
Rte.Tool.Format = new Class(Rte.Tool, {
|
1605
|
-
tag: null, // element's tag name
|
1606
|
-
atts: {}, // element's attributes
|
1607
|
-
|
1608
|
-
/**
|
1609
|
-
* Formatting tools basic constructor
|
1610
|
-
*
|
1611
|
-
* @param Rte rte
|
1612
|
-
* @return Rte.ToolFormat this
|
1613
|
-
*/
|
1614
|
-
initialize: function(rte) {
|
1615
|
-
this.$super(rte);
|
1616
|
-
this.tag = (this.tag || Rte.Tags[this.name] || '').toUpperCase();
|
1617
|
-
return this;
|
1618
|
-
},
|
1619
|
-
|
1620
|
-
/**
|
1621
|
-
* triggering the formatting
|
1622
|
-
*
|
1623
|
-
* @return void
|
1624
|
-
*/
|
1625
|
-
exec: function() {
|
1626
|
-
this[this.active() ? 'unformat' : 'format']();
|
1627
|
-
},
|
1628
|
-
|
1629
|
-
/**
|
1630
|
-
* Overloading the activity checks
|
1631
|
-
*
|
1632
|
-
* @return boolean check result
|
1633
|
-
*/
|
1634
|
-
active: function() {
|
1635
|
-
return this.element() !== null;
|
1636
|
-
},
|
1637
|
-
|
1638
|
-
// protected
|
1639
|
-
|
1640
|
-
/**
|
1641
|
-
* Tries to find a currently active element
|
1642
|
-
*
|
1643
|
-
* @return raw dom element or null
|
1644
|
-
*/
|
1645
|
-
element: function() {
|
1646
|
-
return this.rte.status.findElement(this.tag, this.attrs);
|
1647
|
-
},
|
1648
|
-
|
1649
|
-
/**
|
1650
|
-
* Removes the formatting
|
1651
|
-
*
|
1652
|
-
* @return void
|
1653
|
-
*/
|
1654
|
-
unformat: function() {
|
1655
|
-
this._format(false);
|
1656
|
-
},
|
1657
|
-
|
1658
|
-
/**
|
1659
|
-
* Formats the block according to the settings
|
1660
|
-
*
|
1661
|
-
* @return void
|
1662
|
-
*/
|
1663
|
-
format: function() {
|
1664
|
-
this._format(true);
|
1665
|
-
},
|
1666
|
-
|
1667
|
-
// private
|
1668
|
-
|
1669
|
-
/**
|
1670
|
-
* The actual formatting/unformatting process mumbo-jumbo
|
1671
|
-
*
|
1672
|
-
* @param boolean formatting direction true/false
|
1673
|
-
* @return void
|
1674
|
-
*/
|
1675
|
-
_format: function(formatting) {
|
1676
|
-
var open_tag = '<'+ this.tag,
|
1677
|
-
close_tag = '</'+ this.tag + '>',
|
1678
|
-
editor = this.rte.editor,
|
1679
|
-
selection = this.rte.selection,
|
1680
|
-
range = selection.range(),
|
1681
|
-
selected = selection.text(),
|
1682
|
-
element = this.element(),
|
1683
|
-
content = element && (element.textContent || element.innerText);
|
1684
|
-
|
1685
|
-
// building the open-tag attributes
|
1686
|
-
for (var attr in this.attrs) {
|
1687
|
-
open_tag += ' '+ attr +'="'+ this.attrs[attr]+ '"';
|
1688
|
-
}
|
1689
|
-
open_tag += ">";
|
1690
|
-
|
1691
|
-
selection.store();
|
1692
|
-
|
1693
|
-
// Old IEs screw with the starting position
|
1694
|
-
// placing it before the open tag, so here we switch it back
|
1695
|
-
if (!formatting && range._) {
|
1696
|
-
editor.html(editor.html().replace(
|
1697
|
-
new RegExp(RegExp.escape(SELECTION_START_MARKER + open_tag), 'i'),
|
1698
|
-
open_tag + SELECTION_START_MARKER
|
1699
|
-
));
|
1700
|
-
}
|
1701
|
-
|
1702
|
-
|
1703
|
-
if (formatting) {
|
1704
|
-
editor.html(editor.html()
|
1705
|
-
.replace(SELECTION_START_RE, open_tag + SELECTION_START_MARKER)
|
1706
|
-
.replace(SELECTION_END_RE, SELECTION_END_MARKER + close_tag)
|
1707
|
-
);
|
1708
|
-
} else if (element && selected === content) {
|
1709
|
-
// plainly remove the element if it was fully selected
|
1710
|
-
// in case there are several nested elements so that
|
1711
|
-
// we didn't get screwed with the regexps manipulations
|
1712
|
-
editor.removeElement(element);
|
1713
|
-
} else {
|
1714
|
-
editor.html(editor.html()
|
1715
|
-
.replace(SELECTION_START_RE, close_tag + SELECTION_START_MARKER)
|
1716
|
-
.replace(SELECTION_END_RE, SELECTION_END_MARKER + open_tag)
|
1717
|
-
|
1718
|
-
// cleaning up empty tags that might left
|
1719
|
-
.replace(/<([a-z]+)[^>]*?>\s*?<\/\1>/ig, '')
|
1720
|
-
);
|
1721
|
-
}
|
1722
|
-
|
1723
|
-
selection.restore();
|
1724
|
-
}
|
1725
|
-
|
1726
|
-
});
|
1727
|
-
|
1728
|
-
/**
|
1729
|
-
* A _shared module_ to provide the `options` list functionality
|
1730
|
-
* for the tools
|
1731
|
-
*
|
1732
|
-
* Copyright (C) 2010 Nikolay Nemshilov
|
1733
|
-
*/
|
1734
|
-
Rte.Tool.Options = {
|
1735
|
-
|
1736
|
-
/**
|
1737
|
-
* Builds the options list
|
1738
|
-
*
|
1739
|
-
* @param Object key -> value hash
|
1740
|
-
*/
|
1741
|
-
build: function(options) {
|
1742
|
-
this.trigger = $E('div', {'class': 'trigger', 'html': '·'});
|
1743
|
-
this.display = $E('div', {'class': 'display'});
|
1744
|
-
this.options = $E('ul', {'class': 'options'});
|
1745
|
-
|
1746
|
-
this
|
1747
|
-
.addClass('with-options')
|
1748
|
-
.append(this.display, this.options)
|
1749
|
-
.insert(this.trigger, 'top');
|
1750
|
-
|
1751
|
-
this.items = {};
|
1752
|
-
|
1753
|
-
for (var value in options) {
|
1754
|
-
this.items[value] = $E('li').insert(options[value]);
|
1755
|
-
this.items[value].insertTo(this.options).value = value;
|
1756
|
-
}
|
1757
|
-
|
1758
|
-
// creating an the reset value
|
1759
|
-
this.items[''] = $E('li', {'class': 'remove', 'html': '--', 'title': Rte.i18n.Remove});
|
1760
|
-
this.items[''].insertTo(this.options, 'top').value = '';
|
1761
|
-
|
1762
|
-
// catching the clicks
|
1763
|
-
this.options.onMousedown(R(this.pick).bind(this));
|
1764
|
-
|
1765
|
-
// hidding the menu when the user interacts with the document outside of the document
|
1766
|
-
var hide = R(this.options.hide).bind(this.options, null);
|
1767
|
-
$(document).on({mousedown: hide,
|
1768
|
-
keydown: function(event) {
|
1769
|
-
if (event.keyCode === 27) { hide(); }
|
1770
|
-
}
|
1771
|
-
});
|
1772
|
-
|
1773
|
-
this.value = '';
|
1774
|
-
this.updateDisplay(null);
|
1775
|
-
|
1776
|
-
return this;
|
1777
|
-
},
|
1778
|
-
|
1779
|
-
// protected
|
1780
|
-
|
1781
|
-
// handling an option pick
|
1782
|
-
pick: function(event) {
|
1783
|
-
var target = event.stop().target;
|
1784
|
-
|
1785
|
-
if (target._.tagName !== 'LI') {
|
1786
|
-
target = target.parent('LI');
|
1787
|
-
}
|
1788
|
-
|
1789
|
-
if (target.value !== undefined) {
|
1790
|
-
this.options.hide();
|
1791
|
-
this.value = target.value;
|
1792
|
-
this.updateDisplay(this.value || null);
|
1793
|
-
this.markActive();
|
1794
|
-
this.exec();
|
1795
|
-
}
|
1796
|
-
},
|
1797
|
-
|
1798
|
-
// toggling the menu on the icon-click
|
1799
|
-
mousedown: function() {
|
1800
|
-
if (!this.disabled) {
|
1801
|
-
$$('.rui-rte-toolbar div.with-options ul.options')
|
1802
|
-
.without(this.options).each('hide');
|
1803
|
-
|
1804
|
-
// marking the current value so it could be seen
|
1805
|
-
if (this.options.hidden() && this.value !== null) {
|
1806
|
-
this.markActive();
|
1807
|
-
}
|
1808
|
-
|
1809
|
-
this.options.toggle('fade', {duration: 'short'});
|
1810
|
-
}
|
1811
|
-
},
|
1812
|
-
|
1813
|
-
// marks the currently active item
|
1814
|
-
markActive: function() {
|
1815
|
-
for (var item in this.items) {
|
1816
|
-
this.items[item][
|
1817
|
-
item === this.value ? 'addClass' : 'removeClass'
|
1818
|
-
]('active');
|
1819
|
-
}
|
1820
|
-
},
|
1821
|
-
|
1822
|
-
// updates the display
|
1823
|
-
updateDisplay: function(value) {
|
1824
|
-
this.display.update(
|
1825
|
-
value !== null && value in this.items ?
|
1826
|
-
this.items[value].text() : this._.title
|
1827
|
-
);
|
1828
|
-
}
|
1829
|
-
|
1830
|
-
};
|
1831
|
-
|
1832
|
-
/**
|
1833
|
-
* An abstract formatting tool that works with styles
|
1834
|
-
* basically it wraps a selection with a 'span' tag and then
|
1835
|
-
* handles the 'style' attribute, adds/removes various styles, etc.
|
1836
|
-
*
|
1837
|
-
* Copyright (C) 2010 Nikolay Nemshilov
|
1838
|
-
*/
|
1839
|
-
Rte.Tool.Style = new Class(Rte.Tool.Format, {
|
1840
|
-
include: Rte.Tool.Options,
|
1841
|
-
|
1842
|
-
tag: 'span', // tag name of the element to be used
|
1843
|
-
style: null, // the style property name (dashed)
|
1844
|
-
|
1845
|
-
/**
|
1846
|
-
* Joint constructor
|
1847
|
-
*
|
1848
|
-
* @param Rte rte
|
1849
|
-
* @return Rte.Tool.StyleOptions
|
1850
|
-
*/
|
1851
|
-
initialize: function(rte, options) {
|
1852
|
-
// a regular expression to process the `style` property
|
1853
|
-
this.re = new RegExp("(^|;)\\s*"+ RegExp.escape(this.style + ":")+ "\\s*(.+?)\\s*(;|$)");
|
1854
|
-
this.attrs = { style: this.re };
|
1855
|
-
|
1856
|
-
this.$super(rte).build(options);
|
1857
|
-
|
1858
|
-
return this;
|
1859
|
-
},
|
1860
|
-
|
1861
|
-
/**
|
1862
|
-
* Triggers the action
|
1863
|
-
*
|
1864
|
-
* @return void
|
1865
|
-
*/
|
1866
|
-
exec: function() {
|
1867
|
-
// unformatting if there is a value
|
1868
|
-
if (this.active()) {
|
1869
|
-
this.attrs = {style: this.style + ":" + this._value};
|
1870
|
-
this.unformat();
|
1871
|
-
}
|
1872
|
-
|
1873
|
-
// formatting if some value was asked
|
1874
|
-
if (this.value) {
|
1875
|
-
this.attrs = {style: this.style + ":" + this.value};
|
1876
|
-
this.format();
|
1877
|
-
}
|
1878
|
-
|
1879
|
-
// getting back the RE checker
|
1880
|
-
this.attrs = {style: this.re};
|
1881
|
-
},
|
1882
|
-
|
1883
|
-
/**
|
1884
|
-
* Overloading the original method so that we could do some additional
|
1885
|
-
* features with the actual current value
|
1886
|
-
*
|
1887
|
-
* @return void
|
1888
|
-
*/
|
1889
|
-
active: function() {
|
1890
|
-
var element = this.element(), active = false, value = null;
|
1891
|
-
|
1892
|
-
if (element !== null) {
|
1893
|
-
this._value = value = this.getStyleValue();
|
1894
|
-
active = true;
|
1895
|
-
}
|
1896
|
-
|
1897
|
-
this.updateDisplay(value);
|
1898
|
-
|
1899
|
-
return active;
|
1900
|
-
},
|
1901
|
-
|
1902
|
-
// protected
|
1903
|
-
|
1904
|
-
/**
|
1905
|
-
* Finds the current style value (if any)
|
1906
|
-
*
|
1907
|
-
* @return string style value or null if nothing
|
1908
|
-
*/
|
1909
|
-
getStyleValue: function() {
|
1910
|
-
var element = this.element();
|
1911
|
-
var attribute = element !== null ? element.getAttribute('style') : null;
|
1912
|
-
|
1913
|
-
if (attribute !== null) {
|
1914
|
-
if ((attribute = attribute.match(this.re)) !== null) {
|
1915
|
-
attribute = attribute[2];
|
1916
|
-
}
|
1917
|
-
}
|
1918
|
-
|
1919
|
-
return attribute;
|
1920
|
-
}
|
1921
|
-
});
|
1922
|
-
|
1923
|
-
/**
|
1924
|
-
* an abstract color-picking tool
|
1925
|
-
*
|
1926
|
-
* Copyright (C) 2010-2011 Nikolay Nemshilov
|
1927
|
-
*/
|
1928
|
-
Rte.Tool.Color = new Class(Rte.Tool.Style, {
|
1929
|
-
|
1930
|
-
extend: {
|
1931
|
-
COLORS: R([
|
1932
|
-
// TODO that's ain't no cool hacker's approach!
|
1933
|
-
'000000 444444 666666 999999 cccccc eeeeee f4f4f4 ffffff',
|
1934
|
-
'f24020 f79c33 fff84c 6af244 5ef9fd 0048f7 8950f7 ee5ff8',
|
1935
|
-
'e39e9b f5cba1 fee3a1 bcd3ab a6c3c8 a2c6e5 b1abd3 d0aabc '+
|
1936
|
-
'd77169 f1b374 fdd675 9cbe83 7ca4ae 74aad8 8983bf bb839f '+
|
1937
|
-
'cc0100 e79138 f1c332 69a84f 45818e 3d85c6 674ea7 a64d79 '+
|
1938
|
-
'990000 b45f05 bf9000 38761c 134f5c 0b5394 351b75 751a47 '+
|
1939
|
-
'660000 783e03 7f6000 264e13 0b333d 063763 1f124c 4c1030'
|
1940
|
-
])
|
1941
|
-
},
|
1942
|
-
|
1943
|
-
/**
|
1944
|
-
* Basic constructor, builds the colors picking panel
|
1945
|
-
*
|
1946
|
-
* @param Rte rte
|
1947
|
-
* @return Rte.Tool.Color this
|
1948
|
-
*/
|
1949
|
-
initialize: function(rte) {
|
1950
|
-
this.$super(rte, {}).addClass('color');
|
1951
|
-
this.display.clean();
|
1952
|
-
|
1953
|
-
// building the color picker menu
|
1954
|
-
Rte.Tool.Color.COLORS.each(function(line) {
|
1955
|
-
var group = $E('li', {'class': 'group'}),
|
1956
|
-
list = $E('ul').insertTo(group),
|
1957
|
-
colors = line.split(' '), i = 0, color, forecolor;
|
1958
|
-
|
1959
|
-
for (; i < colors.length; i++) {
|
1960
|
-
color = '#' + colors[i];
|
1961
|
-
forecolor = (parseInt('ffffff', 16) - parseInt(colors[i], 16)).toString(16);
|
1962
|
-
|
1963
|
-
// IE will get screwed if the length of the color is less than 6
|
1964
|
-
while (forecolor.length < 6) {
|
1965
|
-
forecolor += '0';
|
1966
|
-
}
|
1967
|
-
|
1968
|
-
this.items[color] = $E('li', {
|
1969
|
-
html: '•',
|
1970
|
-
style: {
|
1971
|
-
background: color,
|
1972
|
-
color: '#'+ forecolor
|
1973
|
-
}
|
1974
|
-
});
|
1975
|
-
|
1976
|
-
this.items[color].insertTo(list).value = color;
|
1977
|
-
}
|
1978
|
-
|
1979
|
-
this.options.append(group);
|
1980
|
-
}, this);
|
1981
|
-
|
1982
|
-
return this;
|
1983
|
-
},
|
1984
|
-
|
1985
|
-
// protected
|
1986
|
-
|
1987
|
-
/**
|
1988
|
-
* Overloading the property so that it converted any color formats
|
1989
|
-
* into a six chars hex value
|
1990
|
-
*
|
1991
|
-
* @return String current color or null
|
1992
|
-
*/
|
1993
|
-
getStyleValue: function() {
|
1994
|
-
var color = this.$super(), match;
|
1995
|
-
|
1996
|
-
if (color !== null) {
|
1997
|
-
if ((match = /^#(\w)(\w)(\w)$/.exec(color))) {
|
1998
|
-
color = "#"+ match[1]+match[1]+match[2]+match[2]+match[3]+match[3];
|
1999
|
-
} else if ((match = /^\s*rgb\((\d+),\s*(\d+),\s*(\d+)\)\s*$/.exec(color))) {
|
2000
|
-
color = "#"+ R(match.slice(1)).map(function(bit) {
|
2001
|
-
bit = (bit-0).toString(16);
|
2002
|
-
return bit.length === 1 ? '0'+bit : bit;
|
2003
|
-
}).join('');
|
2004
|
-
}
|
2005
|
-
}
|
2006
|
-
|
2007
|
-
return color;
|
2008
|
-
},
|
2009
|
-
|
2010
|
-
/**
|
2011
|
-
* Replacing the original method so that
|
2012
|
-
* it changed the color of the display thing
|
2013
|
-
* instead of text
|
2014
|
-
*
|
2015
|
-
* @param String value
|
2016
|
-
* @return void
|
2017
|
-
*/
|
2018
|
-
updateDisplay: function(value) {
|
2019
|
-
this.display._.style.background = value === null ?
|
2020
|
-
'transparent' : value;
|
2021
|
-
}
|
2022
|
-
});
|
2023
|
-
|
2024
|
-
/**
|
2025
|
-
* An abstract URL tool, used with the links, images, videos, etc.
|
2026
|
-
*
|
2027
|
-
* Copyright (C) 2010-2011 Nikolay Nemshilov
|
2028
|
-
*/
|
2029
|
-
Rte.Tool.Url = new Class(Rte.Tool, {
|
2030
|
-
attr: null, // the url-attribute 'src', 'href', etc.
|
2031
|
-
|
2032
|
-
exec: function(url) {
|
2033
|
-
if (url === undefined) {
|
2034
|
-
this.prompt();
|
2035
|
-
} else {
|
2036
|
-
if (url) {
|
2037
|
-
this[this.element() ? 'url' : 'create'](url);
|
2038
|
-
} else {
|
2039
|
-
this.rte.editor.removeElement(this.element());
|
2040
|
-
}
|
2041
|
-
}
|
2042
|
-
},
|
2043
|
-
|
2044
|
-
active: function() {
|
2045
|
-
return this.element() !== null;
|
2046
|
-
},
|
2047
|
-
|
2048
|
-
prompt: function() {
|
2049
|
-
var url = prompt(Rte.i18n.UrlAddress, this.url() || 'http://some.url.com');
|
2050
|
-
|
2051
|
-
if (url !== null) {
|
2052
|
-
this.exec(url);
|
2053
|
-
}
|
2054
|
-
},
|
2055
|
-
|
2056
|
-
// protected
|
2057
|
-
|
2058
|
-
url: function(url) {
|
2059
|
-
if (this.element()) {
|
2060
|
-
if (url !== undefined) {
|
2061
|
-
this.element()[this.attr] = url;
|
2062
|
-
} else {
|
2063
|
-
return this.element()[this.attr];
|
2064
|
-
}
|
2065
|
-
}
|
2066
|
-
},
|
2067
|
-
|
2068
|
-
create: function(url) {
|
2069
|
-
this.rte.selection.exec(this.command, url);
|
2070
|
-
}
|
2071
|
-
});
|
2072
|
-
|
2073
|
-
/**
|
2074
|
-
* Making the things bold tool
|
2075
|
-
*
|
2076
|
-
* Copyright (C) 2010-2011 Nikolay Nemshilov
|
2077
|
-
*/
|
2078
|
-
Rte.Tools.Bold = new Class(Rte.Tool.Format, {
|
2079
|
-
});
|
2080
|
-
|
2081
|
-
/**
|
2082
|
-
* Making the things italic
|
2083
|
-
*
|
2084
|
-
* Copyright (C) 2010-2011 Nikolay Nemshilov
|
2085
|
-
*/
|
2086
|
-
Rte.Tools.Italic = new Class(Rte.Tool.Format, {
|
2087
|
-
});
|
2088
|
-
|
2089
|
-
/**
|
2090
|
-
* Making the things underline tool
|
2091
|
-
*
|
2092
|
-
* Copyright (C) 2010-2011 Nikolay Nemshilov
|
2093
|
-
*/
|
2094
|
-
Rte.Tools.Underline = new Class(Rte.Tool.Format, {
|
2095
|
-
});
|
2096
|
-
|
2097
|
-
/**
|
2098
|
-
* Making the things strike through
|
2099
|
-
*
|
2100
|
-
* Copyright (C) 2010 Nikolay Nemshilov
|
2101
|
-
*/
|
2102
|
-
Rte.Tools.Strike = new Class(Rte.Tool.Format, {
|
2103
|
-
});
|
2104
|
-
|
2105
|
-
/**
|
2106
|
-
* The cut tool
|
2107
|
-
*
|
2108
|
-
* Copyrigth (C) 2010-2011 Nikolay Nemshilov
|
2109
|
-
*/
|
2110
|
-
Rte.Tools.Cut = new Class(Rte.Tool.Command, {
|
2111
|
-
command: 'cut',
|
2112
|
-
block: false,
|
2113
|
-
blip: true
|
2114
|
-
});
|
2115
|
-
|
2116
|
-
/**
|
2117
|
-
* The copy tool
|
2118
|
-
*
|
2119
|
-
* Copyrigth (C) 2010-2011 Nikolay Nemshilov
|
2120
|
-
*/
|
2121
|
-
Rte.Tools.Copy = new Class(Rte.Tools.Cut, {
|
2122
|
-
command: 'copy'
|
2123
|
-
});
|
2124
|
-
|
2125
|
-
/**
|
2126
|
-
* The paste action
|
2127
|
-
*
|
2128
|
-
* Copyrigth (C) 2010-2011 Nikolay Nemshilov
|
2129
|
-
*/
|
2130
|
-
Rte.Tools.Paste = new Class(Rte.Tools.Cut, {
|
2131
|
-
command: 'paste'
|
2132
|
-
});
|
2133
|
-
|
2134
|
-
/**
|
2135
|
-
* the 'left' tool
|
2136
|
-
*
|
2137
|
-
* Copyright (C) 2010 Nikolay Nemshilov
|
2138
|
-
*/
|
2139
|
-
Rte.Tools.Left = new Class(Rte.Tool.Command, {
|
2140
|
-
command: 'justifyleft'
|
2141
|
-
});
|
2142
|
-
|
2143
|
-
/**
|
2144
|
-
* the 'center' tool
|
2145
|
-
*
|
2146
|
-
* Copyright (C) 2010 Nikolay Nemshilov
|
2147
|
-
*/
|
2148
|
-
Rte.Tools.Center = new Class(Rte.Tool.Command, {
|
2149
|
-
command: 'justifycenter'
|
2150
|
-
});
|
2151
|
-
|
2152
|
-
/**
|
2153
|
-
* the 'right' tool
|
2154
|
-
*
|
2155
|
-
* Copyright (C) 2010 Nikolay Nemshilov
|
2156
|
-
*/
|
2157
|
-
Rte.Tools.Right = new Class(Rte.Tool.Command, {
|
2158
|
-
command: 'justifyright'
|
2159
|
-
});
|
2160
|
-
|
2161
|
-
/**
|
2162
|
-
* the 'justify' tool
|
2163
|
-
*
|
2164
|
-
* Copyright (C) 2010 Nikolay Nemshilov
|
2165
|
-
*/
|
2166
|
-
Rte.Tools.Justify = new Class(Rte.Tool.Command, {
|
2167
|
-
command: 'justifyfull'
|
2168
|
-
});
|
2169
|
-
|
2170
|
-
/**
|
2171
|
-
* The undo tool
|
2172
|
-
*
|
2173
|
-
* The actual magic happens in the Rte.Undoer class
|
2174
|
-
* here we just show the status and blip it when used
|
2175
|
-
*
|
2176
|
-
* Copyright (C) 2010-2011 Nikolay Nemshilov
|
2177
|
-
*/
|
2178
|
-
Rte.Tools.Undo = new Class(Rte.Tool, {
|
2179
|
-
blip: true,
|
2180
|
-
|
2181
|
-
exec: function() {
|
2182
|
-
this.rte.undoer.undo();
|
2183
|
-
},
|
2184
|
-
|
2185
|
-
enabled: function() {
|
2186
|
-
return this.rte.undoer.hasUndo();
|
2187
|
-
}
|
2188
|
-
});
|
2189
|
-
|
2190
|
-
/**
|
2191
|
-
* the 'redo' tool
|
2192
|
-
*
|
2193
|
-
* The actual magic happens in the Rte.Undoer class
|
2194
|
-
* here we just show the status and blip it when used
|
2195
|
-
*
|
2196
|
-
* Copyright (C) 2010 Nikolay Nemshilov
|
2197
|
-
*/
|
2198
|
-
Rte.Tools.Redo = new Class(Rte.Tool, {
|
2199
|
-
blip: true,
|
2200
|
-
|
2201
|
-
exec: function() {
|
2202
|
-
this.rte.undoer.redo();
|
2203
|
-
},
|
2204
|
-
|
2205
|
-
enabled: function() {
|
2206
|
-
return this.rte.undoer.hasRedo();
|
2207
|
-
}
|
2208
|
-
|
2209
|
-
});
|
2210
|
-
|
2211
|
-
/**
|
2212
|
-
* The code block tool
|
2213
|
-
*
|
2214
|
-
* Copyrigth (C) 2010-2011 Nikolay Nemshilov
|
2215
|
-
*/
|
2216
|
-
Rte.Tools.Code = new Class(Rte.Tool.Format, {
|
2217
|
-
});
|
2218
|
-
|
2219
|
-
/**
|
2220
|
-
* The block quote tool
|
2221
|
-
*
|
2222
|
-
* Copyrigth (C) 2010 Nikolay Nemshilov
|
2223
|
-
*/
|
2224
|
-
Rte.Tools.Quote = new Class(Rte.Tool.Format, {
|
2225
|
-
});
|
2226
|
-
|
2227
|
-
/**
|
2228
|
-
* the 'ttext' tool
|
2229
|
-
*
|
2230
|
-
* Copyright (C) 2010-2011 Nikolay Nemshilov
|
2231
|
-
*/
|
2232
|
-
Rte.Tools.Ttext = new Class(Rte.Tool.Format, {
|
2233
|
-
});
|
2234
|
-
|
2235
|
-
/**
|
2236
|
-
* The header block tool
|
2237
|
-
*
|
2238
|
-
* Copyrigth (C) 2010-2011 Nikolay Nemshilov
|
2239
|
-
*/
|
2240
|
-
Rte.Tools.Header = new Class(Rte.Tool.Format, {
|
2241
|
-
});
|
2242
|
-
|
2243
|
-
/**
|
2244
|
-
* The the url link tool
|
2245
|
-
*
|
2246
|
-
* Copyrigth (C) 2010-2011 Nikolay Nemshilov
|
2247
|
-
*/
|
2248
|
-
Rte.Tools.Link = new Class(Rte.Tool.Url, {
|
2249
|
-
command: 'createlink',
|
2250
|
-
attr: 'href',
|
2251
|
-
|
2252
|
-
enabled: function() {
|
2253
|
-
return !this.rte.selection.empty() || this.active();
|
2254
|
-
},
|
2255
|
-
|
2256
|
-
element: function() {
|
2257
|
-
return this.rte.status.findElement('A', {});
|
2258
|
-
}
|
2259
|
-
});
|
2260
|
-
|
2261
|
-
/**
|
2262
|
-
* The image tool
|
2263
|
-
*
|
2264
|
-
* Copyrigth (C) 2010-2011 Nikolay Nemshilov
|
2265
|
-
*/
|
2266
|
-
Rte.Tools.Image = new Class(Rte.Tool.Url, {
|
2267
|
-
command: 'insertimage',
|
2268
|
-
attr: 'src',
|
2269
|
-
|
2270
|
-
element: function() {
|
2271
|
-
var image = this.rte.selection.element();
|
2272
|
-
return image !== null && image.tagName === "IMG" ? image : null;
|
2273
|
-
}
|
2274
|
-
|
2275
|
-
});
|
2276
|
-
|
2277
|
-
/**
|
2278
|
-
* the 'video' tool
|
2279
|
-
*
|
2280
|
-
* Copyright (C) 2010 Nikolay Nemshilov
|
2281
|
-
*/
|
2282
|
-
Rte.Tools.Video = new Class(Rte.Tool.Url, {
|
2283
|
-
command: 'inserthtml',
|
2284
|
-
|
2285
|
-
enabled: function() {
|
2286
|
-
return true; // always enabled
|
2287
|
-
},
|
2288
|
-
|
2289
|
-
element: function() {
|
2290
|
-
return this.rte.status.findElement('OBJECT', {});
|
2291
|
-
},
|
2292
|
-
|
2293
|
-
// works with url address of the embedded object
|
2294
|
-
url: function(url) {
|
2295
|
-
var element = this.element() && this.element().getElementsByTagName('embed')[0];
|
2296
|
-
|
2297
|
-
if (element) {
|
2298
|
-
if (url !== undefined) {
|
2299
|
-
element.src = this.swfUrl(url);
|
2300
|
-
} else {
|
2301
|
-
return element.src;
|
2302
|
-
}
|
2303
|
-
}
|
2304
|
-
},
|
2305
|
-
|
2306
|
-
// creates the actual object block
|
2307
|
-
create: function(url) {
|
2308
|
-
var swf_url = this.swfUrl(url),
|
2309
|
-
size = 'width="'+ this.rte.options.videoSize.split('x')[0] +
|
2310
|
-
'" height="'+ this.rte.options.videoSize.split('x')[1] + '"';
|
2311
|
-
|
2312
|
-
this.$super('<object '+ size +'>'+
|
2313
|
-
'<param name="src" value="'+ swf_url +'" />'+
|
2314
|
-
'<embed src="'+ swf_url +'" type="application/x-shockwave-flash" '+ size + ' />' +
|
2315
|
-
'</object>');
|
2316
|
-
},
|
2317
|
-
|
2318
|
-
// making the actual 'swf' url
|
2319
|
-
swfUrl: function(url) {
|
2320
|
-
return R(Rte.Videos).map(function(desc) {
|
2321
|
-
return url.match(desc[0]) ?
|
2322
|
-
url.replace(desc[0], desc[1]) : null;
|
2323
|
-
}).compact()[0] || url;
|
2324
|
-
}
|
2325
|
-
});
|
2326
|
-
|
2327
|
-
/**
|
2328
|
-
* the 'dotlist' tool
|
2329
|
-
*
|
2330
|
-
* Copyright (C) 2010 Nikolay Nemshilov
|
2331
|
-
*/
|
2332
|
-
Rte.Tools.Dotlist = new Class(Rte.Tool.Command, {
|
2333
|
-
command: 'insertunorderedlist'
|
2334
|
-
});
|
2335
|
-
|
2336
|
-
/**
|
2337
|
-
* the 'numlist' tool
|
2338
|
-
*
|
2339
|
-
* Copyright (C) 2010 Nikolay Nemshilov
|
2340
|
-
*/
|
2341
|
-
Rte.Tools.Numlist = new Class(Rte.Tool.Command, {
|
2342
|
-
command: 'insertorderedlist'
|
2343
|
-
});
|
2344
|
-
|
2345
|
-
/**
|
2346
|
-
* the 'indent' tool
|
2347
|
-
*
|
2348
|
-
* Copyright (C) 2010 Nikolay Nemshilov
|
2349
|
-
*/
|
2350
|
-
Rte.Tools.Indent = new Class(Rte.Tool.Command, {
|
2351
|
-
command: 'indent'
|
2352
|
-
});
|
2353
|
-
|
2354
|
-
/**
|
2355
|
-
* the 'Outdent' tool
|
2356
|
-
*
|
2357
|
-
* Copyright (C) 2010 Nikolay Nemshilov
|
2358
|
-
*/
|
2359
|
-
Rte.Tools.Outdent = new Class(Rte.Tool.Command, {
|
2360
|
-
command: 'outdent'
|
2361
|
-
});
|
2362
|
-
|
2363
|
-
/**
|
2364
|
-
* the 'forecolor' tool
|
2365
|
-
*
|
2366
|
-
* Copyright (C) 2010 Nikolay Nemshilov
|
2367
|
-
*/
|
2368
|
-
Rte.Tools.Forecolor = new Class(Rte.Tool.Color, {
|
2369
|
-
style: 'color'
|
2370
|
-
});
|
2371
|
-
|
2372
|
-
/**
|
2373
|
-
* the 'backcolor' tool
|
2374
|
-
*
|
2375
|
-
* Copyright (C) 2010 Nikolay Nemshilov
|
2376
|
-
*/
|
2377
|
-
Rte.Tools.Backcolor = new Class(Rte.Tool.Color, {
|
2378
|
-
style: 'background-color'
|
2379
|
-
});
|
2380
|
-
|
2381
|
-
/**
|
2382
|
-
* The source tool
|
2383
|
-
*
|
2384
|
-
* Copyrigth (C) 2010-2011 Nikolay Nemshilov
|
2385
|
-
*/
|
2386
|
-
Rte.Tools.Source = new Class(Rte.Tool, {
|
2387
|
-
source: false, // the textarea element reference
|
2388
|
-
|
2389
|
-
exec: function() {
|
2390
|
-
this[this.rte.srcMode ? 'showPreview' : 'showSource']();
|
2391
|
-
this.rte.srcMode = !this.rte.srcMode;
|
2392
|
-
},
|
2393
|
-
|
2394
|
-
active: function() {
|
2395
|
-
return this.rte.srcMode;
|
2396
|
-
},
|
2397
|
-
|
2398
|
-
// protected
|
2399
|
-
|
2400
|
-
showPreview: function() {
|
2401
|
-
this.rte.editor.setStyle('visibility:visible');
|
2402
|
-
if (this.source) {
|
2403
|
-
this.rte.value(this.source.value());
|
2404
|
-
this.source.remove();
|
2405
|
-
}
|
2406
|
-
|
2407
|
-
this.rte.editor.focus();
|
2408
|
-
},
|
2409
|
-
|
2410
|
-
showSource: function() {
|
2411
|
-
this.rte.editor.setStyle('visibility:hidden;');
|
2412
|
-
|
2413
|
-
(
|
2414
|
-
this.source = this.source ||
|
2415
|
-
$E('textarea', {'class': 'rui-rte-source'})
|
2416
|
-
)
|
2417
|
-
.insertTo(this.rte.editor, 'before')
|
2418
|
-
.resize(this.rte.editor.size())
|
2419
|
-
.setValue('' + this.rte.value())
|
2420
|
-
.focus();
|
2421
|
-
|
2422
|
-
this.rte.focused = true;
|
2423
|
-
|
2424
|
-
this.rte.status.update();
|
2425
|
-
|
2426
|
-
// locking all the tools
|
2427
|
-
for (var name in this.rte.tools) {
|
2428
|
-
if (this.rte.tools[name] !== this) {
|
2429
|
-
this.rte.tools[name].addClass('disabled');
|
2430
|
-
}
|
2431
|
-
}
|
2432
|
-
}
|
2433
|
-
});
|
2434
|
-
|
2435
|
-
/**
|
2436
|
-
* the 'clear' tool
|
2437
|
-
*
|
2438
|
-
* Copyright (C) 2010-2011 Nikolay Nemshilov
|
2439
|
-
*/
|
2440
|
-
Rte.Tools.Clear = new Class(Rte.Tool, {
|
2441
|
-
|
2442
|
-
exec: function() {
|
2443
|
-
this.rte.editor.clean();
|
2444
|
-
}
|
2445
|
-
|
2446
|
-
});
|
2447
|
-
|
2448
|
-
/**
|
2449
|
-
* the 'save' tool
|
2450
|
-
*
|
2451
|
-
* Copyright (C) 2010-2011 Nikolay Nemshilov
|
2452
|
-
*/
|
2453
|
-
Rte.Tools.Save = new Class(Rte.Tool, {
|
2454
|
-
|
2455
|
-
initialize: function(rte) {
|
2456
|
-
this.$super(rte);
|
2457
|
-
if (!(rte.textarea && rte.textarea.form())) {
|
2458
|
-
this.disabled = true;
|
2459
|
-
this.addClass('disabled');
|
2460
|
-
}
|
2461
|
-
},
|
2462
|
-
|
2463
|
-
exec: function() {
|
2464
|
-
if (!this.disabled) {
|
2465
|
-
this.rte.textarea.form().submit();
|
2466
|
-
}
|
2467
|
-
},
|
2468
|
-
|
2469
|
-
check: function() {} // checked in the constructor
|
2470
|
-
});
|
2471
|
-
|
2472
|
-
/**
|
2473
|
-
* Formatting style tool
|
2474
|
-
*
|
2475
|
-
* Copyright (C) 2010 Nikolay Nemshilov
|
2476
|
-
*/
|
2477
|
-
Rte.Tools.Format = new Class(Rte.Tool.Format, {
|
2478
|
-
include: Rte.Tool.Options,
|
2479
|
-
|
2480
|
-
/**
|
2481
|
-
* Constructor, builds the options list and
|
2482
|
-
* defines the formats index for quick access
|
2483
|
-
*
|
2484
|
-
* @param Rte rte
|
2485
|
-
*/
|
2486
|
-
initialize: function(rte) {
|
2487
|
-
var options = {}, rule, tag, match;
|
2488
|
-
|
2489
|
-
this.formats = {};
|
2490
|
-
|
2491
|
-
for (rule in Rte.Formats) {
|
2492
|
-
if ((match = rule.match(/^([a-z0-9]+)(\.([a-z0-9_\-]+))?$/))) {
|
2493
|
-
tag = match[1];
|
2494
|
-
|
2495
|
-
this.formats[rule] = { tag: tag.toUpperCase(), attrs: {}, match: {} };
|
2496
|
-
|
2497
|
-
if (match[3]) {
|
2498
|
-
this.formats[rule]['attrs']['class'] = match[3];
|
2499
|
-
this.formats[rule]['match']['class'] = new RegExp(
|
2500
|
-
'(^|\\s+)'+ RegExp.escape(match[3]) + '(\\s+|$)'
|
2501
|
-
);
|
2502
|
-
}
|
2503
|
-
|
2504
|
-
options[rule] = '<'+ tag + ' class="'+ match[3] + '">'+
|
2505
|
-
Rte.Formats[rule] + '</'+ tag + '>';
|
2506
|
-
}
|
2507
|
-
}
|
2508
|
-
|
2509
|
-
this.$super(rte).build(options);
|
2510
|
-
|
2511
|
-
return this;
|
2512
|
-
},
|
2513
|
-
|
2514
|
-
/**
|
2515
|
-
* Handling the formatting
|
2516
|
-
*
|
2517
|
-
* @return void
|
2518
|
-
*/
|
2519
|
-
exec: function() {
|
2520
|
-
// removing the formatting first
|
2521
|
-
if (this.active() && this.rule) {
|
2522
|
-
this.tag = this.formats[this.rule].tag;
|
2523
|
-
this.attrs = this.formats[this.rule].attrs;
|
2524
|
-
this.unformat();
|
2525
|
-
}
|
2526
|
-
|
2527
|
-
// applying a new formatting if needed
|
2528
|
-
if (this.value && this.formats[this.value]) {
|
2529
|
-
this.tag = this.formats[this.value].tag;
|
2530
|
-
this.attrs = this.formats[this.value].attrs;
|
2531
|
-
this.format();
|
2532
|
-
}
|
2533
|
-
},
|
2534
|
-
|
2535
|
-
/**
|
2536
|
-
* Overloading the original method so that it updated the
|
2537
|
-
* currently used formatting style in the display area
|
2538
|
-
*
|
2539
|
-
* @return boolean check result
|
2540
|
-
*/
|
2541
|
-
active: function() {
|
2542
|
-
var active = this.element() !== null;
|
2543
|
-
this.updateDisplay(this.rule);
|
2544
|
-
return active;
|
2545
|
-
},
|
2546
|
-
|
2547
|
-
// protected
|
2548
|
-
|
2549
|
-
// overloading the original method to handle multiple options
|
2550
|
-
element: function() {
|
2551
|
-
var rule, element, status = this.rte.status;
|
2552
|
-
|
2553
|
-
for (rule in this.formats) {
|
2554
|
-
element = status.findElement(
|
2555
|
-
this.formats[rule]['tag'],
|
2556
|
-
this.formats[rule]['match']
|
2557
|
-
);
|
2558
|
-
|
2559
|
-
if (element !== null) {
|
2560
|
-
this.rule = rule;
|
2561
|
-
return element;
|
2562
|
-
}
|
2563
|
-
}
|
2564
|
-
|
2565
|
-
return (this.rule = null);
|
2566
|
-
}
|
2567
|
-
|
2568
|
-
|
2569
|
-
|
2570
|
-
});
|
2571
|
-
|
2572
|
-
/**
|
2573
|
-
* Font-name options tool
|
2574
|
-
*
|
2575
|
-
* Copyright (C) 2010 Nikolay Nemshilov
|
2576
|
-
*/
|
2577
|
-
Rte.Tools.Fontname = new Class(Rte.Tool.Style, {
|
2578
|
-
style: 'font-family',
|
2579
|
-
|
2580
|
-
/**
|
2581
|
-
* Basic constructor
|
2582
|
-
*
|
2583
|
-
* @param Rte rte
|
2584
|
-
*/
|
2585
|
-
initialize: function(rte) {
|
2586
|
-
var options = {}, name, fonts = Rte.FontNames;
|
2587
|
-
|
2588
|
-
for (name in fonts) {
|
2589
|
-
options[fonts[name]] = '<div style="font-family:'+
|
2590
|
-
fonts[name]+ '">' + name + '</div>';
|
2591
|
-
}
|
2592
|
-
|
2593
|
-
return this.$super(rte, options);
|
2594
|
-
}
|
2595
|
-
});
|
2596
|
-
|
2597
|
-
|
2598
|
-
/**
|
2599
|
-
* The font-size tool
|
2600
|
-
*
|
2601
|
-
* Copyright (C) 2010 Nikolay Nemshilov
|
2602
|
-
*/
|
2603
|
-
Rte.Tools.Fontsize = new Class(Rte.Tool.Style, {
|
2604
|
-
style: 'font-size',
|
2605
|
-
|
2606
|
-
/**
|
2607
|
-
* Basic constructor
|
2608
|
-
*
|
2609
|
-
* @param Rte rte
|
2610
|
-
*/
|
2611
|
-
initialize: function(rte) {
|
2612
|
-
var options = {}, i=0, sizes = Rte.FontSizes.split(/\s+/);
|
2613
|
-
|
2614
|
-
for (; i < sizes.length; i++) {
|
2615
|
-
options[sizes[i]] = '<div style="font-size:'+
|
2616
|
-
sizes[i] +'">'+ sizes[i] + '</div>';
|
2617
|
-
}
|
2618
|
-
|
2619
|
-
return this.$super(rte, options);
|
2620
|
-
}
|
2621
|
-
});
|
2622
|
-
|
2623
|
-
/**
|
2624
|
-
* The subscript tool
|
2625
|
-
*
|
2626
|
-
* Copyright (C) 2010 Nikolay Nemshilov
|
2627
|
-
*/
|
2628
|
-
Rte.Tools.Subscript = new Class(Rte.Tool.Command, {
|
2629
|
-
command: 'subscript'
|
2630
|
-
});
|
2631
|
-
|
2632
|
-
/**
|
2633
|
-
* The superscript tool
|
2634
|
-
*
|
2635
|
-
* Copyright (C) 2010 Nikolay Nemshilov
|
2636
|
-
*/
|
2637
|
-
Rte.Tools.Superscript = new Class(Rte.Tool.Command, {
|
2638
|
-
command: 'superscript'
|
2639
|
-
});
|
2640
|
-
|
2641
|
-
/**
|
2642
|
-
* Document level hooks for the Rte widget
|
2643
|
-
*
|
2644
|
-
* Copyright (C) 2010 Nikolay Nemshilov
|
2645
|
-
*/
|
2646
|
-
$(document).onReady(function() {
|
2647
|
-
$$(Rte.Options.cssRule).each('getRich');
|
2648
|
-
});
|
2649
|
-
|
2650
|
-
/**
|
2651
|
-
* Input level hooks to convert textareas into RTE
|
2652
|
-
*
|
2653
|
-
* Copyright (C) 2010 Nikolay Nemshilov
|
2654
|
-
*/
|
2655
|
-
Input.include({
|
2656
|
-
/**
|
2657
|
-
* converts an input field into a RTE
|
2658
|
-
*
|
2659
|
-
* @param Object options
|
2660
|
-
* @return Rte editor
|
2661
|
-
*/
|
2662
|
-
getRich: function(options) {
|
2663
|
-
if (this._.type === 'textarea' && !this.rte) {
|
2664
|
-
this.rte = new Rte(this, options);
|
2665
|
-
}
|
2666
|
-
|
2667
|
-
return this.rte;
|
2668
|
-
}
|
2669
|
-
});
|
2670
|
-
|
2671
|
-
var embed_style = document.createElement('style'),
|
2672
|
-
embed_rules = document.createTextNode("div.rui-rte,div.rui-rte-toolbar,div.rui-rte-toolbar *,div.rui-rte-editor,div.rui-rte-status,div.rui-rte-status *{margin:0;padding:0;background:none;border:none;width:auto;height:auto}textarea[data-rte]{visibility:hidden}div.rui-rte{display:inline-block; *display:inline; *zoom:1;position:relative}div.rui-rte-toolbar{padding:.15em .3em;background:#eee;border-radius:.25em .25em 0 0;-moz-border-radius:.25em .25em 0 0;-webkit-border-radius:.25em .25em 0 0;border:1px solid #ccc;border-bottom:none}div.rui-rte-toolbar div.line{display:inline-block; *display:inline; *zoom:1;margin-bottom:1px}div.rui-rte-toolbar div.bar{display:inline-block; *display:inline; *zoom:1;margin-right:2px}div.rui-rte-toolbar div.tool{display:inline-block; *display:inline; *zoom:1;margin-right:1px;vertical-align:middle;position:relative;cursor:pointer;border:1px solid #bbb;background-image:url(/images/rightjs-ui/rte.png);background-position:0px 0px;background-color:#fff;border-radius:.25em;-moz-border-radius:.25em;-webkit-border-radius:.25em}div.rui-rte-toolbar div.tool:hover{background-color:#ddd;border-color:#777}div.rui-rte-toolbar div.active{background-position:-20px 0px;background-color:#eee;border-color:#666;box-shadow:#aaa .025em .025em .5em;-moz-box-shadow:#aaa .025em .025em .5em;-webkit-box-shadow:#aaa .025em .025em .5em}div.rui-rte-toolbar div.disabled,div.rui-rte-toolbar div.disabled:hover{opacity:.4;filter:alpha(opacity=40);background-position:-40px 0px;background-color:#eee;border-color:#aaa;cursor:default}div.rui-rte-toolbar div.highlight{background-color:#BBB;border-color:#666}div.rui-rte-toolbar div.icon{height:20px;width:20px;background-image:url(/images/rightjs-ui/rte.png);background-repeat:no-repeat;background-position:20px 20px}div.rui-rte-toolbar div.save div.icon{background-position:0px -20px}div.rui-rte-toolbar div.clear div.icon{background-position:-20px -20px}div.rui-rte-toolbar div.source div.icon{background-position:-40px -20px}div.rui-rte-toolbar div.bold div.icon{background-position:0px -40px}div.rui-rte-toolbar div.italic div.icon{background-position:-20px -40px}div.rui-rte-toolbar div.underline div.icon{background-position:-40px -40px}div.rui-rte-toolbar div.strike div.icon{background-position:-60px -40px}div.rui-rte-toolbar div.cut div.icon{background-position:0px -60px}div.rui-rte-toolbar div.copy div.icon{background-position:-20px -60px}div.rui-rte-toolbar div.paste div.icon{background-position:-40px -60px}div.rui-rte-toolbar div.left div.icon{background-position:0px -80px}div.rui-rte-toolbar div.center div.icon{background-position:-20px -80px}div.rui-rte-toolbar div.right div.icon{background-position:-40px -80px}div.rui-rte-toolbar div.justify div.icon{background-position:-60px -80px}div.rui-rte-toolbar div.undo div.icon{background-position:0px -100px}div.rui-rte-toolbar div.redo div.icon{background-position:-20px -100px}div.rui-rte-toolbar div.quote div.icon{background-position:0px -120px}div.rui-rte-toolbar div.code div.icon{background-position:-20px -120px}div.rui-rte-toolbar div.ttext div.icon{background-position:-40px -120px}div.rui-rte-toolbar div.header div.icon{background-position:-60px -120px}div.rui-rte-toolbar div.image div.icon{background-position:0px -140px}div.rui-rte-toolbar div.link div.icon{background-position:-20px -140px}div.rui-rte-toolbar div.video div.icon{background-position:-40px -140px}div.rui-rte-toolbar div.dotlist div.icon{background-position:0px -160px}div.rui-rte-toolbar div.numlist div.icon{background-position:-20px -160px}div.rui-rte-toolbar div.indent div.icon{background-position:-40px -160px}div.rui-rte-toolbar div.outdent div.icon{background-position:-60px -160px}div.rui-rte-toolbar div.forecolor div.icon{background-position:0px -180px}div.rui-rte-toolbar div.backcolor div.icon{background-position:-20px -180px}div.rui-rte-toolbar div.symbol div.icon{background-position:0px -200px}div.rui-rte-toolbar div.subscript div.icon{background-position:-20px -200px}div.rui-rte-toolbar div.superscript div.icon{background-position:-40px -200px}div.rui-rte-toolbar div.with-options{padding-right:8px}div.rui-rte-toolbar div.with-options div.trigger{position:absolute;right:0;height:100%;width:7px;text-align:center;background:#ccc;border-left:1px solid #bbb}div.rui-rte-toolbar div.bar div:hover div.trigger,div.rui-rte-toolbar div.bar div.active div.trigger{background:#aaa;border-color:#888}div.rui-rte-toolbar div.with-options div.icon{display:none}div.rui-rte-toolbar div.with-options div.display{display:block;line-height:20px;padding:0 6px;margin:0;color:#222;font-size:12px;background:#f8f8f8}div.rui-rte-toolbar div.with-options ul.options,div.rui-rte-toolbar div.with-options ul.options li{list-style:none;margin:0;padding:0}div.rui-rte-toolbar div.with-options ul.options{display:none;cursor:default;position:absolute;margin-bottom:1px;margin-left:-1px;background:#fff;border:1px solid #aaa;border-radius:.25em;-moz-border-radius:.25em;-webkit-border-radius:.25em;box-shadow:#bbb .1em .1em .25em;-moz-box-shadow:#bbb .1em .1em .25em;-webkit-box-shadow:#bbb .1em .1em .25em}div.rui-rte-toolbar div.with-options ul.options li{padding:.2em .5em;white-space:nowrap;cursor:pointer}div.rui-rte-toolbar div.with-options ul.options li:hover{background-color:#eee}div.rui-rte-toolbar div.with-options ul.options li> *{margin:0;padding:0;border:none;position:static}div.rui-rte-toolbar div.color div.icon{display:block}div.rui-rte-toolbar div.color ul.options{padding-bottom:.5em}div.rui-rte-toolbar div.color ul.options li.group,div.rui-rte-toolbar div.color ul.options li.group:hover{background:none}div.rui-rte-toolbar div.color ul.options li.group ul{width:144px;clear:both;padding-top:.5em}div.rui-rte-toolbar div.color ul.options li.group ul li{float:left;width:16px;height:16px;line-height:16px;font-size:80%;text-align:center;text-indent:-9999em;padding:0;cursor:pointer;border:1px solid transparent}div.rui-rte-toolbar div.color ul.options li.group ul li:hover,div.rui-rte-toolbar div.color ul.options li.group ul li.active{background:none;border-color:#444;border-radius:.1em;-moz-border-radius:.1em;-webkit-border-radius:.1em}div.rui-rte-toolbar div.color ul.options li.group ul li.active{text-indent:0}div.rui-rte-toolbar div.color div.display{position:absolute;text-indent:-9999em;bottom:2px;left:3px;margin:0;padding:0;width:14px;height:4px;border-radius:.1em;-moz-border-radius:.1em;-webkit-border-radius:.1em}div.rui-rte-toolbar div.color ul.options li.group ul li.none{border-color:#444}div.rui-rte-toolbar div.color ul.options li.group ul li.label,div.rui-rte-toolbar div.color ul.options li.group ul li.label:hover{text-indent:0;border:none;margin-left:.5em;font-size:1em;cursor:default}div.rui-rte-editor{outline:none;outline:hidden;padding:.1em .3em;overflow:auto;background:white;border:1px solid #ccc}div.rui-rte-editor:focus{border-color:#aaa}div.rui-rte-editor> *:first-child{margin-top:0}div.rui-rte-editor> *:last-child{margin-bottom:0}div.rui-rte textarea.rui-rte-source{position:absolute;outline:none;resize:none}div.rui-rte-status{font-size:90%;height:1.4em;padding:0 .5em;color:#888;background:#eee;border:1px solid #ccc;border-top:none;border-radius:0 0 .25em .25em;-moz-border-radius:0 0 .25em .25em;-webkit-border-radius:0 0 .25em .25em}");
|
2673
|
-
|
2674
|
-
embed_style.type = 'text/css';
|
2675
|
-
document.getElementsByTagName('head')[0].appendChild(embed_style);
|
2676
|
-
|
2677
|
-
if(embed_style.styleSheet) {
|
2678
|
-
embed_style.styleSheet.cssText = embed_rules.nodeValue;
|
2679
|
-
} else {
|
2680
|
-
embed_style.appendChild(embed_rules);
|
2681
|
-
}
|
2682
|
-
|
2683
|
-
|
2684
|
-
return Rte;
|
2685
|
-
})(RightJS, document, window);
|