activeadmin-settings 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/lib/activeadmin-settings/version.rb +1 -1
  2. data/vendor/assets/javascripts/activeadmin_settings/tabs.js.coffee +0 -8
  3. data/vendor/assets/javascripts/redactor.js.erb +3224 -0
  4. data/vendor/assets/stylesheets/activeadmin_settings.css.scss +5 -1
  5. data/vendor/assets/stylesheets/redactor.css +555 -0
  6. metadata +6 -41
  7. data/vendor/assets/javascripts/redactor/css/docstyle.css +0 -139
  8. data/vendor/assets/javascripts/redactor/css/style.css +0 -135
  9. data/vendor/assets/javascripts/redactor/css/wym.css +0 -151
  10. data/vendor/assets/javascripts/redactor/index.js +0 -1
  11. data/vendor/assets/javascripts/redactor/langs/bg.js +0 -67
  12. data/vendor/assets/javascripts/redactor/langs/by.js +0 -65
  13. data/vendor/assets/javascripts/redactor/langs/cs.js +0 -77
  14. data/vendor/assets/javascripts/redactor/langs/de.js +0 -70
  15. data/vendor/assets/javascripts/redactor/langs/en.js +0 -66
  16. data/vendor/assets/javascripts/redactor/langs/eo.js +0 -66
  17. data/vendor/assets/javascripts/redactor/langs/es.js +0 -66
  18. data/vendor/assets/javascripts/redactor/langs/fa.js +0 -66
  19. data/vendor/assets/javascripts/redactor/langs/fi.js +0 -69
  20. data/vendor/assets/javascripts/redactor/langs/fr.js +0 -76
  21. data/vendor/assets/javascripts/redactor/langs/hr.js +0 -69
  22. data/vendor/assets/javascripts/redactor/langs/hu.js +0 -67
  23. data/vendor/assets/javascripts/redactor/langs/it.js +0 -68
  24. data/vendor/assets/javascripts/redactor/langs/ja.js +0 -66
  25. data/vendor/assets/javascripts/redactor/langs/ko.js +0 -66
  26. data/vendor/assets/javascripts/redactor/langs/lv.js +0 -65
  27. data/vendor/assets/javascripts/redactor/langs/nl.js +0 -69
  28. data/vendor/assets/javascripts/redactor/langs/pl.js +0 -66
  29. data/vendor/assets/javascripts/redactor/langs/pt_br.js +0 -72
  30. data/vendor/assets/javascripts/redactor/langs/ru.js +0 -66
  31. data/vendor/assets/javascripts/redactor/langs/sk.js +0 -66
  32. data/vendor/assets/javascripts/redactor/langs/sq.js +0 -69
  33. data/vendor/assets/javascripts/redactor/langs/tr.js +0 -66
  34. data/vendor/assets/javascripts/redactor/langs/ua.js +0 -67
  35. data/vendor/assets/javascripts/redactor/langs/zh_cn.js +0 -67
  36. data/vendor/assets/javascripts/redactor/langs/zh_tw.js +0 -66
  37. data/vendor/assets/javascripts/redactor/redactor.js.erb +0 -3375
  38. data/vendor/assets/stylesheets/redactor/css/docstyle.css +0 -139
  39. data/vendor/assets/stylesheets/redactor/css/redactor.css +0 -410
  40. data/vendor/assets/stylesheets/redactor/css/style.css +0 -135
  41. data/vendor/assets/stylesheets/redactor/css/wym.css +0 -151
  42. data/vendor/assets/stylesheets/redactor/img/icons.png +0 -0
  43. data/vendor/assets/stylesheets/redactor/index.css +0 -1
@@ -1,3 +1,3 @@
1
1
  module ActiveadminSettings
2
- VERSION = "0.3.1"
2
+ VERSION = "0.3.2"
3
3
  end
@@ -8,14 +8,6 @@ enable_redactor = ->
8
8
  unless window.redactor_settings
9
9
  window.redactor_settings = {}
10
10
 
11
- window.redactor_settings["buttons"] = [ 'html', '|',
12
- 'formatting', '|',
13
- 'bold', 'italic', 'deleted', '|',
14
- 'unorderedlist', 'orderedlist', 'outdent', 'indent', '|',
15
- 'image', 'video', 'file', 'table', 'link', '|',
16
- 'alignleft', 'aligncenter', 'alignright', 'justify', '|',
17
- 'fullscreen' ]
18
-
19
11
  # after tab was clicked there is a workaround to turn on redactor
20
12
  $('#settings_tabs').bind 'easytabs:after', (event, $clicked, $targetPanel, settings) ->
21
13
  text_input = $targetPanel.find('.settings-redactor')
@@ -0,0 +1,3224 @@
1
+ /*
2
+ Redactor v8.0.1
3
+ Updated: August 14, 2012
4
+
5
+ http://redactorjs.com/
6
+
7
+ Copyright (c) 2009-2012, Imperavi Inc.
8
+ License: http://redactorjs.com/license/
9
+
10
+ Usage: $('#content').redactor();
11
+ */
12
+
13
+ // selection
14
+ var _0xf6db=["(6(){11 49=24;11 14={50:6(8,10){5 10.58(8)\x2692},57:6(8,10){7(8.58!=12){5 8.58(10)\x2616}46{5 8.57(10)}},55:6(8,18,10,20){7(8===10){5 18\x3C=20}7(14.29(8)\x26\x2614.29(10)){5 14.50(8,10)}7(14.29(8)\x26\x26!14.29(10)){5!14.55(10,20,8,18)}7(!14.57(8,10)){5 14.50(8,10)}7(8.47.85\x3C=18){5 40}7(8.47[18]===10){5 0\x3C=20}5 14.50(8.47[18],10)},29:6(61){5(61!=12?61.93==3:40)},81:6(41){11 62=0;88(41=41.59){62++}5 62}};11 4=49.4=(6(){6 4(2){24.2=2}4.34.31=6(){5 4.31(24.2)};4.34.37=6(){5 4.37(24.2)};4.34.38=6(){5 4.38(24.2)};4.34.45=6(){5 4.45(24.2)};4.34.44=6(){5 4.44(24.2)};4.34.52=6(25,26,23,22){5 4.52(24.2,25,26,23,22)};4.34.51=6(){5 4.51(24.2)};5 4})();7(49.35){4.67=43;4.31=6(2){11 9;5(9=2.35())\x26\x26(9.63!=12)\x26\x26(9.36!=12)};4.37=6(2){11 9;7(!((9=2.35())\x26\x26(9.36!=12))){5 12}5[9.36,9.97]};4.38=6(2){11 9;7(!((9=2.35())\x26\x26(9.63!=12))){5 12}5[9.63,9.91]};4.45=6(2){11 8,10,18,20,27,28;7(!4.31(2)){5 12}27=4.37(2),8=27[0],18=27[1];28=4.38(2),10=28[0],20=28[1];7(14.55(8,18,10,20)){5[8,18]}5[10,20]};4.44=6(2){11 8,10,18,20,27,28;7(!4.31(2)){5 12}27=4.37(2),8=27[0],18=27[1];28=4.38(2),10=28[0],20=28[1];7(14.55(8,18,10,20)){5[10,20]}5[8,18]};4.52=6(2,25,26,23,22){11 9=2.35();7(!9){5}7(23==12){23=25}7(22==12){22=26}7(9.60\x26\x269.79){9.60(25,26);9.79(23,22)}46{54=2.15.56();54.106(25,26);54.107(23,22);71{9.73()}80(41){}9.98(54)}};4.51=6(2){71{11 9=2.35();7(!9){5}9.73()}80(41){}}}46 7(49.15.39){11 69=6(42,32,30){11 19,13,21,33,64;13=42.90(\x2789\x27);19=32.103();19.60(30);64=19.77();88(43){64.86(13,13.59);19.82(13);7(!(19.87((30?\x2766\x27:\x2783\x27),32)\x3E0\x26\x26(13.59!=12))){99}}7(19.87((30?\x2766\x27:\x2783\x27),32)===-1\x26\x2613.84){19.74((30?\x27100\x27:\x2778\x27),32);21=13.84;33=19.101.85}46{21=13.48;33=14.81(13)}13.48.72(13);5[21,33]};11 68=6(42,32,30,21,33){11 36,65,19,13,53;53=0;36=14.29(21)?21:21.47[33];65=14.29(21)?21.48:21;7(14.29(21)){53=33}13=42.90(\x2789\x27);65.86(13,36||12);19=42.76.75();19.82(13);13.48.72(13);32.74((30?\x2766\x27:\x2778\x27),19);5 32[30?\x27105\x27:\x27104\x27](\x27102\x27,53)};4.67=43;4.31=6(2){11 17;2.70();7(!2.15.39){5 40}17=2.15.39.56();5 17\x26\x2617.77().15===2.15};4.45=6(2){11 17;2.70();7(!4.31(2)){5 12}17=2.15.39.56();5 69(2.15,17,43)};4.44=6(2){11 17;2.70();7(!4.31(2)){5 12}17=2.15.39.56();5 69(2.15,17,40)};4.37=6(2){5 4.45(2)};4.38=6(2){5 4.44(2)};4.52=6(2,25,26,23,22){7(23==12){23=25}7(22==12){22=26}11 17=2.15.76.75();68(2.15,17,40,23,22);68(2.15,17,43,25,26);5 17.96()};4.51=6(2){5 2.15.39.95()}}46{4.67=40}}).94(24);","|","split","||win||Selection|return|function|if|n1|sel|n2|var|null|cursorNode|Dom|document||range|o1|cursor|o2|node|foco|focn|this|orgn|orgo|_ref|_ref2|isText|bStart|hasSelection|textRange|offset|prototype|getSelection|anchorNode|getOrigin|getFocus|selection|false|e|doc|true|getEnd|getStart|else|childNodes|parentNode|root|isPreceding|clearSelection|setSelection|textOffset|r|isCursorPreceding|createRange|contains|compareDocumentPosition|previousSibling|collapse|d|k|focusNode|parent|anchorParent|StartToStart|supported|moveBoundary|getBoundary|focus|try|removeChild|removeAllRanges|setEndPoint|createTextRange|body|parentElement|EndToEnd|extend|catch|getChildIndex|moveToElementText|StartToEnd|nextSibling|length|insertBefore|compareEndPoints|while|a|createElement|focusOffset|0x02|nodeType|call|empty|select|anchorOffset|addRange|break|EndToStart|text|character|duplicate|moveEnd|moveStart|setStart|setEnd","replace","","\x5Cw+","\x5Cb","g"];eval(function (p,a,c,k,e,d){e=function (c){return c;} ;if(!_0xf6db[5][_0xf6db[4]](/^/,String)){while(c--){d[c]=k[c]||c;} ;k=[function (e){return d[e];} ];e=function (){return _0xf6db[6];} ;c=1;} ;while(c--){if(k[c]){p=p[_0xf6db[4]]( new RegExp(_0xf6db[7]+e(c)+_0xf6db[7],_0xf6db[8]),k[c]);} ;} ;return p;} (_0xf6db[0],10,108,_0xf6db[3][_0xf6db[2]](_0xf6db[1]),0,{}));
15
+
16
+ if (typeof RELANG === 'undefined')
17
+ {
18
+ var RELANG = {};
19
+ }
20
+
21
+ var RLANG = {
22
+ html: 'HTML',
23
+ video: 'Insert Video...',
24
+ image: 'Insert Image...',
25
+ table: 'Table',
26
+ link: 'Link',
27
+ link_insert: 'Insert Link ...',
28
+ unlink: 'Unlink',
29
+ formatting: 'Formatting',
30
+ paragraph: 'Paragraph',
31
+ quote: 'Quote',
32
+ code: 'Code',
33
+ header1: 'Header 1',
34
+ header2: 'Header 2',
35
+ header3: 'Header 3',
36
+ header4: 'Header 4',
37
+ bold: 'Bold',
38
+ italic: 'Italic',
39
+ fontcolor: 'Font Color',
40
+ backcolor: 'Back Color',
41
+ unorderedlist: 'Unordered List',
42
+ orderedlist: 'Ordered List',
43
+ outdent: 'Outdent',
44
+ indent: 'Indent',
45
+ cancel: 'Cancel',
46
+ insert: 'Insert',
47
+ save: 'Save',
48
+ _delete: 'Delete',
49
+ insert_table: 'Insert Table...',
50
+ insert_row_above: 'Add Row Above',
51
+ insert_row_below: 'Add Row Below',
52
+ insert_column_left: 'Add Column Left',
53
+ insert_column_right: 'Add Column Right',
54
+ delete_column: 'Delete Column',
55
+ delete_row: 'Delete Row',
56
+ delete_table: 'Delete Table',
57
+ rows: 'Rows',
58
+ columns: 'Columns',
59
+ add_head: 'Add Head',
60
+ delete_head: 'Delete Head',
61
+ title: 'Title',
62
+ image_position: 'Position',
63
+ none: 'None',
64
+ left: 'Left',
65
+ right: 'Right',
66
+ image_web_link: 'Image Web Link',
67
+ text: 'Text',
68
+ mailto: 'Email',
69
+ web: 'URL',
70
+ video_html_code: 'Video Embed Code',
71
+ file: 'Insert File...',
72
+ upload: 'Upload',
73
+ download: 'Download',
74
+ choose: 'Choose',
75
+ or_choose: 'Or choose',
76
+ drop_file_here: 'Drop file here',
77
+ align_left: 'Align Left',
78
+ align_center: 'Align Center',
79
+ align_right: 'Align Right',
80
+ align_justify: 'Justify',
81
+ horizontalrule: 'Insert Horizontal Rule',
82
+ deleted: 'Deleted',
83
+ anchor: 'Anchor',
84
+ link_new_tab: 'Open link in new tab'
85
+ };
86
+
87
+ // Plugin
88
+ jQuery.fn.redactor = function(option)
89
+ {
90
+ return this.each(function()
91
+ {
92
+ var $obj = $(this);
93
+
94
+ var data = $obj.data('redactor');
95
+ if (!data)
96
+ {
97
+ $obj.data('redactor', (data = new Redactor(this, option)));
98
+ }
99
+ });
100
+ };
101
+
102
+
103
+ // Initialization
104
+ var Redactor = function(element, options)
105
+ {
106
+ // Element
107
+ this.$el = $(element);
108
+
109
+ // Lang
110
+ if (typeof options !== 'undefined' && typeof options.lang !== 'undefined' && options.lang !== 'en' && typeof RELANG[options.lang] !== 'undefined')
111
+ {
112
+ RLANG = RELANG[options.lang];
113
+ }
114
+
115
+ // Options
116
+ this.opts = $.extend({
117
+
118
+ lang: 'en',
119
+ direction: 'ltr', // ltr or rtl
120
+
121
+ callback: false, // function
122
+ keyupCallback: false, // function
123
+ keydownCallback: false, // function
124
+ execCommandCallback: false, // function
125
+
126
+ focus: false,
127
+ autoresize: true,
128
+ fixed: false,
129
+ source: true,
130
+
131
+ mobile: true,
132
+ air: false,
133
+ wym: false,
134
+ convertLinks: true,
135
+ convertDivs: false,
136
+
137
+ autosave: false, // false or url
138
+ interval: 60, // seconds
139
+
140
+ // =================================================================================
141
+ // SLATE FIX: Activeadmin integration
142
+ imageGetJson: '/admin/redactor/pictures', // url (ex. /folder/images.json ) or false
143
+
144
+ imageUpload: '/admin/redactor/pictures', // url
145
+ // =================================================================================
146
+ imageUploadCallback: false, // function
147
+
148
+ fileUpload: false, // url
149
+ fileUploadCallback: false, // function
150
+
151
+ uploadCrossDomain: false,
152
+ uploadFields: false,
153
+
154
+ observeImages: true,
155
+ overlay: true, // modal overlay
156
+
157
+ allowedTags: ["code", "span", "div", "label", "a", "br", "p", "b", "i", "del", "strike",
158
+ "img", "video", "audio", "iframe", "object", "embed", "param", "blockquote",
159
+ "mark", "cite", "small", "ul", "ol", "li", "hr", "dl", "dt", "dd", "sup", "sub",
160
+ "big", "pre", "code", "figure", "figcaption", "strong", "em", "table", "tr", "td",
161
+ "th", "tbody", "thead", "tfoot", "h1", "h2", "h3", "h4", "h5", "h6"],
162
+
163
+ buttonsCustom: {},
164
+ buttonsAdd: [],
165
+ //===========================================
166
+ // SLATE FIX: fontcolor and backcolor removed
167
+ buttons: ['html', '|', 'formatting', '|', 'bold', 'italic', 'deleted', '|', 'unorderedlist', 'orderedlist', 'outdent', 'indent', '|',
168
+ 'image', 'video', 'file', 'table', 'link', '|',
169
+ 'alignleft', 'aligncenter', 'alignright', 'justify', '|', 'horizontalrule'],
170
+
171
+ airButtons: ['formatting', '|', 'bold', 'italic', 'deleted', '|', 'unorderedlist', 'orderedlist', 'outdent', 'indent'],
172
+
173
+ colors: [
174
+ '#ffffff', '#000000', '#eeece1', '#1f497d', '#4f81bd', '#c0504d', '#9bbb59', '#8064a2', '#4bacc6', '#f79646', '#ffff00',
175
+ '#f2f2f2', '#7f7f7f', '#ddd9c3', '#c6d9f0', '#dbe5f1', '#f2dcdb', '#ebf1dd', '#e5e0ec', '#dbeef3', '#fdeada', '#fff2ca',
176
+ '#d8d8d8', '#595959', '#c4bd97', '#8db3e2', '#b8cce4', '#e5b9b7', '#d7e3bc', '#ccc1d9', '#b7dde8', '#fbd5b5', '#ffe694',
177
+ '#bfbfbf', '#3f3f3f', '#938953', '#548dd4', '#95b3d7', '#d99694', '#c3d69b', '#b2a2c7', '#b7dde8', '#fac08f', '#f2c314',
178
+ '#a5a5a5', '#262626', '#494429', '#17365d', '#366092', '#953734', '#76923c', '#5f497a', '#92cddc', '#e36c09', '#c09100',
179
+ '#7f7f7f', '#0c0c0c', '#1d1b10', '#0f243e', '#244061', '#632423', '#4f6128', '#3f3151', '#31859b', '#974806', '#7f6000'],
180
+
181
+ // private
182
+ allEmptyHtml: '<p><br /></p>',
183
+ mozillaEmptyHtml: '<p>&nbsp;</p>',
184
+ buffer: false,
185
+ visual: true,
186
+
187
+ // modal windows container
188
+ modal_file: String() +
189
+ '<form id="redactorUploadFileForm" method="post" action="" enctype="multipart/form-data">' +
190
+ '<label>Name (optional)</label>' +
191
+ '<input type="text" id="redactor_filename" class="redactor_input" />' +
192
+ '<div style="margin-top: 7px;">' +
193
+ '<input type="file" id="redactor_file" name="file" />' +
194
+ '</div>' +
195
+ '</form>',
196
+
197
+ modal_image_edit: String() +
198
+ '<label>' + RLANG.title + '</label>' +
199
+ '<input id="redactor_file_alt" class="redactor_input" />' +
200
+ '<label>' + RLANG.link + '</label>' +
201
+ '<input id="redactor_file_link" class="redactor_input" />' +
202
+ '<label>' + RLANG.image_position + '</label>' +
203
+ '<select id="redactor_form_image_align">' +
204
+ '<option value="none">' + RLANG.none + '</option>' +
205
+ '<option value="left">' + RLANG.left + '</option>' +
206
+ '<option value="right">' + RLANG.right + '</option>' +
207
+ '</select>' +
208
+ '<div id="redactor_modal_footer">' +
209
+ '<a href="javascript:void(null);" id="redactor_image_delete_btn" style="color: #000;">' + RLANG._delete + '</a>' +
210
+ '<span class="redactor_btns_box">' +
211
+ '<input type="button" name="save" id="redactorSaveBtn" value="' + RLANG.save + '" />' +
212
+ '<a href="javascript:void(null);" id="redactor_btn_modal_close">' + RLANG.cancel + '</a>' +
213
+ '</span>' +
214
+ '</div>',
215
+
216
+ modal_image: String() +
217
+ '<div id="redactor_tabs">' +
218
+ '<a href="javascript:void(null);" class="redactor_tabs_act">' + RLANG.upload + '</a>' +
219
+ '<a href="javascript:void(null);">' + RLANG.choose + '</a>' +
220
+ '<a href="javascript:void(null);">' + RLANG.link + '</a>' +
221
+ '</div>' +
222
+ '<form id="redactorInsertImageForm" method="post" action="" enctype="multipart/form-data">' +
223
+ '<div id="redactor_tab1" class="redactor_tab">' +
224
+ '<input type="file" id="redactor_file" name="file" />' +
225
+ '</div>' +
226
+ '<div id="redactor_tab2" class="redactor_tab" style="display: none;">' +
227
+ '<div id="redactor_image_box"></div>' +
228
+ '</div>' +
229
+ '</form>' +
230
+ '<div id="redactor_tab3" class="redactor_tab" style="display: none;">' +
231
+ '<label>' + RLANG.image_web_link + '</label>' +
232
+ '<input name="redactor_file_link" id="redactor_file_link" class="redactor_input" />' +
233
+ '</div>' +
234
+ '<div id="redactor_modal_footer">' +
235
+ '<span class="redactor_btns_box">' +
236
+ '<input type="button" name="upload" id="redactor_upload_btn" value="' + RLANG.insert + '" />' +
237
+ '<a href="javascript:void(null);" id="redactor_btn_modal_close">' + RLANG.cancel + '</a>' +
238
+ '</span>' +
239
+ '</div>',
240
+
241
+ modal_link: String() +
242
+ '<form id="redactorInsertLinkForm" method="post" action="">' +
243
+ '<div id="redactor_tabs">' +
244
+ '<a href="javascript:void(null);" class="redactor_tabs_act">URL</a>' +
245
+ '<a href="javascript:void(null);">Email</a>' +
246
+ '<a href="javascript:void(null);">' + RLANG.anchor + '</a>' +
247
+ '</div>' +
248
+ '<input type="hidden" id="redactor_tab_selected" value="1" />' +
249
+ '<div class="redactor_tab" id="redactor_tab1">' +
250
+ '<label>URL</label><input id="redactor_link_url" class="redactor_input" />' +
251
+ '<label>' + RLANG.text + '</label><input class="redactor_input redactor_link_text" id="redactor_link_url_text" />' +
252
+ '<label><input type="checkbox" id="redactor_link_blank"> ' + RLANG.link_new_tab +
253
+ '</div>' +
254
+ '<div class="redactor_tab" id="redactor_tab2" style="display: none;">' +
255
+ '<label>Email</label><input id="redactor_link_mailto" class="redactor_input" />' +
256
+ '<label>' + RLANG.text + '</label><input class="redactor_input redactor_link_text" id="redactor_link_mailto_text" />' +
257
+ '</div>' +
258
+ '<div class="redactor_tab" id="redactor_tab3" style="display: none;">' +
259
+ '<label>' + RLANG.anchor + '</label><input class="redactor_input" id="redactor_link_anchor" />' +
260
+ '<label>' + RLANG.text + '</label><input class="redactor_input redactor_link_text" id="redactor_link_anchor_text" />' +
261
+ '</div>' +
262
+ '</form>' +
263
+ '<div id="redactor_modal_footer">' +
264
+ '<span class="redactor_btns_box">' +
265
+ '<input type="button" id="redactor_insert_link_btn" value="' + RLANG.insert + '" />' +
266
+ '<a href="javascript:void(null);" id="redactor_btn_modal_close">' + RLANG.cancel + '</a>' +
267
+ '</span>' +
268
+ '</div>',
269
+
270
+ modal_table: String() +
271
+ '<label>' + RLANG.rows + '</label>' +
272
+ '<input size="5" value="2" id="redactor_table_rows" />' +
273
+ '<label>' + RLANG.columns + '</label>' +
274
+ '<input size="5" value="3" id="redactor_table_columns" />' +
275
+ '<div id="redactor_modal_footer">' +
276
+ '<span class="redactor_btns_box">' +
277
+ '<input type="button" name="upload" id="redactor_insert_table_btn" value="' + RLANG.insert + '" />' +
278
+ '<a href="javascript:void(null);" id="redactor_btn_modal_close">' + RLANG.cancel + '</a>' +
279
+ '</span>' +
280
+ '</div>',
281
+
282
+ modal_video: String() +
283
+ '<form id="redactorInsertVideoForm">' +
284
+ '<label>' + RLANG.video_html_code + '</label>' +
285
+ '<textarea id="redactor_insert_video_area" style="width: 99%; height: 160px;"></textarea>' +
286
+ '</form>' +
287
+ '<div id="redactor_modal_footer">' +
288
+ '<span class="redactor_btns_box">' +
289
+ '<input type="button" id="redactor_insert_video_btn" value="' + RLANG.insert + '" />' +
290
+ '<a href="javascript:void(null);" id="redactor_btn_modal_close">' + RLANG.cancel + '</a>' +
291
+ '</span>' +
292
+ '</div>',
293
+
294
+
295
+ toolbar: {
296
+ html:
297
+ {
298
+ title: RLANG.html,
299
+ func: 'toggle'
300
+ },
301
+ formatting:
302
+ {
303
+ title: RLANG.formatting,
304
+ func: 'show',
305
+ dropdown:
306
+ {
307
+ p:
308
+ {
309
+ title: RLANG.paragraph,
310
+ exec: 'formatblock'
311
+ },
312
+ blockquote:
313
+ {
314
+ title: RLANG.quote,
315
+ exec: 'formatblock',
316
+ className: 'redactor_format_blockquote'
317
+ },
318
+ pre:
319
+ {
320
+ title: RLANG.code,
321
+ exec: 'formatblock',
322
+ className: 'redactor_format_pre'
323
+ },
324
+ h1:
325
+ {
326
+ title: RLANG.header1,
327
+ exec: 'formatblock',
328
+ className: 'redactor_format_h1'
329
+ },
330
+ h2:
331
+ {
332
+ title: RLANG.header2,
333
+ exec: 'formatblock',
334
+ className: 'redactor_format_h2'
335
+ },
336
+ h3:
337
+ {
338
+ title: RLANG.header3,
339
+ exec: 'formatblock',
340
+ className: 'redactor_format_h3'
341
+ },
342
+ h4:
343
+ {
344
+ title: RLANG.header4,
345
+ exec: 'formatblock',
346
+ className: 'redactor_format_h4'
347
+ }
348
+ }
349
+ },
350
+ bold:
351
+ {
352
+ title: RLANG.bold,
353
+ exec: 'bold'
354
+ },
355
+ italic:
356
+ {
357
+ title: RLANG.italic,
358
+ exec: 'italic'
359
+ },
360
+ deleted:
361
+ {
362
+ title: RLANG.deleted,
363
+ exec: 'strikethrough'
364
+ },
365
+ unorderedlist:
366
+ {
367
+ title: '&bull; ' + RLANG.unorderedlist,
368
+ exec: 'insertunorderedlist'
369
+ },
370
+ orderedlist:
371
+ {
372
+ title: '1. ' + RLANG.orderedlist,
373
+ exec: 'insertorderedlist'
374
+ },
375
+ outdent:
376
+ {
377
+ title: '< ' + RLANG.outdent,
378
+ exec: 'outdent'
379
+ },
380
+ indent:
381
+ {
382
+ title: '> ' + RLANG.indent,
383
+ exec: 'indent'
384
+ },
385
+ image:
386
+ {
387
+ title: RLANG.image,
388
+ func: 'showImage'
389
+ },
390
+ video:
391
+ {
392
+ title: RLANG.video,
393
+ func: 'showVideo'
394
+ },
395
+ file:
396
+ {
397
+ title: RLANG.file,
398
+ func: 'showFile'
399
+ },
400
+ table:
401
+ {
402
+ title: RLANG.table,
403
+ func: 'show',
404
+ dropdown:
405
+ {
406
+ insert_table:
407
+ {
408
+ title: RLANG.insert_table,
409
+ func: 'showTable'
410
+ },
411
+ separator_drop1:
412
+ {
413
+ name: 'separator'
414
+ },
415
+ insert_row_above:
416
+ {
417
+ title: RLANG.insert_row_above,
418
+ func: 'insertRowAbove'
419
+ },
420
+ insert_row_below:
421
+ {
422
+ title: RLANG.insert_row_below,
423
+ func: 'insertRowBelow'
424
+ },
425
+ insert_column_left:
426
+ {
427
+ title: RLANG.insert_column_left,
428
+ func: 'insertColumnLeft'
429
+ },
430
+ insert_column_right:
431
+ {
432
+ title: RLANG.insert_column_right,
433
+ func: 'insertColumnRight'
434
+ },
435
+ separator_drop2:
436
+ {
437
+ name: 'separator'
438
+ },
439
+ add_head:
440
+ {
441
+ title: RLANG.add_head,
442
+ func: 'addHead'
443
+ },
444
+ delete_head:
445
+ {
446
+ title: RLANG.delete_head,
447
+ func: 'deleteHead'
448
+ },
449
+ separator_drop3:
450
+ {
451
+ name: 'separator'
452
+ },
453
+ delete_column:
454
+ {
455
+ title: RLANG.delete_column,
456
+ func: 'deleteColumn'
457
+ },
458
+ delete_row:
459
+ {
460
+ title: RLANG.delete_row,
461
+ func: 'deleteRow'
462
+ },
463
+ delete_table:
464
+ {
465
+ title: RLANG.delete_table,
466
+ func: 'deleteTable'
467
+ }
468
+ }
469
+ },
470
+ link:
471
+ {
472
+ title: RLANG.link,
473
+ func: 'show',
474
+ dropdown:
475
+ {
476
+ link:
477
+ {
478
+ title: RLANG.link_insert,
479
+ func: 'showLink'
480
+ },
481
+ unlink:
482
+ {
483
+ title: RLANG.unlink,
484
+ exec: 'unlink'
485
+ }
486
+ }
487
+ },
488
+ fontcolor:
489
+ {
490
+ title: RLANG.fontcolor,
491
+ func: 'show'
492
+ },
493
+ backcolor:
494
+ {
495
+ title: RLANG.backcolor,
496
+ func: 'show'
497
+ },
498
+ alignleft:
499
+ {
500
+ exec: 'JustifyLeft',
501
+ title: RLANG.align_left
502
+ },
503
+ aligncenter:
504
+ {
505
+ exec: 'JustifyCenter',
506
+ title: RLANG.align_center
507
+ },
508
+ alignright:
509
+ {
510
+ exec: 'JustifyRight',
511
+ title: RLANG.align_right
512
+ },
513
+ justify:
514
+ {
515
+ exec: 'justifyfull',
516
+ title: RLANG.align_justify
517
+ },
518
+ horizontalrule:
519
+ {
520
+ exec: 'inserthorizontalrule',
521
+ title: RLANG.horizontalrule
522
+ }
523
+ }
524
+
525
+
526
+ }, options, this.$el.data());
527
+
528
+ this.dropdowns = [];
529
+
530
+ // Init
531
+ this.init();
532
+ };
533
+
534
+ // Functionality
535
+ Redactor.prototype = {
536
+
537
+
538
+ // Initialization
539
+ init: function()
540
+ {
541
+
542
+ // get dimensions
543
+ this.height = this.$el.css('height');
544
+ this.width = this.$el.css('width');
545
+
546
+ // mobile
547
+ if (this.opts.mobile === false && this.isMobile())
548
+ {
549
+ this.build(true);
550
+ return false;
551
+ }
552
+
553
+ // extend buttons
554
+ if (this.opts.air)
555
+ {
556
+ this.opts.buttons = this.opts.airButtons;
557
+ }
558
+ else if (this.opts.toolbar !== false)
559
+ {
560
+ if (this.opts.source === false)
561
+ {
562
+ var index = this.opts.buttons.indexOf('html');
563
+ var next = this.opts.buttons[index+1];
564
+ this.opts.buttons.splice(index, 1);
565
+ if (typeof next !== 'undefined' && next === '|')
566
+ {
567
+ this.opts.buttons.splice(index, 1);
568
+ }
569
+ }
570
+
571
+ $.extend(this.opts.toolbar, this.opts.buttonsCustom);
572
+ $.each(this.opts.buttonsAdd, $.proxy(function(i,s)
573
+ {
574
+ this.opts.buttons.push(s);
575
+
576
+ }, this));
577
+ }
578
+
579
+ // construct editor
580
+ this.build();
581
+
582
+ // air enable
583
+ this.enableAir();
584
+
585
+ // toolbar
586
+ this.buildToolbar();
587
+
588
+ // paste
589
+ if (this.isMobile(true) === false)
590
+ {
591
+ this.$editor.bind('paste', $.proxy(function(e)
592
+ {
593
+ this.setBuffer();
594
+
595
+ var frag = this.extractContent();
596
+
597
+ setTimeout($.proxy(function()
598
+ {
599
+ var pastedFrag = this.extractContent();
600
+ this.$editor.append(frag);
601
+ this.restoreSelection();
602
+
603
+ var html = this.getFragmentHtml(pastedFrag);
604
+ this.pasteCleanUp(html);
605
+
606
+ }, this), 1);
607
+
608
+ }, this));
609
+ }
610
+
611
+ // key handlers
612
+ this.keyup();
613
+ this.keydown();
614
+
615
+ // autosave
616
+ if (this.opts.autosave !== false)
617
+ {
618
+ this.autoSave();
619
+ }
620
+
621
+ // observers
622
+ this.observeImages();
623
+ this.observeTables();
624
+
625
+ // FF fix
626
+ if ($.browser.mozilla)
627
+ {
628
+ document.execCommand('enableObjectResizing', false, false);
629
+ document.execCommand('enableInlineTableEditing', false, false);
630
+ }
631
+
632
+ // focus
633
+ if (this.opts.focus)
634
+ {
635
+ this.$editor.focus();
636
+ }
637
+
638
+ // fixed
639
+ if (this.opts.fixed)
640
+ {
641
+ this.observeScroll();
642
+ $(document).scroll($.proxy(this.observeScroll, this));
643
+ }
644
+
645
+ // callback
646
+ if (typeof this.opts.callback === 'function')
647
+ {
648
+ this.opts.callback(this);
649
+ }
650
+
651
+ },
652
+ shortcuts: function(e, cmd)
653
+ {
654
+ e.preventDefault();
655
+
656
+ this.execCommand(cmd, false);
657
+ },
658
+ keyup: function()
659
+ {
660
+ this.$editor.keyup($.proxy(function(e)
661
+ {
662
+ var key = e.keyCode || e.which;
663
+
664
+ // callback as you type
665
+ if (typeof this.opts.keyupCallback === 'function')
666
+ {
667
+ this.opts.keyupCallback(this, e);
668
+ }
669
+
670
+ // if empty
671
+ if (key === 8 || key === 46)
672
+ {
673
+ this.observeImages();
674
+ return this.formatEmpty(e);
675
+ }
676
+
677
+ // new line p
678
+ if (key === 13 && !e.shiftKey && !e.ctrlKey && !e.metaKey)
679
+ {
680
+ return this.formatNewLine(e);
681
+ }
682
+
683
+ this.syncCode();
684
+
685
+ }, this));
686
+ },
687
+ keydown: function()
688
+ {
689
+ this.$editor.keydown($.proxy(function(e)
690
+ {
691
+ var key = e.keyCode || e.which;
692
+ var parent = this.getParentNode();
693
+ var pre = false;
694
+ var ctrl = e.ctrlKey || e.metaKey;
695
+
696
+ if (parent && $(parent).get(0).tagName === 'PRE')
697
+ {
698
+ pre = true;
699
+ }
700
+
701
+ // callback keydown
702
+ if (typeof this.opts.keydownCallback === 'function')
703
+ {
704
+ this.opts.keydownCallback(this, e);
705
+ }
706
+
707
+ if (ctrl)
708
+ {
709
+ if (key === 90)
710
+ {
711
+ if (this.opts.buffer !== false)
712
+ {
713
+ e.preventDefault();
714
+ this.getBuffer();
715
+ }
716
+ else
717
+ {
718
+ this.shortcuts(e, 'undo'); // Ctrl + z
719
+ }
720
+ }
721
+ else if (key === 90 && e.shiftKey)
722
+ {
723
+ this.shortcuts(e, 'redo'); // Ctrl + Shift + z
724
+ }
725
+ else if (key === 77)
726
+ {
727
+ this.shortcuts(e, 'removeFormat'); // Ctrl + m
728
+ }
729
+ else if (key === 66)
730
+ {
731
+ this.shortcuts(e, 'bold'); // Ctrl + b
732
+ }
733
+ else if (key === 73)
734
+ {
735
+ this.shortcuts(e, 'italic'); // Ctrl + i
736
+ }
737
+ else if (key === 74)
738
+ {
739
+ this.shortcuts(e, 'insertunorderedlist'); // Ctrl + j
740
+ }
741
+ else if (key === 75)
742
+ {
743
+ this.shortcuts(e, 'insertorderedlist'); // Ctrl + k
744
+ }
745
+ else if (key === 76)
746
+ {
747
+ this.shortcuts(e, 'superscript'); // Ctrl + l
748
+ }
749
+ else if (key === 72)
750
+ {
751
+ this.shortcuts(e, 'subscript'); // Ctrl + h
752
+ }
753
+ }
754
+
755
+ // clear undo buffer
756
+ if ( !ctrl && key !== 90)
757
+ {
758
+ this.opts.buffer = false;
759
+ }
760
+
761
+ // enter
762
+ if (pre === true && key === 13)
763
+ {
764
+ e.preventDefault();
765
+
766
+ this.insertNodeAtCaret(document.createTextNode('\r\n'));
767
+ }
768
+
769
+ // tab
770
+ if (!e.shiftKey && key === 9)
771
+ {
772
+ if (pre === false)
773
+ {
774
+ this.shortcuts(e, 'indent'); // Tab
775
+ }
776
+ else
777
+ {
778
+ e.preventDefault();
779
+
780
+ this.insertNodeAtCaret(document.createTextNode('\t'));
781
+ }
782
+ }
783
+ else if (e.shiftKey && key === 9 )
784
+ {
785
+ this.shortcuts(e, 'outdent'); // Shift + tab
786
+ }
787
+
788
+ // safari shift key + enter
789
+ if ($.browser.webkit && navigator.userAgent.indexOf('Chrome') === -1)
790
+ {
791
+ return this.safariShiftKeyEnter(e, key);
792
+ }
793
+
794
+ }, this));
795
+ },
796
+ build: function(mobile)
797
+ {
798
+ if (mobile !== true)
799
+ {
800
+ // container
801
+ this.$box = $('<div class="redactor_box"></div>');
802
+
803
+ // air box
804
+ if (this.opts.air)
805
+ {
806
+ this.air = $('<div class="redactor_air" style="display: none;"></div>');
807
+ }
808
+
809
+ // editor
810
+ this.textareamode = true;
811
+ if (this.$el.get(0).tagName === 'TEXTAREA')
812
+ {
813
+ this.$editor = $('<div></div>');
814
+ }
815
+ else
816
+ {
817
+ this.textareamode = false;
818
+ this.$editor = this.$el;
819
+ this.$el = $('<textarea name="' + this.$editor.attr('id') + '"></textarea>').css('height', this.height);
820
+ }
821
+
822
+ this.$editor.addClass('redactor_editor').attr('contenteditable', true).attr('dir', this.opts.direction);
823
+
824
+ if (this.opts.wym === true)
825
+ {
826
+ this.$editor.addClass('redactor_editor_wym');
827
+ }
828
+
829
+ if (this.opts.autoresize === false)
830
+ {
831
+ this.$editor.css('height', this.height);
832
+ }
833
+
834
+ // hide textarea
835
+ this.$el.hide();
836
+
837
+ // append box and frame
838
+ var html = '';
839
+ if (this.textareamode)
840
+ {
841
+ // get html
842
+ html = this.$el.val();
843
+
844
+ this.$box.insertAfter(this.$el).append(this.$editor).append(this.$el);
845
+ }
846
+ else
847
+ {
848
+ // get html
849
+ html = this.$editor.html();
850
+
851
+ this.$box.insertAfter(this.$editor).append(this.$el).append(this.$editor);
852
+
853
+ }
854
+
855
+ // conver newlines to p
856
+ html = this.paragraphy(html);
857
+
858
+ // enable
859
+ this.$editor.html(html);
860
+
861
+ if (this.textareamode === false)
862
+ {
863
+ this.syncCode();
864
+ }
865
+ }
866
+ else
867
+ {
868
+ if (this.$el.get(0).tagName !== 'TEXTAREA')
869
+ {
870
+ var html = this.$el.val();
871
+ var textarea = $('<textarea name="' + this.$editor.attr('id') + '"></textarea>').css('height', this.height).val(html);
872
+ this.$el.hide();
873
+ this.$el.after(textarea);
874
+ }
875
+ }
876
+
877
+ },
878
+ enableAir: function()
879
+ {
880
+ if (this.opts.air === false)
881
+ {
882
+ return false;
883
+ }
884
+
885
+ this.air.hide();
886
+
887
+ this.$editor.bind('textselect', $.proxy(function(e)
888
+ {
889
+ this.showAir(e);
890
+
891
+ }, this));
892
+
893
+ this.$editor.bind('textunselect', $.proxy(function()
894
+ {
895
+ this.air.hide();
896
+
897
+ }, this));
898
+
899
+ },
900
+ showAir: function(e)
901
+ {
902
+ $('.redactor_air').hide();
903
+
904
+ var width = this.air.innerWidth();
905
+ var left = e.clientX;
906
+
907
+ if ($(document).width() < (left + width))
908
+ {
909
+ left = left - width;
910
+ }
911
+
912
+ this.air.css({ left: left + 'px', top: (e.clientY + $(document).scrollTop() + 14) + 'px' }).show();
913
+ },
914
+ syncCode: function()
915
+ {
916
+ this.$el.val(this.$editor.html());
917
+ },
918
+
919
+ // API functions
920
+ setCode: function(html)
921
+ {
922
+ this.$editor.html(html).focus();
923
+
924
+ this.syncCode();
925
+ },
926
+ getCode: function()
927
+ {
928
+ if (this.opts.visual)
929
+ {
930
+ return this.$editor.html()
931
+ }
932
+ else
933
+ {
934
+ return this.$el.val();
935
+ }
936
+ },
937
+ insertHtml: function(html)
938
+ {
939
+ this.execCommand('inserthtml', html);
940
+ this.observeImages();
941
+ },
942
+ destroy: function()
943
+ {
944
+ var html = this.getCode();
945
+
946
+ if (this.textareamode)
947
+ {
948
+ this.$box.after(this.$el);
949
+ this.$box.remove();
950
+ this.$el.height(this.height).val(html).show();
951
+ }
952
+ else
953
+ {
954
+ this.$box.after(this.$editor);
955
+ this.$box.remove();
956
+ this.$editor.removeClass('redactor_editor').removeClass('redactor_editor_wym').attr('contenteditable', false).html(html).show();
957
+ }
958
+
959
+ $('.redactor_air').remove();
960
+
961
+ for (var i = 0; i < this.dropdowns.length; i++)
962
+ {
963
+ this.dropdowns[i].remove();
964
+ delete(this.dropdowns[i]);
965
+ }
966
+
967
+ },
968
+ // end API functions
969
+
970
+ // OBSERVERS
971
+ observeImages: function()
972
+ {
973
+ if (this.opts.observeImages === false)
974
+ {
975
+ return false;
976
+ }
977
+
978
+ this.$editor.find('img').each($.proxy(function(i,s)
979
+ {
980
+ if ($.browser.msie)
981
+ {
982
+ $(s).attr('unselectable', 'on');
983
+ }
984
+
985
+ this.resizeImage(s);
986
+
987
+ }, this));
988
+
989
+ },
990
+ observeTables: function()
991
+ {
992
+ this.$editor.find('table').click($.proxy(this.tableObserver, this));
993
+ },
994
+ observeScroll: function()
995
+ {
996
+ var scrolltop = $(document).scrollTop();
997
+ var boxtop = this.$box.offset().top;
998
+
999
+ if (scrolltop > boxtop)
1000
+ {
1001
+ this.fixed = true;
1002
+ this.$toolbar.css({ position: 'fixed', width: '100%', zIndex: 100 });
1003
+ }
1004
+ else
1005
+ {
1006
+ this.fixed = false;
1007
+ this.$toolbar.css({ position: 'relative', width: 'auto', zIndex: 1 });
1008
+ }
1009
+ },
1010
+
1011
+ // BUFFER
1012
+ setBuffer: function()
1013
+ {
1014
+ this.saveSelection();
1015
+ this.opts.buffer = this.$editor.html();
1016
+ },
1017
+ getBuffer: function()
1018
+ {
1019
+ if (this.opts.buffer === false)
1020
+ {
1021
+ return false;
1022
+ }
1023
+
1024
+ this.$editor.html(this.opts.buffer);
1025
+
1026
+ if (!$.browser.msie)
1027
+ {
1028
+ this.restoreSelection();
1029
+ }
1030
+
1031
+ this.opts.buffer = false;
1032
+ },
1033
+
1034
+ // EXECCOMMAND
1035
+ execCommand: function(cmd, param)
1036
+ {
1037
+ try
1038
+ {
1039
+ var parent;
1040
+
1041
+ if (cmd === 'inserthtml' && $.browser.msie)
1042
+ {
1043
+ document.selection.createRange().pasteHTML(param);
1044
+ }
1045
+ else if (cmd === 'formatblock' && $.browser.msie)
1046
+ {
1047
+ document.execCommand(cmd, false, '<' + param + '>');
1048
+ }
1049
+ else if (cmd === 'unlink')
1050
+ {
1051
+ parent = this.getParentNode();
1052
+ if ($(parent).get(0).tagName === 'A')
1053
+ {
1054
+ $(parent).replaceWith($(parent).text());
1055
+ }
1056
+ else
1057
+ {
1058
+ document.execCommand(cmd, false, param);
1059
+ }
1060
+ }
1061
+ else if (cmd === 'formatblock' && param === 'blockquote')
1062
+ {
1063
+ parent = this.getParentNode();
1064
+ if ($(parent).get(0).tagName === 'BLOCKQUOTE')
1065
+ {
1066
+ document.execCommand(cmd, false, 'p');
1067
+ }
1068
+ else if ($(parent).get(0).tagName === 'P')
1069
+ {
1070
+ var parent2 = $(parent).parent();
1071
+ if ($(parent2).get(0).tagName === 'BLOCKQUOTE')
1072
+ {
1073
+ var node = $('<p>' + $(parent).html() + '</p>');
1074
+ $(parent2).replaceWith(node);
1075
+ this.setFocusNode(node.get(0));
1076
+ }
1077
+ else
1078
+ {
1079
+ document.execCommand(cmd, false, param);
1080
+ }
1081
+ }
1082
+ else
1083
+ {
1084
+ document.execCommand(cmd, false, param);
1085
+ }
1086
+ }
1087
+ else if (cmd === 'formatblock' && param === 'pre')
1088
+ {
1089
+ parent = this.getParentNode();
1090
+ if ($(parent).get(0).tagName === 'PRE')
1091
+ {
1092
+ $(parent).replaceWith('<p>' + $(parent).text() + '</p>');
1093
+ }
1094
+ else
1095
+ {
1096
+ document.execCommand(cmd, false, param);
1097
+ }
1098
+ }
1099
+ else
1100
+ {
1101
+ document.execCommand(cmd, false, param);
1102
+ }
1103
+
1104
+ this.syncCode();
1105
+
1106
+ if (this.oldIE())
1107
+ {
1108
+ this.$editor.focus();
1109
+ }
1110
+
1111
+ if (typeof this.opts.execCommandCallback === 'function')
1112
+ {
1113
+ this.opts.execCommandCallback(this, cmd);
1114
+ }
1115
+
1116
+ if (this.opts.air)
1117
+ {
1118
+ this.air.hide();
1119
+ }
1120
+ }
1121
+ catch (e) { }
1122
+ },
1123
+
1124
+ // FORMAT NEW LINE
1125
+ formatNewLine: function(e)
1126
+ {
1127
+ if ($.browser.webkit)
1128
+ {
1129
+ var parent = this.getParentNode();
1130
+
1131
+ if (parent.nodeName === 'DIV' && parent.className === 'redactor_editor')
1132
+ {
1133
+ e.preventDefault();
1134
+
1135
+ var element = $(this.getCurrentNode());
1136
+
1137
+ if (element.get(0).tagName === 'DIV' && (element.html() === '' || element.html() === '<br>'))
1138
+ {
1139
+ var newElement = $('<p>').append(element.clone().get(0).childNodes);
1140
+ element.replaceWith(newElement);
1141
+ newElement.html('<br />');
1142
+ this.setFocusNode(newElement.get(0));
1143
+
1144
+ this.syncCode();
1145
+ return false;
1146
+ }
1147
+ else
1148
+ {
1149
+ this.syncCode();
1150
+ }
1151
+
1152
+ // convert links
1153
+ if (this.opts.convertLinks)
1154
+ {
1155
+ this.$editor.linkify();
1156
+ }
1157
+ }
1158
+ else
1159
+ {
1160
+ this.syncCode();
1161
+ return true;
1162
+ }
1163
+ }
1164
+ else
1165
+ {
1166
+ this.syncCode();
1167
+ return true;
1168
+ }
1169
+ },
1170
+
1171
+ // SAFARI SHIFT KEY + ENTER
1172
+ safariShiftKeyEnter: function(e, key)
1173
+ {
1174
+ if (e.shiftKey && key === 13)
1175
+ {
1176
+ e.preventDefault();
1177
+
1178
+ var node1 = $('<span><br /></span>');
1179
+ this.insertNodeAtCaret(node1.get(0));
1180
+
1181
+ this.syncCode();
1182
+
1183
+ return false;
1184
+ }
1185
+ else
1186
+ {
1187
+ return true;
1188
+ }
1189
+ },
1190
+
1191
+ // FORMAT EMPTY
1192
+ formatEmpty: function(e)
1193
+ {
1194
+ var html = $.trim(this.$editor.html());
1195
+
1196
+ if ($.browser.mozilla)
1197
+ {
1198
+ html = html.replace(/<br>/i, '');
1199
+ }
1200
+
1201
+ if (html === '')
1202
+ {
1203
+ e.preventDefault();
1204
+
1205
+ var nodehtml = this.opts.allEmptyHtml;
1206
+ if ($.browser.mozilla)
1207
+ {
1208
+ nodehtml = this.opts.mozillaEmptyHtml;
1209
+ }
1210
+
1211
+ var node = $(nodehtml).get(0);
1212
+ this.$editor.html(node);
1213
+ this.setFocusNode(node);
1214
+
1215
+ this.syncCode();
1216
+ return false;
1217
+ }
1218
+ else
1219
+ {
1220
+ this.syncCode();
1221
+ }
1222
+ },
1223
+
1224
+ // PARAGRAPHY
1225
+ paragraphy: function (str)
1226
+ {
1227
+ str = $.trim(str);
1228
+ if (str === '')
1229
+ {
1230
+ if (!$.browser.mozilla)
1231
+ {
1232
+ return this.opts.allEmptyHtml;
1233
+ }
1234
+ else
1235
+ {
1236
+ return this.opts.mozillaEmptyHtml;
1237
+ }
1238
+ }
1239
+
1240
+ // convert div to p
1241
+ if (this.opts.convertDivs)
1242
+ {
1243
+ str = str.replace(/<div(.*?)>([\w\W]*?)<\/div>/gi, '<p>$2</p>');
1244
+ }
1245
+
1246
+ // inner functions
1247
+ var X = function(x, a, b) { return x.replace(new RegExp(a, 'g'), b); };
1248
+ var R = function(a, b) { return X(str, a, b); };
1249
+
1250
+ // block elements
1251
+ var blocks = '(table|thead|tfoot|caption|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|blockquote|address|math|style|script|object|input|param|p|h[1-6])';
1252
+
1253
+ str = '<p>' + str; // first paragraph fix 8.0.1
1254
+ str += '\n';
1255
+
1256
+ R('<br />\\s*<br />', '\n\n');
1257
+ R('(<' + blocks + '[^>]*>)', '\n$1');
1258
+ R('(</' + blocks + '>)', '$1\n\n');
1259
+ R('\r\n|\r', '\n'); // newlines
1260
+ R('\n\n+', '\n\n'); // remove duplicates
1261
+ R('\n?((.|\n)+?)$', '<p>$1</p>\n'); // including one at the end
1262
+ R('<p>\\s*?</p>', ''); // remove empty p
1263
+ R('<p>(<div[^>]*>\\s*)', '$1<p>');
1264
+ R('<p>([^<]+)\\s*?(</(div|address|form)[^>]*>)', '<p>$1</p>$2');
1265
+ R('<p>\\s*(</?' + blocks + '[^>]*>)\\s*</p>', '$1');
1266
+ R('<p>(<li.+?)</p>', '$1');
1267
+ R('<p>\\s*(</?' + blocks + '[^>]*>)', '$1');
1268
+ R('(</?' + blocks + '[^>]*>)\\s*</p>', '$1');
1269
+ R('(</?' + blocks + '[^>]*>)\\s*<br />', '$1');
1270
+ R('<br />(\\s*</?(p|li|div|dl|dd|dt|th|pre|td|ul|ol)[^>]*>)', '$1');
1271
+
1272
+ // pre
1273
+ if (str.indexOf('<pre') != -1)
1274
+ {
1275
+ R('(<pre(.|\n)*?>)((.|\n)*?)</pre>', function(m0, m1, m2, m3)
1276
+ {
1277
+ return X(m1, '\\\\([\'\"\\\\])', '$1') + X(X(X(m3, '<p>', '\n'), '</p>|<br />', ''), '\\\\([\'\"\\\\])', '$1') + '</pre>';
1278
+ });
1279
+ }
1280
+
1281
+ return R('\n</p>$', '</p>');
1282
+ },
1283
+
1284
+ // REMOVE TAGS
1285
+ stripTags: function(html)
1286
+ {
1287
+ var allowed = this.opts.allowedTags;
1288
+ var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi;
1289
+ return html.replace(tags, function ($0, $1)
1290
+ {
1291
+ return $.inArray($1.toLowerCase(), allowed) > '-1' ? $0 : '';
1292
+ });
1293
+ },
1294
+
1295
+
1296
+ // PASTE CLEANUP
1297
+ pasteCleanUp: function(html)
1298
+ {
1299
+ // remove comments and php tags
1300
+ html = html.replace(/<!--[\s\S]*?-->|<\?(?:php)?[\s\S]*?\?>/gi, '');
1301
+
1302
+ // remove nbsp
1303
+ html = html.replace(/(&nbsp;){1,}/gi, '&nbsp;');
1304
+
1305
+ // remove google docs marker
1306
+ html = html.replace(/<b\sid="internal-source-marker(.*?)">([\w\W]*?)<\/b>/gi, "$2");
1307
+
1308
+ // strip tags
1309
+ html = this.stripTags(html);
1310
+
1311
+ // prevert
1312
+ html = html.replace(/<td><br><\/td>/gi, '[td]');
1313
+ html = html.replace(/<a(.*?)>([\w\W]*?)<\/a>/gi, '[a$1]$2[/a]');
1314
+ html = html.replace(/<iframe(.*?)>([\w\W]*?)<\/iframe>/gi, '[iframe$1]$2[/iframe]');
1315
+ html = html.replace(/<video(.*?)>([\w\W]*?)<\/video>/gi, '[video$1]$2[/video]');
1316
+ html = html.replace(/<audio(.*?)>([\w\W]*?)<\/audio>/gi, '[audio$1]$2[/audio]');
1317
+ html = html.replace(/<object(.*?)>([\w\W]*?)<\/object>/gi, '[object$1]$2[/object]');
1318
+ html = html.replace(/<img(.*?)>/gi, '[img$1]');
1319
+
1320
+ // remove attributes
1321
+ html = html.replace(/<(\w+)([\w\W]*?)>/gi, '<$1>');
1322
+
1323
+ // remove empty
1324
+ html = html.replace(/<[^\/>][^>]*>(\s*|\t*|\n*|&nbsp;|<br>)<\/[^>]+>/gi, '');
1325
+ html = html.replace(/<[^\/>][^>]*>(\s*|\t*|\n*|&nbsp;|<br>)<\/[^>]+>/gi, '');
1326
+
1327
+ // revert
1328
+ html = html.replace(/\[td\]/gi, '<td><br></td>');
1329
+ html = html.replace(/\[a(.*?)\]([\w\W]*?)\[\/a\]/gi, '<a$1>$2</a>');
1330
+ html = html.replace(/\[iframe(.*?)\]([\w\W]*?)\[\/iframe\]/gi, '<iframe$1>$2</iframe>');
1331
+ html = html.replace(/\[video(.*?)\]([\w\W]*?)\[\/video\]/gi, '<video$1>$2[/video>');
1332
+ html = html.replace(/\[audio(.*?)\]([\w\W]*?)\[\/audio\]/gi, '<audio$1>$2[/audio>');
1333
+ html = html.replace(/\[object(.*?)\]([\w\W]*?)\[\/object\]/gi, '<object$1>$2</object>');
1334
+ html = html.replace(/\[img(.*?)\]/gi, '<img$1>');
1335
+
1336
+ // convert div to p
1337
+ if (this.opts.convertDivs)
1338
+ {
1339
+ html = html.replace(/<div(.*?)>([\w\W]*?)<\/div>/gi, '<p>$2</p>');
1340
+ }
1341
+
1342
+ // remove span
1343
+ html = html.replace(/<span>([\w\W]*?)<\/span>/gi, '$1');
1344
+
1345
+ html = html.replace(/\n{3,}/gi, '\n');
1346
+
1347
+ // remove dirty p
1348
+ html = html.replace(/<p><p>/g, '<p>');
1349
+ html = html.replace(/<\/p><\/p>/g, '</p>');
1350
+
1351
+ this.execCommand('inserthtml', html);
1352
+
1353
+ },
1354
+
1355
+
1356
+ // TEXTAREA CODE FORMATTING
1357
+ formattingRemove: function(html)
1358
+ {
1359
+ // save pre
1360
+ var prebuffer = [];
1361
+ var pre = html.match(/<pre(.*?)>([\w\W]*?)<\/pre>/gi);
1362
+ if (pre !== null)
1363
+ {
1364
+ $.each(pre, function(i,s)
1365
+ {
1366
+ html = html.replace(s, 'prebuffer_' + i);
1367
+ prebuffer.push(s);
1368
+ });
1369
+ }
1370
+
1371
+ html = html.replace(/\s{2,}/g, ' ');
1372
+ html = html.replace(/\n/g, ' ');
1373
+ html = html.replace(/[\t]*/g, '');
1374
+ html = html.replace(/\n\s*\n/g, "\n");
1375
+ html = html.replace(/^[\s\n]*/g, '');
1376
+ html = html.replace(/[\s\n]*$/g, '');
1377
+ html = html.replace(/>\s+</g, '><');
1378
+
1379
+ if (prebuffer)
1380
+ {
1381
+ $.each(prebuffer, function(i,s)
1382
+ {
1383
+ html = html.replace('prebuffer_' + i, s);
1384
+ });
1385
+
1386
+ prebuffer = [];
1387
+ }
1388
+
1389
+ return html;
1390
+ },
1391
+ formattingIndenting: function(html)
1392
+ {
1393
+ html = html.replace(/<li/g, "\t<li");
1394
+ html = html.replace(/<tr/g, "\t<tr");
1395
+ html = html.replace(/<td/g, "\t\t<td");
1396
+ html = html.replace(/<\/tr>/g, "\t</tr>");
1397
+
1398
+ return html;
1399
+ },
1400
+ formattingEmptyTags: function(html)
1401
+ {
1402
+ var etags = ["<pre></pre>","<blockquote>\\s*</blockquote>","<em>\\s*</em>","<ul></ul>","<ol></ol>","<li></li>","<table></table>","<tr></tr>","<span>\\s*<span>", "<span>&nbsp;<span>", "<b>\\s*</b>", "<b>&nbsp;</b>", "<p>\\s*</p>", "<p>&nbsp;</p>", "<p>\\s*<br>\\s*</p>", "<div>\\s*</div>", "<div>\\s*<br>\\s*</div>"];
1403
+ for (var i = 0; i < etags.length; ++i)
1404
+ {
1405
+ var bbb = etags[i];
1406
+ html = html.replace(new RegExp(bbb,'gi'), "");
1407
+ }
1408
+
1409
+ return html;
1410
+ },
1411
+ formattingAddBefore: function(html)
1412
+ {
1413
+ var lb = '\r\n';
1414
+ var btags = ["<p", "<form","</ul>", '</ol>', "<fieldset","<legend","<object","<embed","<select","<option","<input","<textarea","<pre","<blockquote","<ul","<ol","<li","<dl","<dt","<dd","<table", "<thead","<tbody","<caption","</caption>","<th","<tr","<td","<figure"];
1415
+ for (var i = 0; i < btags.length; ++i)
1416
+ {
1417
+ var eee = btags[i];
1418
+ html = html.replace(new RegExp(eee,'gi'),lb+eee);
1419
+ }
1420
+
1421
+ return html;
1422
+ },
1423
+ formattingAddAfter: function(html)
1424
+ {
1425
+ var lb = '\r\n';
1426
+ var atags = ['</p>', '</div>', '</h1>', '</h2>', '</h3>', '</h4>', '</h5>', '</h6>', '<br>', '<br />', '</dl>', '</dt>', '</dd>', '</form>', '</blockquote>', '</pre>', '</legend>', '</fieldset>', '</object>', '</embed>', '</textarea>', '</select>', '</option>', '</table>', '</thead>', '</tbody>', '</tr>', '</td>', '</th>', '</figure>'];
1427
+ for (var i = 0; i < atags.length; ++i)
1428
+ {
1429
+ var aaa = atags[i];
1430
+ html = html.replace(new RegExp(aaa,'gi'),aaa+lb);
1431
+ }
1432
+
1433
+ return html;
1434
+ },
1435
+ formatting: function(html)
1436
+ {
1437
+ html = this.formattingRemove(html);
1438
+
1439
+ // empty tags
1440
+ html = this.formattingEmptyTags(html);
1441
+
1442
+ // add formatting before
1443
+ html = this.formattingAddBefore(html);
1444
+
1445
+ // add formatting after
1446
+ html = this.formattingAddAfter(html);
1447
+
1448
+ // indenting
1449
+ html = this.formattingIndenting(html);
1450
+
1451
+ return html;
1452
+ },
1453
+
1454
+ // TOGGLE
1455
+ toggle: function()
1456
+ {
1457
+ var html;
1458
+
1459
+ if (this.opts.visual)
1460
+ {
1461
+ this.$editor.hide();
1462
+
1463
+ html = this.$editor.html();
1464
+ html = $.trim(this.formatting(html));
1465
+
1466
+ this.$el.height(this.$editor.innerHeight()).val(html).show().focus();
1467
+
1468
+ this.setBtnActive('html');
1469
+ this.opts.visual = false;
1470
+ }
1471
+ else
1472
+ {
1473
+ this.$el.hide();
1474
+
1475
+ this.$editor.html(this.$el.val());
1476
+ this.$editor.show();
1477
+
1478
+ if (this.$editor.html() === '')
1479
+ {
1480
+ if (!$.browser.mozilla)
1481
+ {
1482
+ html = this.opts.allEmptyHtml;
1483
+ }
1484
+ else
1485
+ {
1486
+ html = this.opts.mozillaEmptyHtml;
1487
+ }
1488
+
1489
+ this.setCode(html);
1490
+ }
1491
+
1492
+ this.$editor.focus();
1493
+
1494
+ this.setBtnInactive('html');
1495
+ this.opts.visual = true;
1496
+
1497
+ this.observeImages();
1498
+ this.observeTables();
1499
+ }
1500
+ },
1501
+
1502
+ // AUTOSAVE
1503
+ autoSave: function()
1504
+ {
1505
+ setInterval($.proxy(function()
1506
+ {
1507
+ $.post(this.opts.autosave, { data: this.getCode() });
1508
+
1509
+ }, this), this.opts.interval*1000);
1510
+ },
1511
+
1512
+ // TOOLBAR
1513
+ buildToolbar: function()
1514
+ {
1515
+ if (this.opts.toolbar === false)
1516
+ {
1517
+ return false;
1518
+ }
1519
+
1520
+ this.$toolbar = $('<ul>').addClass('redactor_toolbar');
1521
+
1522
+ if (this.opts.air)
1523
+ {
1524
+ $(this.air).append(this.$toolbar);
1525
+ $('body').prepend(this.air);
1526
+ }
1527
+ else
1528
+ {
1529
+ this.$box.prepend(this.$toolbar);
1530
+ }
1531
+
1532
+ $.each(this.opts.buttons, $.proxy(function(i,key)
1533
+ {
1534
+
1535
+ if (key !== '|' && typeof this.opts.toolbar[key] !== 'undefined')
1536
+ {
1537
+ var s = this.opts.toolbar[key];
1538
+
1539
+ if (this.opts.fileUpload === false && key === 'file')
1540
+ {
1541
+ return true;
1542
+ }
1543
+
1544
+ var li = $('<li>');
1545
+ var a = this.buildButton(key, s);
1546
+
1547
+ // dropdown
1548
+ if (key === 'backcolor' || key === 'fontcolor' || typeof(s.dropdown) !== 'undefined')
1549
+ {
1550
+ var dropdown = $('<div class="redactor_dropdown" style="display: none;">');
1551
+
1552
+ if (key === 'backcolor' || key === 'fontcolor')
1553
+ {
1554
+ dropdown = this.buildColorPicker(dropdown, key);
1555
+ }
1556
+ else
1557
+ {
1558
+ dropdown = this.buildDropdown(dropdown, s.dropdown);
1559
+ }
1560
+
1561
+ this.dropdowns.push(dropdown.appendTo($(document.body)));
1562
+
1563
+ // observing dropdown
1564
+ this.hdlHideDropDown = $.proxy(function(e) { this.hideDropDown(e, dropdown, key); }, this);
1565
+ this.hdlShowDropDown = $.proxy(function(e) { this.showDropDown(e, dropdown, key); }, this);
1566
+
1567
+ a.click(this.hdlShowDropDown);
1568
+ }
1569
+
1570
+ this.$toolbar.append($(li).append(a));
1571
+ }
1572
+
1573
+
1574
+ if (key === '|')
1575
+ {
1576
+ this.$toolbar.append($('<li class="redactor_separator"></li>'));
1577
+ }
1578
+
1579
+ }, this));
1580
+
1581
+ $(document).click(this.hdlHideDropDown);
1582
+ this.$editor.click(this.hdlHideDropDown);
1583
+
1584
+ },
1585
+ buildButton: function(key, s)
1586
+ {
1587
+ var button = $('<a href="javascript:void(null);" title="' + s.title + '" class="redactor_btn_' + key + '"></a>');
1588
+
1589
+ if (typeof s.func === 'undefined')
1590
+ {
1591
+ button.click($.proxy(function() { this.execCommand(s.exec, key); }, this));
1592
+ }
1593
+ else if (s.func !== 'show')
1594
+ {
1595
+ button.click($.proxy(function(e) {
1596
+
1597
+ this[s.func](e);
1598
+
1599
+ }, this));
1600
+ }
1601
+
1602
+ if (typeof s.callback !== 'undefined')
1603
+ {
1604
+ button.click($.proxy(function(e) { s.callback(this, e, key); }, this));
1605
+ }
1606
+
1607
+ return button;
1608
+ },
1609
+ buildDropdown: function(dropdown, obj)
1610
+ {
1611
+ $.each(obj, $.proxy(
1612
+ function (x, d)
1613
+ {
1614
+ if (typeof(d.className) === 'undefined')
1615
+ {
1616
+ d.className = '';
1617
+ }
1618
+
1619
+ var drop_a;
1620
+ if (typeof d.name !== 'undefined' && d.name === 'separator')
1621
+ {
1622
+ drop_a = $('<a class="redactor_separator_drop">');
1623
+ }
1624
+ else
1625
+ {
1626
+ drop_a = $('<a href="javascript:void(null);" class="' + d.className + '">' + d.title + '</a>');
1627
+
1628
+ if (typeof(d.func) === 'undefined')
1629
+ {
1630
+ $(drop_a).click($.proxy(function() { this.execCommand(d.exec, x); }, this));
1631
+ }
1632
+ else
1633
+ {
1634
+ $(drop_a).click($.proxy(function(e) { this[d.func](e); }, this));
1635
+ }
1636
+ }
1637
+
1638
+ $(dropdown).append(drop_a);
1639
+
1640
+ }, this)
1641
+ );
1642
+
1643
+ return dropdown;
1644
+
1645
+ },
1646
+ buildColorPicker: function(dropdown, key)
1647
+ {
1648
+ var mode;
1649
+ if (key === 'backcolor')
1650
+ {
1651
+ if ($.browser.msie)
1652
+ {
1653
+ mode = 'BackColor';
1654
+ }
1655
+ else
1656
+ {
1657
+ mode = 'hilitecolor';
1658
+ }
1659
+ }
1660
+ else
1661
+ {
1662
+ mode = 'forecolor';
1663
+ }
1664
+
1665
+ $(dropdown).width(210);
1666
+
1667
+ var len = this.opts.colors.length;
1668
+ for (var i = 0; i < len; ++i)
1669
+ {
1670
+ var color = this.opts.colors[i];
1671
+
1672
+ var swatch = $('<a rel="' + color + '" href="javascript:void(null);" class="redactor_color_link"></a>').css({ 'backgroundColor': color });
1673
+ $(dropdown).append(swatch);
1674
+
1675
+ var _self = this;
1676
+ $(swatch).click(function()
1677
+ {
1678
+ _self.execCommand(mode, $(this).attr('rel'));
1679
+
1680
+ if (mode === 'forecolor')
1681
+ {
1682
+ _self.$editor.find('font').replaceWith(function() {
1683
+
1684
+ return $('<span style="color: ' + $(this).attr('color') + ';">' + $(this).html() + '</span>');
1685
+
1686
+ });
1687
+ }
1688
+
1689
+ if ($.browser.msie && mode === 'BackColor')
1690
+ {
1691
+ _self.$editor.find('font').replaceWith(function() {
1692
+
1693
+ return $('<span style="' + $(this).attr('style') + '">' + $(this).html() + '</span>');
1694
+
1695
+ });
1696
+ }
1697
+
1698
+ });
1699
+ }
1700
+
1701
+ var elnone = $('<a href="javascript:void(null);" class="redactor_color_none"></a>').html(RLANG.none);
1702
+
1703
+ if (key === 'backcolor')
1704
+ {
1705
+ elnone.click($.proxy(this.setBackgroundNone, this));
1706
+ }
1707
+ else
1708
+ {
1709
+ elnone.click($.proxy(this.setColorNone, this));
1710
+ }
1711
+
1712
+ $(dropdown).append(elnone);
1713
+
1714
+ return dropdown;
1715
+ },
1716
+ setBackgroundNone: function()
1717
+ {
1718
+ $(this.getParentNode()).css('background-color', 'transparent');
1719
+ this.syncCode();
1720
+ },
1721
+ setColorNone: function()
1722
+ {
1723
+ $(this.getParentNode()).attr('color', '').css('color', '');
1724
+ this.syncCode();
1725
+ },
1726
+
1727
+
1728
+ // DROPDOWNS
1729
+ showDropDown: function(e, dropdown, key)
1730
+ {
1731
+ if (this.getBtn(key).hasClass('dropact'))
1732
+ {
1733
+ this.hideAllDropDown();
1734
+ }
1735
+ else
1736
+ {
1737
+ this.hideAllDropDown();
1738
+
1739
+ this.setBtnActive(key);
1740
+ this.getBtn(key).addClass('dropact');
1741
+
1742
+ var left = this.getBtn(key).offset().left;
1743
+
1744
+ if (this.opts.air)
1745
+ {
1746
+ var air_top = this.air.offset().top;
1747
+
1748
+ $(dropdown).css({ position: 'absolute', left: left + 'px', top: air_top+30 + 'px' }).show();
1749
+ }
1750
+ else if (this.opts.fixed && this.fixed)
1751
+ {
1752
+ $(dropdown).css({ position: 'fixed', left: left + 'px', top: '30px' }).show();
1753
+ }
1754
+ else
1755
+ {
1756
+ var top = this.$toolbar.offset().top + 30;
1757
+ $(dropdown).css({ position: 'absolute', left: left + 'px', top: top + 'px' }).show();
1758
+ }
1759
+ }
1760
+
1761
+ },
1762
+ hideAllDropDown: function()
1763
+ {
1764
+ this.$toolbar.find('a.dropact').removeClass('act').removeClass('dropact');
1765
+ $('.redactor_dropdown').hide();
1766
+ },
1767
+ hideDropDown: function(e, dropdown, key)
1768
+ {
1769
+ if (!$(e.target).hasClass('dropact'))
1770
+ {
1771
+ $(dropdown).removeClass('act');
1772
+ this.showedDropDown = false;
1773
+ this.hideAllDropDown();
1774
+ }
1775
+ },
1776
+
1777
+ // SELECTION AND NODE MANIPULATION
1778
+ getSelection: function ()
1779
+ {
1780
+ if (typeof window.getSelection !== 'undefined')
1781
+ {
1782
+ return document.getSelection();
1783
+ }
1784
+ else if (typeof document.selection !== 'undefined')
1785
+ {
1786
+ return document.selection.createRange();
1787
+ }
1788
+ },
1789
+ getFragmentHtml: function (fragment)
1790
+ {
1791
+ var cloned = fragment.cloneNode(true);
1792
+ var div = document.createElement('div');
1793
+ div.appendChild(cloned);
1794
+ return div.innerHTML;
1795
+ },
1796
+ extractContent: function()
1797
+ {
1798
+ var node = this.$editor.get(0);
1799
+ var frag = document.createDocumentFragment(), child;
1800
+ while ((child = node.firstChild))
1801
+ {
1802
+ frag.appendChild(child);
1803
+ }
1804
+
1805
+ return frag;
1806
+ },
1807
+ saveSelection: function()
1808
+ {
1809
+ this.savedSel = null;
1810
+ this.savedSelObj = null;
1811
+
1812
+ if ($.browser.msie && parseInt($.browser.version, 10) < 9)
1813
+ {
1814
+ var node = this.$editor.get(0);
1815
+ this.savedSel = window.Selection.getOrigin(node);
1816
+ this.savedSelObj = window.Selection.getFocus(node);
1817
+ }
1818
+ else
1819
+ {
1820
+ this.savedSel = window.Selection.getOrigin(window);
1821
+ this.savedSelObj = window.Selection.getFocus(window);
1822
+ }
1823
+ },
1824
+ restoreSelection: function()
1825
+ {
1826
+ if (this.savedSel !== null && this.savedSelObj !== null && this.savedSel[0].tagName !== 'BODY')
1827
+ {
1828
+ window.Selection.setSelection(window, this.savedSel[0], this.savedSel[1], this.savedSelObj[0], this.savedSelObj[1]);
1829
+ }
1830
+ else
1831
+ {
1832
+ this.$editor.focus();
1833
+ }
1834
+ },
1835
+ getParentNode: function()
1836
+ {
1837
+ if (typeof window.getSelection !== 'undefined')
1838
+ {
1839
+ var s = window.getSelection();
1840
+ if (s.rangeCount > 0)
1841
+ {
1842
+ return this.getSelection().getRangeAt(0).startContainer.parentNode;
1843
+ }
1844
+ else return false;
1845
+
1846
+ }
1847
+ else if (typeof document.selection !== 'undefined')
1848
+ {
1849
+ return this.getSelection().parentElement();
1850
+ }
1851
+ },
1852
+ getCurrentNode: function()
1853
+ {
1854
+ if (typeof window.getSelection !== 'undefined')
1855
+ {
1856
+ return this.getSelection().getRangeAt(0).startContainer;
1857
+ }
1858
+ else if (typeof document.selection !== 'undefined')
1859
+ {
1860
+ return this.getSelection();
1861
+ }
1862
+ },
1863
+ setFocusNode: function(node)
1864
+ {
1865
+ if (typeof node === 'undefined')
1866
+ {
1867
+ return false;
1868
+ }
1869
+
1870
+ try {
1871
+
1872
+ var range = document.createRange();
1873
+ var selection = this.getSelection();
1874
+
1875
+ if (selection !== null)
1876
+ {
1877
+ range.selectNodeContents(node);
1878
+ selection.addRange(range);
1879
+ selection.collapse(node, 0);
1880
+ }
1881
+
1882
+ this.$editor.focus();
1883
+
1884
+ } catch (e) { }
1885
+
1886
+ },
1887
+ insertNodeAtCaret: function (node)
1888
+ {
1889
+ if (window.getSelection)
1890
+ {
1891
+ var sel = this.getSelection();
1892
+ if (sel.rangeCount)
1893
+ {
1894
+ var range = sel.getRangeAt(0);
1895
+ range.collapse(false);
1896
+ range.insertNode(node);
1897
+ range = range.cloneRange();
1898
+ range.selectNodeContents(node);
1899
+ range.collapse(false);
1900
+ sel.removeAllRanges();
1901
+ sel.addRange(range);
1902
+ }
1903
+ }
1904
+ else if (document.selection)
1905
+ {
1906
+ var html = (node.nodeType === 1) ? node.outerHTML : node.data;
1907
+ var id = "marker_" + ("" + Math.random()).slice(2);
1908
+ html += '<span id="' + id + '"></span>';
1909
+ var textRange = this.getSelection();
1910
+ textRange.collapse(false);
1911
+ textRange.pasteHTML(html);
1912
+ var markerSpan = document.getElementById(id);
1913
+ textRange.moveToElementText(markerSpan);
1914
+ textRange.select();
1915
+ markerSpan.parentNode.removeChild(markerSpan);
1916
+ }
1917
+ },
1918
+ getSelectedHtml: function()
1919
+ {
1920
+ var html = '';
1921
+ if (window.getSelection)
1922
+ {
1923
+ var sel = window.getSelection();
1924
+ if (sel.rangeCount)
1925
+ {
1926
+ var container = document.createElement("div");
1927
+ for (var i = 0, len = sel.rangeCount; i < len; ++i)
1928
+ {
1929
+ container.appendChild(sel.getRangeAt(i).cloneContents());
1930
+ }
1931
+
1932
+ html = container.innerHTML;
1933
+
1934
+ }
1935
+ }
1936
+ else if (document.selection)
1937
+ {
1938
+ if (document.selection.type === "Text")
1939
+ {
1940
+ html = document.selection.createRange().htmlText;
1941
+ }
1942
+ }
1943
+
1944
+ return html;
1945
+ },
1946
+
1947
+ // BUTTONS MANIPULATIONS
1948
+ getBtn: function(key)
1949
+ {
1950
+ return $(this.$toolbar.find('a.redactor_btn_' + key));
1951
+ },
1952
+ setBtnActive: function(key)
1953
+ {
1954
+ this.getBtn(key).addClass('act');
1955
+ },
1956
+ setBtnInactive: function(key)
1957
+ {
1958
+ this.getBtn(key).removeClass('act');
1959
+ },
1960
+
1961
+ // RESIZE IMAGES
1962
+ resizeImage: function(resize)
1963
+ {
1964
+ var clicked = false;
1965
+ var clicker = false;
1966
+ var start_x;
1967
+ var start_y;
1968
+ var ratio = $(resize).width()/$(resize).height();
1969
+ var min_w = 10;
1970
+ var min_h = 10;
1971
+
1972
+ $(resize).hover(function() { $(resize).css('cursor', 'nw-resize'); }, function() { $(resize).css('cursor','default'); clicked = false; });
1973
+
1974
+ $(resize).mousedown(function(e)
1975
+ {
1976
+ e.preventDefault();
1977
+
1978
+ clicked = true;
1979
+ clicker = true;
1980
+
1981
+ start_x = Math.round(e.pageX - $(resize).eq(0).offset().left);
1982
+ start_y = Math.round(e.pageY - $(resize).eq(0).offset().top);
1983
+ });
1984
+
1985
+ $(resize).mouseup($.proxy(function(e)
1986
+ {
1987
+ clicked = false;
1988
+ this.syncCode();
1989
+
1990
+ }, this));
1991
+
1992
+ $(resize).click($.proxy(function(e)
1993
+ {
1994
+ if (clicker)
1995
+ {
1996
+ this.imageEdit(e);
1997
+ }
1998
+
1999
+ }, this));
2000
+
2001
+ $(resize).mousemove(function(e)
2002
+ {
2003
+ if (clicked)
2004
+ {
2005
+ clicker = false;
2006
+
2007
+ var mouse_x = Math.round(e.pageX - $(this).eq(0).offset().left) - start_x;
2008
+ var mouse_y = Math.round(e.pageY - $(this).eq(0).offset().top) - start_y;
2009
+
2010
+ var div_h = $(resize).height();
2011
+
2012
+ var new_h = parseInt(div_h, 10) + mouse_y;
2013
+ var new_w = new_h*ratio;
2014
+
2015
+ if (new_w > min_w)
2016
+ {
2017
+ $(resize).width(new_w);
2018
+ }
2019
+
2020
+ if (new_h > min_h)
2021
+ {
2022
+ $(resize).height(new_h);
2023
+ }
2024
+
2025
+ start_x = Math.round(e.pageX - $(this).eq(0).offset().left);
2026
+ start_y = Math.round(e.pageY - $(this).eq(0).offset().top);
2027
+ }
2028
+ });
2029
+ },
2030
+
2031
+ // TABLE
2032
+ showTable: function()
2033
+ {
2034
+ this.saveSelection();
2035
+
2036
+ this.modalInit(RLANG.table, 'table', 300, $.proxy(function()
2037
+ {
2038
+ $('#redactor_insert_table_btn').click($.proxy(this.insertTable, this));
2039
+ }, this),
2040
+
2041
+ function()
2042
+ {
2043
+ $('#redactor_table_rows').focus();
2044
+ }
2045
+ );
2046
+ },
2047
+ insertTable: function()
2048
+ {
2049
+ var rows = $('#redactor_table_rows').val();
2050
+ var columns = $('#redactor_table_columns').val();
2051
+
2052
+ var table_box = $('<div></div>');
2053
+
2054
+ var tableid = Math.floor(Math.random() * 99999);
2055
+ var table = $('<table id="table' + tableid + '"><tbody></tbody></table>');
2056
+
2057
+ for (var i = 0; i < rows; i++)
2058
+ {
2059
+ var row = $('<tr></tr>');
2060
+ for (var z = 0; z < columns; z++)
2061
+ {
2062
+ var column = $('<td><br></td>');
2063
+ $(row).append(column);
2064
+ }
2065
+ $(table).append(row);
2066
+ }
2067
+
2068
+ $(table_box).append(table);
2069
+ var html = $(table_box).html() + '<p></p>';
2070
+
2071
+ this.restoreSelection();
2072
+ this.execCommand('inserthtml', html);
2073
+ this.modalClose();
2074
+ this.observeTables();
2075
+
2076
+ },
2077
+ tableObserver: function(e)
2078
+ {
2079
+ this.$table = $(e.target).parents('table');
2080
+
2081
+ this.$table_tr = this.$table.find('tr');
2082
+ this.$table_td = this.$table.find('td');
2083
+
2084
+ this.$table_td.removeClass('current');
2085
+
2086
+ this.$tbody = $(e.target).parents('tbody');
2087
+ this.$thead = $(this.$table).find('thead');
2088
+
2089
+ this.$current_td = $(e.target);
2090
+ this.$current_td.addClass('current');
2091
+
2092
+ this.$current_tr = $(e.target).parents('tr');
2093
+ },
2094
+ deleteTable: function()
2095
+ {
2096
+ $(this.$table).remove();
2097
+ this.$table = false;
2098
+ this.syncCode();
2099
+ },
2100
+ deleteRow: function()
2101
+ {
2102
+ $(this.$current_tr).remove();
2103
+ this.syncCode();
2104
+ },
2105
+ deleteColumn: function()
2106
+ {
2107
+ var index = $(this.$current_td).get(0).cellIndex;
2108
+
2109
+ $(this.$table).find('tr').each(function()
2110
+ {
2111
+ $(this).find('td').eq(index).remove();
2112
+ });
2113
+
2114
+ this.syncCode();
2115
+ },
2116
+ addHead: function()
2117
+ {
2118
+ if ($(this.$table).find('thead').size() !== 0)
2119
+ {
2120
+ this.deleteHead();
2121
+ }
2122
+ else
2123
+ {
2124
+ var tr = $(this.$table).find('tr').first().clone();
2125
+ tr.find('td').html('&nbsp;');
2126
+ this.$thead = $('<thead></thead>');
2127
+ this.$thead.append(tr);
2128
+ $(this.$table).prepend(this.$thead);
2129
+ this.syncCode();
2130
+ }
2131
+ },
2132
+ deleteHead: function()
2133
+ {
2134
+ $(this.$thead).remove();
2135
+ this.$thead = false;
2136
+ this.syncCode();
2137
+ },
2138
+ insertRowAbove: function()
2139
+ {
2140
+ this.insertRow('before');
2141
+ },
2142
+ insertRowBelow: function()
2143
+ {
2144
+ this.insertRow('after');
2145
+ },
2146
+ insertColumnLeft: function()
2147
+ {
2148
+ this.insertColumn('before');
2149
+ },
2150
+ insertColumnRight: function()
2151
+ {
2152
+ this.insertColumn('after');
2153
+ },
2154
+ insertRow: function(type)
2155
+ {
2156
+ var new_tr = $(this.$current_tr).clone();
2157
+ new_tr.find('td').html('&nbsp;');
2158
+ if (type === 'after')
2159
+ {
2160
+ $(this.$current_tr).after(new_tr);
2161
+ }
2162
+ else
2163
+ {
2164
+ $(this.$current_tr).before(new_tr);
2165
+ }
2166
+
2167
+ this.syncCode();
2168
+ },
2169
+ insertColumn: function(type)
2170
+ {
2171
+ var index = 0;
2172
+
2173
+ this.$current_td.addClass('current');
2174
+
2175
+ this.$current_tr.find('td').each(function(i,s)
2176
+ {
2177
+ if ($(s).hasClass('current'))
2178
+ {
2179
+ index = i;
2180
+ }
2181
+ });
2182
+
2183
+ this.$table_tr.each(function(i,s)
2184
+ {
2185
+ var current = $(s).find('td').eq(index);
2186
+
2187
+ var td = current.clone();
2188
+ td.html('&nbsp;');
2189
+
2190
+ if (type === 'after')
2191
+ {
2192
+ $(current).after(td);
2193
+ }
2194
+ else
2195
+ {
2196
+ $(current).before(td);
2197
+ }
2198
+
2199
+ });
2200
+
2201
+ this.syncCode();
2202
+ },
2203
+
2204
+ // INSERT VIDEO
2205
+ showVideo: function()
2206
+ {
2207
+ this.saveSelection();
2208
+ this.modalInit(RLANG.video, 'video', 600, $.proxy(function()
2209
+ {
2210
+ $('#redactor_insert_video_btn').click($.proxy(this.insertVideo, this));
2211
+ }, this),
2212
+
2213
+ function()
2214
+ {
2215
+ $('#redactor_insert_video_area').focus();
2216
+ }
2217
+ );
2218
+ },
2219
+ insertVideo: function()
2220
+ {
2221
+ var data = $('#redactor_insert_video_area').val();
2222
+ data = this.stripTags(data);
2223
+
2224
+ this.restoreSelection();
2225
+ this.execCommand('inserthtml', data);
2226
+ this.modalClose();
2227
+ },
2228
+
2229
+ // INSERT IMAGE
2230
+ imageEdit: function(e)
2231
+ {
2232
+ var $el = $(e.target);
2233
+ var parent = $el.parent();
2234
+
2235
+ var handler = $.proxy(function()
2236
+ {
2237
+ $('#redactor_file_alt').val($el.attr('alt'));
2238
+ $('#redactor_image_edit_src').attr('href', $el.attr('src'));
2239
+ $('#redactor_form_image_align').val($el.css('float'));
2240
+
2241
+ if ($(parent).get(0).tagName === 'A')
2242
+ {
2243
+ $('#redactor_file_link').val($(parent).attr('href'));
2244
+ }
2245
+
2246
+ $('#redactor_image_delete_btn').click($.proxy(function() { this.imageDelete($el); }, this));
2247
+ $('#redactorSaveBtn').click($.proxy(function() { this.imageSave($el); }, this));
2248
+
2249
+ }, this);
2250
+
2251
+ this.modalInit(RLANG.image, 'image_edit', 380, handler);
2252
+
2253
+ },
2254
+ imageDelete: function(el)
2255
+ {
2256
+ $(el).remove();
2257
+ this.modalClose();
2258
+ this.syncCode();
2259
+ },
2260
+ imageSave: function(el)
2261
+ {
2262
+ var parent = $(el).parent();
2263
+
2264
+ $(el).attr('alt', $('#redactor_file_alt').val());
2265
+
2266
+ var floating = $('#redactor_form_image_align').val();
2267
+
2268
+ if (floating === 'left')
2269
+ {
2270
+ $(el).css({ 'float': 'left', margin: '0 10px 10px 0' });
2271
+ }
2272
+ else if (floating === 'right')
2273
+ {
2274
+ $(el).css({ 'float': 'right', margin: '0 0 10px 10px' });
2275
+ }
2276
+ else
2277
+ {
2278
+ $(el).css({ 'float': 'none', margin: '0' });
2279
+ }
2280
+
2281
+ // as link
2282
+ var link = $.trim($('#redactor_file_link').val());
2283
+ if (link !== '')
2284
+ {
2285
+ if ($(parent).get(0).tagName !== 'A')
2286
+ {
2287
+ $(el).replaceWith('<a href="' + link + '">' + this.outerHTML(el) + '</a>');
2288
+ }
2289
+ else
2290
+ {
2291
+ $(parent).attr('href', link);
2292
+ }
2293
+ }
2294
+ else
2295
+ {
2296
+ if ($(parent).get(0).tagName === 'A')
2297
+ {
2298
+ $(parent).replaceWith(this.outerHTML(el));
2299
+ }
2300
+ }
2301
+
2302
+ this.modalClose();
2303
+ this.observeImages();
2304
+ this.syncCode();
2305
+
2306
+ },
2307
+ showImage: function()
2308
+ {
2309
+ this.saveSelection();
2310
+
2311
+ var handler = $.proxy(function()
2312
+ {
2313
+ // json
2314
+ if (this.opts.imageGetJson !== false)
2315
+ {
2316
+ $.getJSON(this.opts.imageGetJson, $.proxy(function(data) {
2317
+
2318
+ $.each(data, $.proxy(function(key, val)
2319
+ {
2320
+ var img = $('<img src="' + val.thumb + '" rel="' + val.image + '" />');
2321
+ $('#redactor_image_box').append(img);
2322
+ $(img).click($.proxy(this.imageSetThumb, this));
2323
+
2324
+ }, this));
2325
+
2326
+ }, this));
2327
+ }
2328
+ else
2329
+ {
2330
+ $('#redactor_tabs a').eq(1).remove();
2331
+ }
2332
+
2333
+ if (this.opts.imageUpload !== false)
2334
+ {
2335
+
2336
+ // dragupload
2337
+ if (this.opts.uploadCrossDomain === false && this.isMobile() === false)
2338
+ {
2339
+
2340
+ if ($('#redactor_file').size() !== 0)
2341
+ {
2342
+ $('#redactor_file').dragupload(
2343
+ {
2344
+ url: this.opts.imageUpload,
2345
+ uploadFields: this.opts.uploadFields,
2346
+ success: $.proxy(this.imageUploadCallback, this)
2347
+ });
2348
+ }
2349
+ }
2350
+
2351
+ // ajax upload
2352
+ this.uploadInit('redactor_file', { auto: true, url: this.opts.imageUpload, success: $.proxy(this.imageUploadCallback, this) });
2353
+ }
2354
+ else
2355
+ {
2356
+ $('.redactor_tab').hide();
2357
+ if (this.opts.imageGetJson === false)
2358
+ {
2359
+ $('#redactor_tabs').remove();
2360
+ $('#redactor_tab3').show();
2361
+ }
2362
+ else
2363
+ {
2364
+ var tabs = $('#redactor_tabs a');
2365
+ tabs.eq(0).remove();
2366
+ tabs.eq(1).addClass('redactor_tabs_act');
2367
+ $('#redactor_tab2').show();
2368
+ }
2369
+ }
2370
+
2371
+ $('#redactor_upload_btn').click($.proxy(this.imageUploadCallbackLink, this));
2372
+
2373
+ }, this);
2374
+
2375
+ var endCallback = $.proxy(function()
2376
+ {
2377
+ if (this.opts.imageUpload === false && this.opts.imageGetJson === false)
2378
+ {
2379
+ $('#redactor_file_link').focus();
2380
+ }
2381
+ }, this);
2382
+
2383
+ this.modalInit(RLANG.image, 'image', 570, handler, endCallback, true);
2384
+
2385
+ },
2386
+ imageSetThumb: function(e)
2387
+ {
2388
+ this._imageSet('<img alt="" src="' + $(e.target).attr('rel') + '" />', true);
2389
+ },
2390
+ imageUploadCallbackLink: function()
2391
+ {
2392
+ if ($('#redactor_file_link').val() !== '')
2393
+ {
2394
+ var data = '<img src="' + $('#redactor_file_link').val() + '" />';
2395
+ this._imageSet(data, true);
2396
+ }
2397
+ else
2398
+ {
2399
+ this.modalClose();
2400
+ }
2401
+ },
2402
+ imageUploadCallback: function(data)
2403
+ {
2404
+ this._imageSet(data);
2405
+ },
2406
+ _imageSet: function(json, link)
2407
+ {
2408
+ this.restoreSelection();
2409
+
2410
+ if (json !== false)
2411
+ {
2412
+ var html = '', data = '';
2413
+ if (link !== true)
2414
+ {
2415
+ data = $.parseJSON(json);
2416
+ html = '<p><img src="' + data.filelink + '" /></p>';
2417
+ }
2418
+ else
2419
+ {
2420
+ html = json;
2421
+ }
2422
+
2423
+ this.execCommand('inserthtml', html);
2424
+
2425
+ // upload image callback
2426
+ if (link !== true && typeof this.opts.imageUploadCallback === 'function')
2427
+ {
2428
+ this.opts.imageUploadCallback(this, data);
2429
+ }
2430
+ }
2431
+
2432
+ this.modalClose();
2433
+ this.observeImages();
2434
+ },
2435
+
2436
+ // INSERT LINK
2437
+ showLink: function()
2438
+ {
2439
+ this.saveSelection();
2440
+
2441
+ var handler = $.proxy(function()
2442
+ {
2443
+ this.insert_link_node = false;
2444
+ var sel = this.getSelection();
2445
+ var url = '', text = '', target = '';
2446
+
2447
+ if ($.browser.msie)
2448
+ {
2449
+ var parent = this.getParentNode();
2450
+ if (parent.nodeName === 'A')
2451
+ {
2452
+ this.insert_link_node = $(parent);
2453
+ text = this.insert_link_node.text();
2454
+ url = this.insert_link_node.attr('href');
2455
+ target = this.insert_link_node.attr('target');
2456
+ }
2457
+ else
2458
+ {
2459
+ if (this.oldIE())
2460
+ {
2461
+ text = sel.text;
2462
+ }
2463
+ else
2464
+ {
2465
+ text = sel.toString();
2466
+ }
2467
+ }
2468
+ }
2469
+ else
2470
+ {
2471
+ if (sel && sel.anchorNode && sel.anchorNode.parentNode.tagName === 'A')
2472
+ {
2473
+ url = sel.anchorNode.parentNode.href;
2474
+ text = sel.anchorNode.parentNode.text;
2475
+ target = sel.anchorNode.parentNode.target;
2476
+
2477
+ if (sel.toString() === '')
2478
+ {
2479
+ this.insert_link_node = sel.anchorNode.parentNode;
2480
+ }
2481
+ }
2482
+ else
2483
+ {
2484
+ text = sel.toString();
2485
+ }
2486
+ }
2487
+
2488
+ $('.redactor_link_text').val(text);
2489
+
2490
+ var turl = url.replace(self.location.href, '');
2491
+
2492
+ if (url.search('mailto:') === 0)
2493
+ {
2494
+ this.setModalTab(2);
2495
+
2496
+ $('#redactor_tab_selected').val(2);
2497
+ $('#redactor_link_mailto').val(url.replace('mailto:', ''));
2498
+ }
2499
+ else if (turl.search(/^#/gi) === 0)
2500
+ {
2501
+ this.setModalTab(3);
2502
+
2503
+ $('#redactor_tab_selected').val(3);
2504
+ $('#redactor_link_anchor').val(turl.replace(/^#/gi, ''));
2505
+ }
2506
+ else
2507
+ {
2508
+ $('#redactor_link_url').val(url);
2509
+ }
2510
+
2511
+ if (target === '_blank')
2512
+ {
2513
+ $('#redactor_link_blank').attr('checked', true);
2514
+ }
2515
+
2516
+ $('#redactor_insert_link_btn').click($.proxy(this.insertLink, this));
2517
+
2518
+
2519
+ }, this);
2520
+
2521
+ var endCallback = function(url)
2522
+ {
2523
+ $('#redactor_link_url').focus();
2524
+ };
2525
+
2526
+
2527
+ this.modalInit(RLANG.link, 'link', 460, handler, endCallback);
2528
+
2529
+ },
2530
+ insertLink: function()
2531
+ {
2532
+ var tab_selected = $('#redactor_tab_selected').val();
2533
+ var link = '', text = '', target = '';
2534
+
2535
+ if (tab_selected === '1') // url
2536
+ {
2537
+ link = $('#redactor_link_url').val();
2538
+ text = $('#redactor_link_url_text').val();
2539
+ if ($('#redactor_link_blank').attr('checked'))
2540
+ {
2541
+ target = '_blank';
2542
+ }
2543
+ }
2544
+ else if (tab_selected === '2') // mailto
2545
+ {
2546
+ link = 'mailto:' + $('#redactor_link_mailto').val();
2547
+ text = $('#redactor_link_mailto_text').val();
2548
+ }
2549
+ else if (tab_selected === '3') // anchor
2550
+ {
2551
+ link = '#' + $('#redactor_link_anchor').val();
2552
+ text = $('#redactor_link_anchor_text').val();
2553
+ }
2554
+
2555
+ this._insertLink('<a href="' + link + '" target="' + target + '">' + text + '</a>&nbsp;', $.trim(text), link, target);
2556
+
2557
+ },
2558
+ _insertLink: function(a, text, link, target)
2559
+ {
2560
+ this.$editor.focus();
2561
+ this.restoreSelection();
2562
+
2563
+ if (text !== '')
2564
+ {
2565
+ if (this.insert_link_node)
2566
+ {
2567
+ $(this.insert_link_node).text(text);
2568
+ $(this.insert_link_node).attr('href', link);
2569
+ if (target !== '')
2570
+ {
2571
+ $(this.insert_link_node).attr('target', target);
2572
+ }
2573
+ this.syncCode();
2574
+ }
2575
+ else
2576
+ {
2577
+ this.execCommand('inserthtml', a);
2578
+ }
2579
+ }
2580
+
2581
+ this.modalClose();
2582
+ },
2583
+
2584
+ // INSERT FILE
2585
+ showFile: function()
2586
+ {
2587
+ this.saveSelection();
2588
+
2589
+ var handler = $.proxy(function()
2590
+ {
2591
+ var sel = this.getSelection();
2592
+
2593
+ var text = '';
2594
+
2595
+ if (this.oldIE())
2596
+ {
2597
+ text = sel.text;
2598
+ }
2599
+ else
2600
+ {
2601
+ text = sel.toString();
2602
+ }
2603
+
2604
+ $('#redactor_filename').val(text);
2605
+
2606
+ // dragupload
2607
+ if (this.opts.uploadCrossDomain === false && this.isMobile() === false)
2608
+ {
2609
+ $('#redactor_file').dragupload(
2610
+ {
2611
+ url: this.opts.fileUpload,
2612
+ uploadFields: this.opts.uploadFields,
2613
+ success: $.proxy(function(data)
2614
+ {
2615
+ this.fileUploadCallback(data);
2616
+ }, this)
2617
+ });
2618
+ }
2619
+
2620
+ this.uploadInit('redactor_file', { auto: true, url: this.opts.fileUpload, success: $.proxy(function(data) {
2621
+
2622
+ this.fileUploadCallback(data);
2623
+
2624
+ }, this)});
2625
+
2626
+ }, this);
2627
+
2628
+ this.modalInit(RLANG.file, 'file', 500, handler);
2629
+ },
2630
+ fileUploadCallback: function(json)
2631
+ {
2632
+ this.restoreSelection();
2633
+
2634
+ if (json !== false)
2635
+ {
2636
+ var data = $.parseJSON(json);
2637
+ var text = $('#redactor_filename').val();
2638
+
2639
+ if (text === '')
2640
+ {
2641
+ text = data.filename;
2642
+ }
2643
+
2644
+ var link = '<a href="' + data.filelink + '">' + text + '</a>';
2645
+
2646
+ // chrome fix
2647
+ if ($.browser.webkit && !!window.chrome)
2648
+ {
2649
+ link = link + '&nbsp;';
2650
+ }
2651
+
2652
+ this.execCommand('inserthtml', link);
2653
+
2654
+ // file upload callback
2655
+ if (typeof this.opts.fileUploadCallback === 'function')
2656
+ {
2657
+ this.opts.fileUploadCallback(this, data);
2658
+ }
2659
+ }
2660
+
2661
+ this.modalClose();
2662
+ },
2663
+
2664
+
2665
+
2666
+ // MODAL
2667
+ modalInit: function(title, url, width, handler, endCallback, scroll)
2668
+ {
2669
+ // modal overlay
2670
+ if ($('#redactor_modal_overlay').size() === 0)
2671
+ {
2672
+ this.overlay = $('<div id="redactor_modal_overlay" style="display: none;"></div>');
2673
+ $('body').prepend(this.overlay);
2674
+ }
2675
+
2676
+ if (this.opts.overlay)
2677
+ {
2678
+ $('#redactor_modal_overlay').show();
2679
+ $('#redactor_modal_overlay').click($.proxy(this.modalClose, this));
2680
+ }
2681
+
2682
+ if ($('#redactor_modal').size() === 0)
2683
+ {
2684
+ this.modal = $('<div id="redactor_modal" style="display: none;"><div id="redactor_modal_close">&times;</div><div id="redactor_modal_header"></div><div id="redactor_modal_inner"></div></div>');
2685
+ $('body').append(this.modal);
2686
+ }
2687
+
2688
+ $('#redactor_modal_close').click($.proxy(this.modalClose, this));
2689
+
2690
+ this.hdlModalClose = $.proxy(function(e) { if ( e.keyCode === 27) { this.modalClose(); } }, this);
2691
+
2692
+ $(document).keyup(this.hdlModalClose);
2693
+ this.$editor.keyup(this.hdlModalClose);
2694
+
2695
+ $('#redactor_modal_inner').html(this.opts['modal_' + url]);
2696
+ $('#redactor_modal_header').html(title);
2697
+
2698
+ // tabs
2699
+ if ($('#redactor_tabs').size() !== 0)
2700
+ {
2701
+ var that = this;
2702
+ $('#redactor_tabs a').each(function(i,s)
2703
+ {
2704
+ i++;
2705
+ $(s).click(function()
2706
+ {
2707
+ $('#redactor_tabs a').removeClass('redactor_tabs_act');
2708
+ $(this).addClass('redactor_tabs_act');
2709
+ $('.redactor_tab').hide();
2710
+ $('#redactor_tab' + i).show();
2711
+ $('#redactor_tab_selected').val(i);
2712
+
2713
+ if (that.isMobile() === false)
2714
+ {
2715
+ var height = $('#redactor_modal').outerHeight();
2716
+ $('#redactor_modal').css('margin-top', '-' + (height+10)/2 + 'px');
2717
+ }
2718
+ });
2719
+ });
2720
+ }
2721
+
2722
+ $('#redactor_btn_modal_close').click($.proxy(this.modalClose, this));
2723
+
2724
+ // callback
2725
+ if (typeof(handler) === 'function')
2726
+ {
2727
+ handler();
2728
+ }
2729
+
2730
+ // setup
2731
+ var height = $('#redactor_modal').outerHeight();
2732
+
2733
+ if (this.isMobile() === false)
2734
+ {
2735
+ $('#redactor_modal').css({ position: 'fixed', top: '50%', left: '50%', width: width + 'px', height: 'auto', minHeight: 'auto', marginTop: '-' + (height+10)/2 + 'px', marginLeft: '-' + (width+60)/2 + 'px' }).fadeIn('fast');
2736
+ }
2737
+ else
2738
+ {
2739
+ $('#redactor_modal').css({ position: 'fixed', width: '100%', height: '100%', top: '0', left: '0', margin: '0', minHeight: '300px' }).show();
2740
+ }
2741
+
2742
+ // end callback
2743
+ if (typeof(endCallback) === 'function')
2744
+ {
2745
+ endCallback();
2746
+ }
2747
+
2748
+ if (scroll === true)
2749
+ {
2750
+ $('#redactor_image_box').height(300).css('overflow', 'auto');
2751
+ }
2752
+
2753
+ },
2754
+ modalClose: function()
2755
+ {
2756
+
2757
+ $('#redactor_modal_close').unbind('click', this.modalClose);
2758
+ $('#redactor_modal').fadeOut('fast', $.proxy(function()
2759
+ {
2760
+ $('#redactor_modal_inner').html('');
2761
+
2762
+ if (this.opts.overlay)
2763
+ {
2764
+ $('#redactor_modal_overlay').hide();
2765
+ $('#redactor_modal_overlay').unbind('click', this.modalClose);
2766
+ }
2767
+
2768
+ $(document).unbind('keyup', this.hdlModalClose);
2769
+ this.$editor.unbind('keyup', this.hdlModalClose);
2770
+
2771
+ }, this));
2772
+
2773
+ },
2774
+ setModalTab: function(num)
2775
+ {
2776
+ $('.redactor_tab').hide();
2777
+ var tabs = $('#redactor_tabs a');
2778
+ tabs.removeClass('redactor_tabs_act');
2779
+ tabs.eq(num-1).addClass('redactor_tabs_act');
2780
+ $('#redactor_tab' + num).show();
2781
+ },
2782
+
2783
+ // UPLOAD
2784
+ uploadInit: function(element, options)
2785
+ {
2786
+ // Upload Options
2787
+ this.uploadOptions = {
2788
+ url: false,
2789
+ success: false,
2790
+ start: false,
2791
+ trigger: false,
2792
+ auto: false,
2793
+ input: false
2794
+ };
2795
+
2796
+ $.extend(this.uploadOptions, options);
2797
+
2798
+ // Test input or form
2799
+ if ($('#' + element).size() !== 0 && $('#' + element).get(0).tagName === 'INPUT')
2800
+ {
2801
+ this.uploadOptions.input = $('#' + element);
2802
+ this.element = $($('#' + element).get(0).form);
2803
+ }
2804
+ else
2805
+ {
2806
+ this.element = $('#' + element);
2807
+ }
2808
+
2809
+ this.element_action = this.element.attr('action');
2810
+
2811
+ // Auto or trigger
2812
+ if (this.uploadOptions.auto)
2813
+ {
2814
+ $(this.uploadOptions.input).change($.proxy(function()
2815
+ {
2816
+ this.element.submit(function(e) { return false; });
2817
+ this.uploadSubmit();
2818
+ }, this));
2819
+
2820
+ }
2821
+ else if (this.uploadOptions.trigger)
2822
+ {
2823
+ $('#' + this.uploadOptions.trigger).click($.proxy(this.uploadSubmit, this));
2824
+ }
2825
+ },
2826
+ uploadSubmit : function()
2827
+ {
2828
+ this.uploadForm(this.element, this.uploadFrame());
2829
+ },
2830
+ uploadFrame : function()
2831
+ {
2832
+ this.id = 'f' + Math.floor(Math.random() * 99999);
2833
+
2834
+ var d = document.createElement('div');
2835
+ var iframe = '<iframe style="display:none" id="'+this.id+'" name="'+this.id+'"></iframe>';
2836
+ d.innerHTML = iframe;
2837
+ document.body.appendChild(d);
2838
+
2839
+ // Start
2840
+ if (this.uploadOptions.start)
2841
+ {
2842
+ this.uploadOptions.start();
2843
+ }
2844
+
2845
+ $('#' + this.id).load($.proxy(this.uploadLoaded, this));
2846
+
2847
+ return this.id;
2848
+ },
2849
+ uploadForm : function(f, name)
2850
+ {
2851
+ if (this.uploadOptions.input)
2852
+ {
2853
+ var formId = 'redactorUploadForm' + this.id;
2854
+ var fileId = 'redactorUploadFile' + this.id;
2855
+ this.form = $('<form action="' + this.uploadOptions.url + '" method="POST" target="' + name + '" name="' + formId + '" id="' + formId + '" enctype="multipart/form-data"></form>');
2856
+
2857
+ // append hidden fields
2858
+ if (this.opts.uploadFields !== false && typeof this.opts.uploadFields === 'object')
2859
+ {
2860
+ $.each(this.opts.uploadFields, $.proxy(function(k,v)
2861
+ {
2862
+ if (v.indexOf('#') === 0)
2863
+ {
2864
+ v = $(v).val();
2865
+ }
2866
+
2867
+ var hidden = $('<input type="hidden" name="' + k + '" value="' + v + '">');
2868
+ $(this.form).append(hidden);
2869
+
2870
+ }, this));
2871
+ }
2872
+
2873
+ var oldElement = this.uploadOptions.input;
2874
+ var newElement = $(oldElement).clone();
2875
+ $(oldElement).attr('id', fileId);
2876
+ $(oldElement).before(newElement);
2877
+ $(oldElement).appendTo(this.form);
2878
+ $(this.form).css('position', 'absolute');
2879
+ $(this.form).css('top', '-2000px');
2880
+ $(this.form).css('left', '-2000px');
2881
+ $(this.form).appendTo('body');
2882
+ // ==========================================
2883
+ // SLATE FIX: Rails workaround
2884
+
2885
+ $('input[name="utf8"]').clone().appendTo(this.form);
2886
+ $('input[name="authenticity_token"]').clone().appendTo(this.form);
2887
+
2888
+ // ==========================================
2889
+ this.form.submit();
2890
+ }
2891
+ else
2892
+ {
2893
+ f.attr('target', name);
2894
+ f.attr('method', 'POST');
2895
+ f.attr('enctype', 'multipart/form-data');
2896
+ f.attr('action', this.uploadOptions.url);
2897
+
2898
+ this.element.submit();
2899
+ }
2900
+
2901
+ },
2902
+ uploadLoaded : function()
2903
+ {
2904
+ var i = $('#' + this.id);
2905
+ var d;
2906
+
2907
+ if (i.contentDocument)
2908
+ {
2909
+ d = i.contentDocument;
2910
+ }
2911
+ else if (i.contentWindow)
2912
+ {
2913
+ d = i.contentWindow.document;
2914
+ }
2915
+ else
2916
+ {
2917
+ d = window.frames[this.id].document;
2918
+ }
2919
+
2920
+ // Success
2921
+ if (this.uploadOptions.success)
2922
+ {
2923
+ if (typeof d !== 'undefined')
2924
+ {
2925
+ // Remove bizarre <pre> tag wrappers around our json data:
2926
+ var rawString = d.body.innerHTML;
2927
+ var jsonString = rawString.match(/\{.*\}/)[0];
2928
+ this.uploadOptions.success(jsonString);
2929
+ }
2930
+ else
2931
+ {
2932
+ alert('Upload failed!');
2933
+ this.uploadOptions.success(false);
2934
+ }
2935
+ }
2936
+
2937
+ this.element.attr('action', this.element_action);
2938
+ this.element.attr('target', '');
2939
+
2940
+ },
2941
+
2942
+ // UTILITY
2943
+ oldIE: function()
2944
+ {
2945
+ if ($.browser.msie && parseInt($.browser.version, 10) < 9)
2946
+ {
2947
+ return true;
2948
+ }
2949
+
2950
+ return false;
2951
+ },
2952
+ outerHTML: function(s)
2953
+ {
2954
+ return $("<p>").append($(s).eq(0).clone()).html();
2955
+ },
2956
+ normalize: function(str)
2957
+ {
2958
+ return parseInt(str.replace('px',''), 10);
2959
+ },
2960
+ isMobile: function(ipad)
2961
+ {
2962
+ if (ipad === true && /(iPhone|iPod|iPad|BlackBerry|Android)/.test(navigator.userAgent))
2963
+ {
2964
+ return true;
2965
+ }
2966
+ else if (/(iPhone|iPod|BlackBerry|Android)/.test(navigator.userAgent))
2967
+ {
2968
+ return true;
2969
+ }
2970
+ else
2971
+ {
2972
+ return false;
2973
+ }
2974
+ }
2975
+
2976
+ };
2977
+
2978
+
2979
+ // API
2980
+ $.fn.getEditor = function()
2981
+ {
2982
+ return this.data('redactor').$editor;
2983
+ };
2984
+
2985
+ $.fn.getCode = function()
2986
+ {
2987
+ return this.data('redactor').getCode();
2988
+ };
2989
+
2990
+ $.fn.getText = function()
2991
+ {
2992
+ return this.data('redactor').$editor.text();
2993
+ };
2994
+
2995
+ $.fn.getSelected = function()
2996
+ {
2997
+ return this.data('redactor').getSelectedHtml();
2998
+ };
2999
+
3000
+ $.fn.setCode = function(html)
3001
+ {
3002
+ this.data('redactor').setCode(html);
3003
+ };
3004
+
3005
+ $.fn.insertHtml = function(html)
3006
+ {
3007
+ this.data('redactor').insertHtml(html);
3008
+ };
3009
+
3010
+ $.fn.destroyEditor = function()
3011
+ {
3012
+ this.data('redactor').destroy();
3013
+ this.removeData('redactor');
3014
+ };
3015
+
3016
+ $.fn.setFocus = function()
3017
+ {
3018
+ this.data('redactor').focus();
3019
+ };
3020
+
3021
+ $.fn.execCommand = function(cmd, param)
3022
+ {
3023
+ this.data('redactor').execCommand(cmd, param);
3024
+ };
3025
+
3026
+
3027
+ /*
3028
+ Plugin Drag and drop Upload v1.0.2
3029
+ http://imperavi.com/
3030
+ Copyright 2012, Imperavi Inc.
3031
+ */
3032
+ (function($){
3033
+
3034
+ "use strict";
3035
+
3036
+ // Initialization
3037
+ $.fn.dragupload = function(options)
3038
+ {
3039
+ return this.each(function() {
3040
+ var obj = new Construct(this, options);
3041
+ obj.init();
3042
+ });
3043
+ };
3044
+
3045
+ // Options and variables
3046
+ function Construct(el, options) {
3047
+
3048
+ this.opts = $.extend({
3049
+
3050
+ url: false,
3051
+ success: false,
3052
+ preview: false,
3053
+ uploadFields: false,
3054
+
3055
+ text: RLANG.drop_file_here,
3056
+ atext: RLANG.or_choose
3057
+
3058
+ }, options);
3059
+
3060
+ this.$el = $(el);
3061
+ }
3062
+
3063
+ // Functionality
3064
+ Construct.prototype = {
3065
+ init: function()
3066
+ {
3067
+ if (!$.browser.msie)
3068
+ {
3069
+ this.droparea = $('<div class="redactor_droparea"></div>');
3070
+ this.dropareabox = $('<div class="redactor_dropareabox">' + this.opts.text + '</div>');
3071
+ this.dropalternative = $('<div class="redactor_dropalternative">' + this.opts.atext + '</div>');
3072
+
3073
+ this.droparea.append(this.dropareabox);
3074
+
3075
+ this.$el.before(this.droparea);
3076
+ this.$el.before(this.dropalternative);
3077
+
3078
+ // drag over
3079
+ this.dropareabox.bind('dragover', $.proxy(function() { return this.ondrag(); }, this));
3080
+
3081
+ // drag leave
3082
+ this.dropareabox.bind('dragleave', $.proxy(function() { return this.ondragleave(); }, this));
3083
+
3084
+ var uploadProgress = $.proxy(function(e)
3085
+ {
3086
+ var percent = parseInt(e.loaded / e.total * 100, 10);
3087
+ this.dropareabox.text('Loading ' + percent + '%');
3088
+
3089
+ }, this);
3090
+
3091
+ var xhr = jQuery.ajaxSettings.xhr();
3092
+
3093
+ if (xhr.upload)
3094
+ {
3095
+ xhr.upload.addEventListener('progress', uploadProgress, false);
3096
+ }
3097
+
3098
+ var provider = function () { return xhr; };
3099
+
3100
+ // drop
3101
+ this.dropareabox.get(0).ondrop = $.proxy(function(event)
3102
+ {
3103
+ event.preventDefault();
3104
+
3105
+ this.dropareabox.removeClass('hover').addClass('drop');
3106
+
3107
+ var file = event.dataTransfer.files[0];
3108
+ var fd = new FormData();
3109
+
3110
+ // append hidden fields
3111
+ if (this.opts.uploadFields !== false && typeof this.opts.uploadFields === 'object')
3112
+ {
3113
+ $.each(this.opts.uploadFields, $.proxy(function(k,v)
3114
+ {
3115
+ if (v.indexOf('#') === 0)
3116
+ {
3117
+ v = $(v).val();
3118
+ }
3119
+
3120
+ fd.append(k, v);
3121
+
3122
+ }, this));
3123
+ }
3124
+
3125
+ // append file data
3126
+ fd.append('file', file);
3127
+
3128
+
3129
+ $.ajax({
3130
+ dataType: 'html',
3131
+ url: this.opts.url,
3132
+ data: fd,
3133
+ xhr: provider,
3134
+ cache: false,
3135
+ contentType: false,
3136
+ processData: false,
3137
+ type: 'POST',
3138
+ success: $.proxy(function(data)
3139
+ {
3140
+ if (this.opts.success !== false)
3141
+ {
3142
+ this.opts.success(data);
3143
+ }
3144
+
3145
+ if (this.opts.preview === true)
3146
+ {
3147
+ this.dropareabox.html(data);
3148
+ }
3149
+
3150
+ }, this)
3151
+ });
3152
+
3153
+
3154
+ }, this);
3155
+ }
3156
+ },
3157
+ ondrag: function()
3158
+ {
3159
+ this.dropareabox.addClass('hover');
3160
+ return false;
3161
+ },
3162
+ ondragleave: function()
3163
+ {
3164
+ this.dropareabox.removeClass('hover');
3165
+ return false;
3166
+ }
3167
+ };
3168
+
3169
+ })(jQuery);
3170
+
3171
+
3172
+ // Define: Linkify plugin from stackoverflow
3173
+ (function($){
3174
+
3175
+ "use strict";
3176
+
3177
+ var url1 = /(^|&lt;|\s)(www\..+?\..+?)(\s|&gt;|$)/g,
3178
+ url2 = /(^|&lt;|\s)(((https?|ftp):\/\/|mailto:).+?)(\s|&gt;|$)/g,
3179
+
3180
+ linkifyThis = function ()
3181
+ {
3182
+ var childNodes = this.childNodes,
3183
+ i = childNodes.length;
3184
+ while(i--)
3185
+ {
3186
+ var n = childNodes[i];
3187
+ if (n.nodeType === 3)
3188
+ {
3189
+ var html = n.nodeValue;
3190
+ if (html)
3191
+ {
3192
+ html = html.replace(/&/g, '&amp;')
3193
+ .replace(/</g, '&lt;')
3194
+ .replace(/>/g, '&gt;')
3195
+ .replace(url1, '$1<a href="http://$2">$2</a>$3')
3196
+ .replace(url2, '$1<a href="$2">$2</a>$5');
3197
+
3198
+ $(n).after(html).remove();
3199
+ }
3200
+ }
3201
+ else if (n.nodeType === 1 && !/^(a|button|textarea)$/i.test(n.tagName))
3202
+ {
3203
+ linkifyThis.call(n);
3204
+ }
3205
+ }
3206
+ };
3207
+
3208
+ $.fn.linkify = function ()
3209
+ {
3210
+ this.each(linkifyThis);
3211
+ };
3212
+
3213
+ })(jQuery);
3214
+
3215
+
3216
+
3217
+
3218
+ /* jQuery plugin textselect
3219
+ * version: 0.9
3220
+ * author: Josef Moravec, josef.moravec@gmail.com
3221
+ * updated: Imperavi Inc.
3222
+ *
3223
+ */
3224
+ (function($){$.event.special.textselect={setup:function(data,namespaces){$(this).data("textselected",false);$(this).data("ttt",data);$(this).bind('mouseup',$.event.special.textselect.handler)},teardown:function(data){$(this).unbind('mouseup',$.event.special.textselect.handler)},handler:function(event){var data=$(this).data("ttt");var text=$.event.special.textselect.getSelectedText(data).toString();if(text!=''){$(this).data("textselected",true);event.type="textselect";event.text=text;$.event.handle.apply(this,arguments)}},getSelectedText:function(data){var text='';if(window.getSelection)text=window.getSelection();else if(document.getSelection) text=document.getSelection();else if(document.selection)text=document.selection.createRange().text;return text}};$.event.special.textunselect={setup:function(data,namespaces){$(this).data("rttt",data);$(this).data("textselected",false);$(this).bind('mouseup',$.event.special.textunselect.handler);$(this).bind('keyup',$.event.special.textunselect.handlerKey)},teardown:function(data){$(this).unbind('mouseup',$.event.special.textunselect.handler)},handler:function(event){if($(this).data("textselected")){var data=$(this).data("rttt");var text=$.event.special.textselect.getSelectedText(data).toString();if(text==''){$(this).data("textselected",false);event.type="textunselect";$.event.handle.apply(this,arguments)}}},handlerKey:function(event){if($(this).data("textselected")){var data=$(this).data("rttt");var text=$.event.special.textselect.getSelectedText(data).toString();if((event.keyCode=27)&&(text=='')){$(this).data("textselected",false);event.type="textunselect";$.event.handle.apply(this,arguments)}}}}})(jQuery);