redactor-rails 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/{LICENSE → MIT-LICENSE} +0 -0
  2. data/README.md +18 -0
  3. data/lib/redactor-rails/version.rb +1 -1
  4. data/vendor/assets/javascripts/redactor-rails/css/docstyle.css +18 -2
  5. data/vendor/assets/javascripts/redactor-rails/css/style.css +20 -4
  6. data/vendor/assets/javascripts/redactor-rails/css/wym.css +18 -3
  7. data/vendor/assets/javascripts/redactor-rails/index.js +1 -1
  8. data/vendor/assets/javascripts/redactor-rails/langs/bg.js +67 -0
  9. data/vendor/assets/javascripts/redactor-rails/langs/by.js +7 -14
  10. data/vendor/assets/javascripts/redactor-rails/langs/cs.js +77 -0
  11. data/vendor/assets/javascripts/redactor-rails/langs/de.js +21 -26
  12. data/vendor/assets/javascripts/redactor-rails/langs/en.js +32 -42
  13. data/vendor/assets/javascripts/redactor-rails/langs/es.js +5 -15
  14. data/vendor/assets/javascripts/redactor-rails/langs/fi.js +69 -0
  15. data/vendor/assets/javascripts/redactor-rails/langs/fr.js +9 -7
  16. data/vendor/assets/javascripts/redactor-rails/langs/hr.js +69 -0
  17. data/vendor/assets/javascripts/redactor-rails/langs/hu.js +5 -14
  18. data/vendor/assets/javascripts/redactor-rails/langs/it.js +5 -13
  19. data/vendor/assets/javascripts/redactor-rails/langs/ja.js +5 -15
  20. data/vendor/assets/javascripts/redactor-rails/langs/ko.js +66 -0
  21. data/vendor/assets/javascripts/redactor-rails/langs/lv.js +6 -15
  22. data/vendor/assets/javascripts/redactor-rails/langs/nl.js +5 -12
  23. data/vendor/assets/javascripts/redactor-rails/langs/pl.js +6 -15
  24. data/vendor/assets/javascripts/redactor-rails/langs/pt_br.js +6 -15
  25. data/vendor/assets/javascripts/redactor-rails/langs/ru.js +8 -17
  26. data/vendor/assets/javascripts/redactor-rails/langs/sk.js +66 -0
  27. data/vendor/assets/javascripts/redactor-rails/langs/sq.js +5 -12
  28. data/vendor/assets/javascripts/redactor-rails/langs/tr.js +5 -15
  29. data/vendor/assets/javascripts/redactor-rails/langs/ua.js +6 -14
  30. data/vendor/assets/javascripts/redactor-rails/langs/zh_cn.js +5 -15
  31. data/vendor/assets/javascripts/redactor-rails/langs/zh_tw.js +16 -26
  32. data/vendor/assets/javascripts/redactor-rails/redactor.js +1576 -582
  33. data/vendor/assets/javascripts/redactor-rails/redactor.min.js +1 -1
  34. data/vendor/assets/stylesheets/redactor-rails/css/redactor.css +76 -35
  35. metadata +69 -56
  36. data/vendor/assets/javascripts/redactor-rails/plugins/file.html +0 -3
  37. data/vendor/assets/javascripts/redactor-rails/plugins/image.html +0 -39
  38. data/vendor/assets/javascripts/redactor-rails/plugins/image_edit.html +0 -35
  39. data/vendor/assets/javascripts/redactor-rails/plugins/link.html +0 -74
  40. data/vendor/assets/javascripts/redactor-rails/plugins/table.html +0 -25
  41. data/vendor/assets/javascripts/redactor-rails/plugins/video.html +0 -15
  42. data/vendor/assets/javascripts/redactor-rails/toolbars/default.js +0 -214
  43. data/vendor/assets/javascripts/redactor-rails/toolbars/mini.js +0 -103
@@ -1,4 +1,5 @@
1
- var RLANG = {
1
+ var RELANG = {};
2
+ RELANG['sq'] = {
2
3
  html: 'HTML',
3
4
  video: 'Video',
4
5
  image: 'Fotografi',
@@ -6,7 +7,7 @@ var RLANG = {
6
7
  link: 'Link',
7
8
  link_insert: 'Lidh linq ...',
8
9
  unlink: 'Hiq linkun',
9
- styles: 'Stilet',
10
+ formatting: 'Stilet',
10
11
  paragraph: 'Paragraf',
11
12
  quote: 'Kuotë',
12
13
  code: 'Kod',
@@ -14,16 +15,10 @@ var RLANG = {
14
15
  header2: 'Header 2',
15
16
  header3: 'Header 3',
16
17
  header4: 'Header 4',
17
- format: 'Formati',
18
18
  bold: 'Te trasha / Bold',
19
19
  italic: 'Kursive / Italic',
20
- superscript: 'Superscript',
21
- strikethrough: 'Strikethrough',
22
20
  fontcolor: 'Ngjyra e shkronjave',
23
21
  backcolor: 'Ngjyra e mbrapavisë së shkronjave',
24
- removeformat: 'Fshije formatin',
25
- cleanstyles: 'Pastro stilet',
26
- lists: 'Listat',
27
22
  unorderedlist: 'Liste pa renditje',
28
23
  orderedlist: 'Liste me renditje',
29
24
  outdent: 'Outdent',
@@ -43,12 +38,11 @@ var RLANG = {
43
38
  delete_column: 'Fshije kolonën',
44
39
  delete_row: 'Fshije rreshtin',
45
40
  delete_table: 'Fshije tabelën',
46
- Rows: 'Rreshta',
47
- Columns: 'Kolona',
41
+ rows: 'Rreshta',
42
+ columns: 'Kolona',
48
43
  add_head: 'Shto titujt e tabelës',
49
44
  delete_head: 'Fshije titujt e tabelës',
50
45
  title: 'Titulli',
51
- image_view: 'Shiko fotografinë',
52
46
  image_position: 'Pozita',
53
47
  none: 'Normale',
54
48
  left: 'Majtas',
@@ -71,6 +65,5 @@ var RLANG = {
71
65
  horizontalrule: 'Vizë horizontale',
72
66
  fullscreen: 'Pamje e plotë',
73
67
  deleted: 'E fshirë',
74
- none: 'None',
75
68
  anchor: 'Anchor'
76
69
  };
@@ -1,4 +1,5 @@
1
- var RLANG = {
1
+ var RELANG = {};
2
+ RELANG['tr'] = {
2
3
  html: 'HTML',
3
4
  video: 'Video',
4
5
  image: 'Görsel',
@@ -6,7 +7,7 @@ var RLANG = {
6
7
  link: 'Bağlantı',
7
8
  link_insert: 'Bağlantı Ekle ...',
8
9
  unlink: 'Bağlantı Kaldır',
9
- styles: 'Stiller',
10
+ formatting: 'Stiller',
10
11
  paragraph: 'Paragraf',
11
12
  quote: 'Alıntı',
12
13
  code: 'Kod',
@@ -14,23 +15,14 @@ var RLANG = {
14
15
  header2: 'Başlık 2',
15
16
  header3: 'Başlık 3',
16
17
  header4: 'Başlık 4',
17
- format: 'Biçim',
18
18
  bold: 'Kalın',
19
19
  italic: 'Eğik',
20
- superscript: 'Üst simge',
21
- strikethrough: 'Üstü çizili',
22
20
  fontcolor: 'Yazı rengi',
23
21
  backcolor: 'Arkaplan rengi',
24
- removeformat: 'Biçimi kaldır',
25
- cleanstyles: 'Stilleri temizle',
26
- lists: 'Listeler',
27
22
  unorderedlist: 'Sırasız liste',
28
23
  orderedlist: 'Sıralı liste',
29
24
  outdent: 'Girintiyi azalt',
30
25
  indent: 'Girintiyi artır',
31
- redo: 'Yeniden yap',
32
- undo: 'Geri al',
33
- cut: 'Kes',
34
26
  cancel: 'İptal',
35
27
  insert: 'Ekle',
36
28
  save: 'Kaydet',
@@ -43,12 +35,11 @@ var RLANG = {
43
35
  delete_column: 'Sütun sil',
44
36
  delete_row: 'Satır sil',
45
37
  delete_table: 'Tablo sil',
46
- Rows: 'Satırlar',
47
- Columns: 'Sütunlar',
38
+ rows: 'Satırlar',
39
+ columns: 'Sütunlar',
48
40
  add_head: 'Başlık ekle',
49
41
  delete_head: 'Başlık sil',
50
42
  title: 'Başlık',
51
- image_view: 'Görseli göster',
52
43
  image_position: 'Pozisyon',
53
44
  none: 'hiçbiri',
54
45
  left: 'sol',
@@ -71,6 +62,5 @@ var RLANG = {
71
62
  horizontalrule: 'Yatay çizgi',
72
63
  fullscreen: 'Tam ekran',
73
64
  deleted: 'Silindi',
74
- none: 'Hiçbiri',
75
65
  anchor: 'Çapa'
76
66
  };
@@ -1,4 +1,5 @@
1
- var RLANG = {
1
+ var RELANG = {};
2
+ RELANG['ua'] = {
2
3
  html: 'Код',
3
4
  video: 'Відео',
4
5
  image: 'Зображення',
@@ -6,7 +7,7 @@ var RLANG = {
6
7
  link: 'Посилання',
7
8
  link_insert: 'Вставити посилання ...',
8
9
  unlink: 'Видалити посилання',
9
- styles: 'Стилі',
10
+ formatting: 'Стилі',
10
11
  paragraph: 'Звичайний текст',
11
12
  quote: 'Цитата',
12
13
  code: 'Код',
@@ -14,23 +15,14 @@ var RLANG = {
14
15
  header2: 'Заголовок 2',
15
16
  header3: 'Заголовок 3',
16
17
  header4: 'Заголовок 4',
17
- format: 'Формат',
18
18
  bold: 'Жирний',
19
19
  italic: 'Похилий',
20
- superscript: 'Надрядковий',
21
- strikethrough: 'Закреслений',
22
20
  fontcolor: 'Колір тексту',
23
21
  backcolor: 'Заливка тексту',
24
- removeformat: 'Видалити формат',
25
- cleanstyles: 'Видалити стилі MS Word',
26
- lists: 'Списки',
27
22
  unorderedlist: 'Звичайний список',
28
23
  orderedlist: 'Нумерований список',
29
24
  outdent: 'Зменшити відступ',
30
25
  indent: 'Збільшити відступ',
31
- redo: 'Повтор',
32
- undo: 'Скасування',
33
- cut: 'Кат / Врізка',
34
26
  cancel: 'Скасувати',
35
27
  insert: 'Вставити',
36
28
  save: 'Зберегти',
@@ -43,8 +35,8 @@ var RLANG = {
43
35
  delete_column: 'Видалити стовпець',
44
36
  delete_row: 'Видалити рядок',
45
37
  delete_table: 'Видалити таблицю',
46
- Rows: 'Рядки',
47
- Columns: 'Стовпці',
38
+ rows: 'Рядки',
39
+ columns: 'Стовпці',
48
40
  add_head: 'Додати заголовок',
49
41
  delete_head: 'Видалити заголовок',
50
42
  title: 'Підказка',
@@ -71,5 +63,5 @@ var RLANG = {
71
63
  horizontalrule: 'Горизонтальная линейка',
72
64
  fullscreen: 'Во весь экран',
73
65
  deleted: 'Зачеркнутый',
74
- none: 'Нет'
66
+ anchor: 'Anchor'
75
67
  };
@@ -1,5 +1,6 @@
1
1
  //@chen1706@gmail.com
2
- var RLANG = {
2
+ var RELANG = {};
3
+ RELANG['zh_cn'] = {
3
4
  html: 'HTML代码',
4
5
  video: '视频',
5
6
  image: '图片',
@@ -7,7 +8,7 @@ var RLANG = {
7
8
  link: '链接',
8
9
  link_insert: '插入链接',
9
10
  unlink: '取消链接',
10
- styles: '样式',
11
+ formatting: '样式',
11
12
  paragraph: '段落',
12
13
  quote: '引用',
13
14
  code: '代码',
@@ -15,23 +16,14 @@ var RLANG = {
15
16
  header2: '二级标题',
16
17
  header3: '三级标题',
17
18
  header4: '四级标题',
18
- format: '格式',
19
19
  bold: '粗体',
20
20
  italic: '斜体',
21
- superscript: '上标',
22
- strikethrough: '删除线',
23
21
  fontcolor: '字体颜色',
24
22
  backcolor: '背景颜色',
25
- removeformat: '取消格式',
26
- cleanstyles: '清除样式',
27
- lists: '目录',
28
23
  unorderedlist: '项目编号',
29
24
  orderedlist: '数字编号',
30
25
  outdent: '减少缩进',
31
26
  indent: '增加缩进',
32
- redo: '重做',
33
- undo: '撤销',
34
- cut: '剪切',
35
27
  cancel: '取消',
36
28
  insert: '插入',
37
29
  save: '保存',
@@ -44,12 +36,11 @@ var RLANG = {
44
36
  delete_column: '删除整列',
45
37
  delete_row: '删除整行',
46
38
  delete_table: '删除表格',
47
- Rows: '行',
48
- Columns: '列',
39
+ rows: '行',
40
+ columns: '列',
49
41
  add_head: '添加标题',
50
42
  delete_head: '删除标题',
51
43
  title: '标题',
52
- image_view: '查看图片',
53
44
  image_position: '位置',
54
45
  none: '无',
55
46
  left: '左',
@@ -72,6 +63,5 @@ var RLANG = {
72
63
  horizontalrule: '水平线',
73
64
  fullscreen: '全屏',
74
65
  deleted: '删除',
75
- none: '无',
76
66
  anchor: '锚点'
77
67
  };
@@ -1,4 +1,5 @@
1
- var RLANG = {
1
+ var RLANG = {};
2
+ RELANG['zh_tw'] = {
2
3
  html: '原始碼',
3
4
  video: '影片',
4
5
  image: '圖片',
@@ -6,7 +7,7 @@ var RLANG = {
6
7
  link: '超連結',
7
8
  link_insert: '插入超連結',
8
9
  unlink: '取消超連結',
9
- styles: '樣式',
10
+ formatting: '樣式',
10
11
  paragraph: '段落',
11
12
  quote: '引用',
12
13
  code: '程式碼',
@@ -14,41 +15,31 @@ var RLANG = {
14
15
  header2: '標題 2',
15
16
  header3: '標題 3',
16
17
  header4: '標題 4',
17
- format: '格式',
18
- bold: '粗體',
18
+ bold: '粗體',
19
19
  italic: '斜體',
20
- superscript: '上標',
21
- strikethrough: '刪除線',
22
20
  fontcolor: '字體顏色',
23
21
  backcolor: '背景顏色',
24
- removeformat: '取消格式',
25
- cleanstyles: '清除樣式',
26
- lists: '列表',
27
22
  unorderedlist: '項號編號',
28
- orderedlist: '數字編號',
23
+ orderedlist: '數字編號',
29
24
  outdent: '減少縮排',
30
25
  indent: '增加縮排',
31
- redo: '取消復原',
32
- undo: '復原',
33
- cut: '剪下',
34
- cancel: '取消',
26
+ cancel: '取消',
35
27
  insert: '貼上',
36
- save: '儲存',
28
+ save: '儲存',
37
29
  _delete: '刪除',
38
- insert_table: '插入表格',
30
+ insert_table: '插入表格',
39
31
  insert_row_above: '從上方插入',
40
32
  insert_row_below: '從下方插入',
41
33
  insert_column_left: '從左側插入',
42
- insert_column_right: '從右側插入',
43
- delete_column: '刪除整列',
44
- delete_row: '刪除整行',
34
+ insert_column_right: '從右側插入',
35
+ delete_column: '刪除整列',
36
+ delete_row: '刪除整行',
45
37
  delete_table: '刪除表格',
46
- Rows: '行',
47
- Columns: '列',
38
+ rows: '行',
39
+ columns: '列',
48
40
  add_head: '新增標題',
49
- delete_head: '刪除標題',
41
+ delete_head: '刪除標題',
50
42
  title: '標題',
51
- image_view: '圖片內容',
52
43
  image_position: '位置',
53
44
  none: '無',
54
45
  left: '左',
@@ -58,19 +49,18 @@ var RLANG = {
58
49
  mailto: '電子郵件信箱',
59
50
  web: '網址',
60
51
  video_html_code: '影片嵌入程式碼',
61
- file: '檔案',
52
+ file: '檔案',
62
53
  upload: '上傳',
63
54
  download: '下載',
64
55
  choose: '選擇',
65
56
  or_choose: '或選擇',
66
57
  drop_file_here: '把檔案拖曳到這邊',
67
- align_left: '靠左對齊',
58
+ align_left: '靠左對齊',
68
59
  align_center: '文字置中',
69
60
  align_right: '靠右對齊',
70
61
  align_justify: '左右對齊',
71
62
  horizontalrule: '水平線',
72
63
  fullscreen: '全螢幕',
73
64
  deleted: '刪除線',
74
- none: '無',
75
65
  anchor: '錨點'
76
66
  };
@@ -1,28 +1,105 @@
1
1
  /*
2
- Redactor v7.6.3
3
- Updated 31.05.2012
2
+ Redactor v7.7.0
3
+ Updated 27.06.2012
4
4
 
5
5
  http://redactorjs.com/
6
-
6
+
7
7
  Copyright (c) 2009-2012, Imperavi Ltd.
8
- Licensed under Creative Commons Attribution-NonCommercial 3.0 license.
8
+ License: http://redactorjs.com/license/
9
9
 
10
- Usage: $('#content').redactor();
10
+ Usage: $('#content').redactor();
11
11
  */
12
12
 
13
- var RTOOLBAR = {};
13
+ if (typeof RELANG === 'undefined')
14
+ {
15
+ var RELANG = {};
16
+ }
17
+
18
+ var RLANG = {
19
+ html: 'HTML',
20
+ video: 'Insert Video...',
21
+ image: 'Insert Image...',
22
+ table: 'Table',
23
+ link: 'Link',
24
+ link_insert: 'Insert Link ...',
25
+ unlink: 'Unlink',
26
+ formatting: 'Formatting',
27
+ paragraph: 'Paragraph',
28
+ quote: 'Quote',
29
+ code: 'Code',
30
+ header1: 'Header 1',
31
+ header2: 'Header 2',
32
+ header3: 'Header 3',
33
+ header4: 'Header 4',
34
+ bold: 'Bold',
35
+ italic: 'Italic',
36
+ fontcolor: 'Font Color',
37
+ backcolor: 'Back Color',
38
+ unorderedlist: 'Unordered List',
39
+ orderedlist: 'Ordered List',
40
+ outdent: 'Outdent',
41
+ indent: 'Indent',
42
+ cancel: 'Cancel',
43
+ insert: 'Insert',
44
+ save: 'Save',
45
+ _delete: 'Delete',
46
+ insert_table: 'Insert Table...',
47
+ insert_row_above: 'Add Row Above',
48
+ insert_row_below: 'Add Row Below',
49
+ insert_column_left: 'Add Column Left',
50
+ insert_column_right: 'Add Column Right',
51
+ delete_column: 'Delete Column',
52
+ delete_row: 'Delete Row',
53
+ delete_table: 'Delete Table',
54
+ rows: 'Rows',
55
+ columns: 'Columns',
56
+ add_head: 'Add Head',
57
+ delete_head: 'Delete Head',
58
+ title: 'Title',
59
+ image_position: 'Position',
60
+ none: 'None',
61
+ left: 'Left',
62
+ right: 'Right',
63
+ image_web_link: 'Image Web Link',
64
+ text: 'Text',
65
+ mailto: 'Email',
66
+ web: 'URL',
67
+ video_html_code: 'Video Embed Code',
68
+ file: 'Insert File...',
69
+ upload: 'Upload',
70
+ download: 'Download',
71
+ choose: 'Choose',
72
+ or_choose: 'Or choose',
73
+ drop_file_here: 'Drop file here',
74
+ align_left: 'Align Left',
75
+ align_center: 'Align Center',
76
+ align_right: 'Align Right',
77
+ align_justify: 'Justify',
78
+ horizontalrule: 'Insert Horizontal Rule',
79
+ fullscreen: 'Fullscreen',
80
+ deleted: 'Deleted',
81
+ anchor: 'Anchor'
82
+ };
83
+
84
+
85
+
14
86
 
15
87
  (function($){
16
88
 
89
+ "use strict";
90
+
17
91
  // Plugin
18
92
  jQuery.fn.redactor = function(option)
19
93
  {
20
94
  return this.each(function()
21
95
  {
22
- var $this = $(this);
96
+ var $obj = $(this);
23
97
 
24
- var data = $this.data('redactor');
25
- if (!data) $this.data('redactor', (data = new Redactor(this, option)));
98
+ var data = $obj.data('redactor');
99
+ if (!data)
100
+ {
101
+ $obj.data('redactor', (data = new Redactor(this, option)));
102
+ }
26
103
  });
27
104
  };
28
105
 
@@ -32,28 +109,38 @@ var RTOOLBAR = {};
32
109
  {
33
110
  // Element
34
111
  this.$el = $(element);
112
+
113
+ // Lang
114
+ if (typeof options !== 'undefined' && typeof options.lang !== 'undefined' && options.lang !== 'en' && typeof RELANG[options.lang] !== 'undefined')
115
+ {
116
+ RLANG = RELANG[options.lang];
117
+ }
35
118
 
36
119
  // Options
37
120
  this.opts = $.extend({
38
121
 
39
122
  lang: 'en',
40
- toolbar: 'default',
123
+ direction: 'ltr', // ltr or rtl
41
124
 
42
- load: true,
125
+ callback: false, // function
126
+ keyupCallback: false, // function
127
+ keydownCallback: false, // function
128
+ execCommandCallback: false, // function
43
129
 
44
130
  path: false,
45
131
  css: 'style.css',
46
- focus: true,
132
+ focus: false,
47
133
  resize: true,
48
134
  autoresize: false,
49
135
  fixed: false,
50
136
 
51
137
  autoformat: true,
52
138
  cleanUp: true,
53
- convertDivs: true,
54
- removeClasses: true,
55
139
  removeStyles: false,
140
+ removeClasses: false,
141
+ convertDivs: true,
56
142
  convertLinks: true,
143
+ xhtml: false,
57
144
 
58
145
  handler: false, // false or url
59
146
 
@@ -63,25 +150,376 @@ var RTOOLBAR = {};
63
150
  imageGetJson: false, // url (ex. /folder/images.json ) or false
64
151
 
65
152
  imageUpload: false, // url
66
- linkFileUpload: false, // url
153
+ imageUploadCallback: false, // function
154
+
67
155
  fileUpload: false, // url
156
+ fileUploadCallback: false, // function
68
157
 
69
158
  visual: true,
70
159
  fullscreen: false,
71
160
  overlay: true, // modal overlay
72
-
73
- colors: Array(
161
+
162
+ buttonsCustom: {},
163
+ buttonsAdd: [],
164
+ buttons: ['html', '|', 'formatting', '|', 'bold', 'italic', 'deleted', '|', 'unorderedlist', 'orderedlist', 'outdent', 'indent', '|',
165
+ 'image', 'video', 'file', 'table', 'link', '|',
166
+ 'fontcolor', 'backcolor', '|', 'alignleft', 'aligncenter', 'alignright', 'justify', '|',
167
+ 'horizontalrule', 'fullscreen'],
168
+
169
+ colors: [
74
170
  '#ffffff', '#000000', '#eeece1', '#1f497d', '#4f81bd', '#c0504d', '#9bbb59', '#8064a2', '#4bacc6', '#f79646', '#ffff00',
75
171
  '#f2f2f2', '#7f7f7f', '#ddd9c3', '#c6d9f0', '#dbe5f1', '#f2dcdb', '#ebf1dd', '#e5e0ec', '#dbeef3', '#fdeada', '#fff2ca',
76
172
  '#d8d8d8', '#595959', '#c4bd97', '#8db3e2', '#b8cce4', '#e5b9b7', '#d7e3bc', '#ccc1d9', '#b7dde8', '#fbd5b5', '#ffe694',
77
173
  '#bfbfbf', '#3f3f3f', '#938953', '#548dd4', '#95b3d7', '#d99694', '#c3d69b', '#b2a2c7', '#b7dde8', '#fac08f', '#f2c314',
78
174
  '#a5a5a5', '#262626', '#494429', '#17365d', '#366092', '#953734', '#76923c', '#5f497a', '#92cddc', '#e36c09', '#c09100',
79
- '#7f7f7f', '#0c0c0c', '#1d1b10', '#0f243e', '#244061', '#632423', '#4f6128', '#3f3151', '#31859b', '#974806', '#7f6000'),
175
+ '#7f7f7f', '#0c0c0c', '#1d1b10', '#0f243e', '#244061', '#632423', '#4f6128', '#3f3151', '#31859b', '#974806', '#7f6000'],
80
176
 
81
177
  // private
82
178
  allEmptyHtml: '<p><br /></p>',
83
- mozillaEmptyHtml: '<p>&nbsp;</p>'
84
-
179
+ mozillaEmptyHtml: '<p>&nbsp;</p>',
180
+
181
+ // modal windows container
182
+ modal_file: String() +
183
+ '<form id="redactorUploadFileForm" method="post" action="" enctype="multipart/form-data">' +
184
+ '<label>Name (optional)</label>' +
185
+ '<input type="text" id="redactor_filename" class="redactor_input" />' +
186
+ '<div style="margin-top: 7px;">' +
187
+ '<input type="file" id="redactor_file" name="file" />' +
188
+ '</div>' +
189
+ '</form>',
190
+
191
+ modal_image_edit: String() +
192
+ '<label>' + RLANG.title + '</label>' +
193
+ '<input id="redactor_file_alt" class="redactor_input" />' +
194
+ '<label>' + RLANG.link + '</label>' +
195
+ '<input id="redactor_file_link" class="redactor_input" />' +
196
+ '<label>' + RLANG.image_position + '</label>' +
197
+ '<select id="redactor_form_image_align">' +
198
+ '<option value="none">' + RLANG.none + '</option>' +
199
+ '<option value="left">' + RLANG.left + '</option>' +
200
+ '<option value="right">' + RLANG.right + '</option>' +
201
+ '</select>' +
202
+ '<div id="redactor_modal_footer">' +
203
+ '<a href="javascript:void(null);" id="redactor_image_delete_btn" style="color: #000;">' + RLANG._delete + '</a>' +
204
+ '<span class="redactor_btns_box">' +
205
+ '<input type="button" name="save" id="redactorSaveBtn" value="' + RLANG.save + '" />' +
206
+ '<a href="javascript:void(null);" id="redactor_btn_modal_close">' + RLANG.cancel + '</a>' +
207
+ '</span>' +
208
+ '</div>',
209
+
210
+ modal_image: String() +
211
+ '<div id="redactor_tabs">' +
212
+ '<a href="javascript:void(null);" class="redactor_tabs_act">' + RLANG.upload + '</a>' +
213
+ '<a href="javascript:void(null);">' + RLANG.choose + '</a>' +
214
+ '<a href="javascript:void(null);">' + RLANG.link + '</a>' +
215
+ '</div>' +
216
+ '<form id="redactorInsertImageForm" method="post" action="" enctype="multipart/form-data">' +
217
+ '<div id="redactor_tab1" class="redactor_tab">' +
218
+ '<input type="file" id="redactor_file" name="file" />' +
219
+ '</div>' +
220
+ '<div id="redactor_tab2" class="redactor_tab" style="display: none;">' +
221
+ '<div id="redactor_image_box"></div>' +
222
+ '</div>' +
223
+ '</form>' +
224
+ '<div id="redactor_tab3" class="redactor_tab" style="display: none;">' +
225
+ '<label>' + RLANG.image_web_link + '</label>' +
226
+ '<input name="redactor_file_link" id="redactor_file_link" class="redactor_input" />' +
227
+ '</div>' +
228
+ '<div id="redactor_modal_footer">' +
229
+ '<span class="redactor_btns_box">' +
230
+ '<input type="button" name="upload" id="redactor_upload_btn" value="' + RLANG.insert + '" />' +
231
+ '<a href="javascript:void(null);" id="redactor_btn_modal_close">' + RLANG.cancel + '</a>' +
232
+ '</span>' +
233
+ '</div>',
234
+
235
+ modal_link: String() +
236
+ '<form id="redactorInsertLinkForm" method="post" action="">' +
237
+ '<div id="redactor_tabs">' +
238
+ '<a href="javascript:void(null);" class="redactor_tabs_act">URL</a>' +
239
+ '<a href="javascript:void(null);">Email</a>' +
240
+ '<a href="javascript:void(null);">' + RLANG.anchor + '</a>' +
241
+ '</div>' +
242
+ '<input type="hidden" id="redactor_tab_selected" value="1" />' +
243
+ '<div class="redactor_tab" id="redactor_tab1">' +
244
+ '<label>URL</label><input id="redactor_link_url" class="redactor_input" />' +
245
+ '<label>' + RLANG.text + '</label><input class="redactor_input redactor_link_text" id="redactor_link_url_text" />' +
246
+ '</div>' +
247
+ '<div class="redactor_tab" id="redactor_tab2" style="display: none;">' +
248
+ '<label>Email</label><input id="redactor_link_mailto" class="redactor_input" />' +
249
+ '<label>' + RLANG.text + '</label><input class="redactor_input redactor_link_text" id="redactor_link_mailto_text" />' +
250
+ '</div>' +
251
+ '<div class="redactor_tab" id="redactor_tab3" style="display: none;">' +
252
+ '<label>' + RLANG.anchor + '</label><input class="redactor_input" id="redactor_link_anchor" />' +
253
+ '<label>' + RLANG.text + '</label><input class="redactor_input redactor_link_text" id="redactor_link_anchor_text" />' +
254
+ '</div>' +
255
+ '</form>' +
256
+ '<div id="redactor_modal_footer">' +
257
+ '<span class="redactor_btns_box">' +
258
+ '<input type="button" id="redactor_insert_link_btn" value="' + RLANG.insert + '" />' +
259
+ '<a href="javascript:void(null);" id="redactor_btn_modal_close">' + RLANG.cancel + '</a>' +
260
+ '</span>' +
261
+ '</div>',
262
+
263
+ modal_table: String() +
264
+ '<label>' + RLANG.rows + '</label>' +
265
+ '<input size="5" value="2" id="redactor_table_rows" />' +
266
+ '<label>' + RLANG.columns + '</label>' +
267
+ '<input size="5" value="3" id="redactor_table_columns" />' +
268
+ '<div id="redactor_modal_footer">' +
269
+ '<span class="redactor_btns_box">' +
270
+ '<input type="button" name="upload" id="redactor_insert_table_btn" value="' + RLANG.insert + '" />' +
271
+ '<a href="javascript:void(null);" id="redactor_btn_modal_close">' + RLANG.cancel + '</a>' +
272
+ '</span>' +
273
+ '</div>',
274
+
275
+ modal_video: String() +
276
+ '<form id="redactorInsertVideoForm">' +
277
+ '<label>' + RLANG.video_html_code + '</label>' +
278
+ '<textarea id="redactor_insert_video_area" style="width: 99%; height: 160px;"></textarea>' +
279
+ '</form>' +
280
+ '<div id="redactor_modal_footer">' +
281
+ '<span class="redactor_btns_box">' +
282
+ '<input type="button" id="redactor_insert_video_btn" value="' + RLANG.insert + '" />' +
283
+ '<a href="javascript:void(null);" id="redactor_btn_modal_close">' + RLANG.cancel + '</a>' +
284
+ '</span>' +
285
+ '</div>',
286
+
287
+
288
+ toolbar: {
289
+ html:
290
+ {
291
+ title: RLANG.html,
292
+ func: 'toggle'
293
+ },
294
+ formatting:
295
+ {
296
+ title: RLANG.formatting,
297
+ func: 'show',
298
+ dropdown:
299
+ {
300
+ p:
301
+ {
302
+ title: RLANG.paragraph,
303
+ exec: 'formatblock'
304
+ },
305
+ blockquote:
306
+ {
307
+ title: RLANG.quote,
308
+ exec: 'formatblock',
309
+ className: 'redactor_format_blockquote'
310
+ },
311
+ pre:
312
+ {
313
+ title: RLANG.code,
314
+ exec: 'formatblock',
315
+ className: 'redactor_format_pre'
316
+ },
317
+ h1:
318
+ {
319
+ title: RLANG.header1,
320
+ exec: 'formatblock',
321
+ className: 'redactor_format_h1'
322
+ },
323
+ h2:
324
+ {
325
+ title: RLANG.header2,
326
+ exec: 'formatblock',
327
+ className: 'redactor_format_h2'
328
+ },
329
+ h3:
330
+ {
331
+ title: RLANG.header3,
332
+ exec: 'formatblock',
333
+ className: 'redactor_format_h3'
334
+ },
335
+ h4:
336
+ {
337
+ title: RLANG.header4,
338
+ exec: 'formatblock',
339
+ className: 'redactor_format_h4'
340
+ }
341
+ }
342
+ },
343
+ bold:
344
+ {
345
+ title: RLANG.bold,
346
+ exec: 'bold'
347
+ },
348
+ italic:
349
+ {
350
+ title: RLANG.italic,
351
+ exec: 'italic'
352
+ },
353
+ deleted:
354
+ {
355
+ title: RLANG.deleted,
356
+ exec: 'strikethrough'
357
+ },
358
+ unorderedlist:
359
+ {
360
+ title: '&bull; ' + RLANG.unorderedlist,
361
+ exec: 'insertunorderedlist'
362
+ },
363
+ orderedlist:
364
+ {
365
+ title: '1. ' + RLANG.orderedlist,
366
+ exec: 'insertorderedlist'
367
+ },
368
+ outdent:
369
+ {
370
+ title: '< ' + RLANG.outdent,
371
+ exec: 'outdent'
372
+ },
373
+ indent:
374
+ {
375
+ title: '> ' + RLANG.indent,
376
+ exec: 'indent'
377
+ },
378
+ image:
379
+ {
380
+ title: RLANG.image,
381
+ func: 'showImage'
382
+ },
383
+ video:
384
+ {
385
+ title: RLANG.video,
386
+ func: 'showVideo'
387
+ },
388
+ file:
389
+ {
390
+ title: RLANG.file,
391
+ func: 'showFile'
392
+ },
393
+ table:
394
+ {
395
+ title: RLANG.table,
396
+ func: 'show',
397
+ dropdown:
398
+ {
399
+ insert_table:
400
+ {
401
+ title: RLANG.insert_table,
402
+ func: 'showTable'
403
+ },
404
+ separator_drop1:
405
+ {
406
+ name: 'separator'
407
+ },
408
+ insert_row_above:
409
+ {
410
+ title: RLANG.insert_row_above,
411
+ func: 'insertRowAbove'
412
+ },
413
+ insert_row_below:
414
+ {
415
+ title: RLANG.insert_row_below,
416
+ func: 'insertRowBelow'
417
+ },
418
+ insert_column_left:
419
+ {
420
+ title: RLANG.insert_column_left,
421
+ func: 'insertColumnLeft'
422
+ },
423
+ insert_column_right:
424
+ {
425
+ title: RLANG.insert_column_right,
426
+ func: 'insertColumnRight'
427
+ },
428
+ separator_drop2:
429
+ {
430
+ name: 'separator'
431
+ },
432
+ add_head:
433
+ {
434
+ title: RLANG.add_head,
435
+ func: 'addHead'
436
+ },
437
+ delete_head:
438
+ {
439
+ title: RLANG.delete_head,
440
+ func: 'deleteHead'
441
+ },
442
+ separator_drop3:
443
+ {
444
+ name: 'separator'
445
+ },
446
+ delete_column:
447
+ {
448
+ title: RLANG.delete_column,
449
+ func: 'deleteColumn'
450
+ },
451
+ delete_row:
452
+ {
453
+ title: RLANG.delete_row,
454
+ func: 'deleteRow'
455
+ },
456
+ delete_table:
457
+ {
458
+ title: RLANG.delete_table,
459
+ func: 'deleteTable'
460
+ }
461
+ }
462
+ },
463
+ link:
464
+ {
465
+ title: RLANG.link,
466
+ func: 'show',
467
+ dropdown:
468
+ {
469
+ link:
470
+ {
471
+ title: RLANG.link_insert,
472
+ func: 'showLink'
473
+ },
474
+ unlink:
475
+ {
476
+ title: RLANG.unlink,
477
+ exec: 'unlink'
478
+ }
479
+ }
480
+ },
481
+ fontcolor:
482
+ {
483
+ title: RLANG.fontcolor,
484
+ func: 'show'
485
+ },
486
+ backcolor:
487
+ {
488
+ title: RLANG.backcolor,
489
+ func: 'show'
490
+ },
491
+ alignleft:
492
+ {
493
+ exec: 'JustifyLeft',
494
+ title: RLANG.align_left
495
+ },
496
+ aligncenter:
497
+ {
498
+ exec: 'JustifyCenter',
499
+ title: RLANG.align_center
500
+ },
501
+ alignright:
502
+ {
503
+ exec: 'JustifyRight',
504
+ title: RLANG.align_right
505
+ },
506
+ justify:
507
+ {
508
+ exec: 'justifyfull',
509
+ title: RLANG.align_justify
510
+ },
511
+ horizontalrule:
512
+ {
513
+ exec: 'inserthorizontalrule',
514
+ title: RLANG.horizontalrule
515
+ },
516
+ fullscreen:
517
+ {
518
+ title: RLANG.fullscreen,
519
+ func: 'fullscreen'
520
+ }
521
+ }
522
+
85
523
 
86
524
  }, options, this.$el.data());
87
525
 
@@ -94,70 +532,22 @@ var RTOOLBAR = {};
94
532
  // Functionality
95
533
  Redactor.prototype = {
96
534
 
97
- // DYNAMICALLY LOAD
98
- _loadFile: function(file, array)
99
- {
100
- var item = array[0];
101
- array.splice(0, 1);
102
-
103
- var callback;
104
- if (typeof(item) == 'function') callback = item;
105
- else callback = $.proxy(function() { this._loadFile(item, array); }, this);
106
-
107
- this.dynamicallyLoad(file, callback);
108
- },
109
- loadFiles: function(array)
110
- {
111
- var item = array[0];
112
- array.splice(0, 1);
113
-
114
- this._loadFile(item, array);
115
- },
116
- dynamicallyLoad: function (url, callback)
117
- {
118
- var head = document.getElementsByTagName("head")[0];
119
- var script = document.createElement("script");
120
- script.src = url;
121
-
122
- var done = false;
123
-
124
- script.onload = script.onreadystatechange = function()
125
- {
126
- if (!done && (!this.readyState || this.readyState == "loaded" || this.readyState == "complete"))
127
- {
128
- done = true;
129
- if (callback) callback();
130
- script.onload = script.onreadystatechange = null;
131
- }
132
- };
133
-
134
- head.appendChild(script);
135
-
136
- },
137
535
 
138
536
  // Initialization
139
537
  init: function()
140
538
  {
141
539
  // get path to styles
142
540
  this.getPath();
143
-
144
- if (this.opts.load)
541
+
542
+ if (this.opts.toolbar !== false)
145
543
  {
146
- // load files
147
- var files = [];
148
-
149
- files.push(this.opts.path + '/langs/' + this.opts.lang + '.js');
150
- if (this.opts.toolbar !== false) files.push(this.opts.path + '/toolbars/' + this.opts.toolbar + '.js');
151
- files.push($.proxy(this.start, this));
152
-
153
- this.loadFiles(files);
544
+ $.extend(this.opts.toolbar, this.opts.buttonsCustom);
545
+
546
+ $.each(this.opts.buttonsAdd, $.proxy(function(i,s)
547
+ {
548
+ this.opts.buttons.push(s);
549
+ }, this));
154
550
  }
155
- else this.start();
156
-
157
-
158
- },
159
- start: function()
160
- {
161
551
 
162
552
  // get dimensions
163
553
  this.height = this.$el.css('height');
@@ -171,56 +561,59 @@ var RTOOLBAR = {};
171
561
 
172
562
  // preformatter
173
563
  html = this.preformater(html);
174
-
175
- // conver newlines to p
176
- if (this.opts.autoformat) html = this.paragraphy(html);
177
564
 
178
565
  // enable
179
566
  this.$editor = this.enable(html);
180
567
 
181
568
  // focus always on page
182
- $(this.doc).click($.proxy(function(e) { this.$editor.focus(); }, this));
569
+ this.observeFocus();
183
570
 
184
571
  // cleanup
185
- $(this.doc).bind('paste', $.proxy(function(e)
186
- {
187
- setTimeout($.proxy(function ()
188
- {
189
- var node = $('<span id="pastemarkerend">&nbsp;</span>');
190
- this.insertNodeAtCaret(node.get(0));
191
-
192
- this.pasteCleanUp();
193
-
194
- }, this), 200);
195
-
196
-
197
-
198
- }, this));
199
-
200
- // keypress
201
- $(this.doc).keypress($.proxy(function(e)
572
+ if (this.opts.cleanUp === true)
202
573
  {
203
- var key = e.keyCode || e.which;
204
-
205
- // safari shift key + enter
206
- if (navigator.userAgent.indexOf('AppleWebKit') != -1) return this.safariShiftKeyEnter(e, key);
207
-
208
- }, this))
574
+ $(this.doc).bind('paste', $.proxy(function(e)
575
+ {
576
+ setTimeout($.proxy(function ()
577
+ {
578
+ var marker = Math.floor(Math.random() * 99999);
579
+ var marker_text = '';
580
+ if ($.browser.mozilla) marker_text = '&nbsp;';
581
+ var node = $('<span rel="pastemarkerend" id="pastemarkerend' + marker + '">' + marker_text + '</span>');
582
+ this.insertNodeAtCaret(node.get(0));
583
+
584
+ this.pasteCleanUp(marker);
585
+
586
+ }, this), 100);
587
+
588
+ }, this));
589
+ }
209
590
 
210
591
  // keyup
211
- .keyup($.proxy(function(e)
592
+ $(this.doc).keyup($.proxy(function(e)
212
593
  {
213
594
  var key = e.keyCode || e.which;
214
595
 
596
+ // callback as you type
597
+ if (typeof this.opts.keyupCallback === 'function')
598
+ {
599
+ this.opts.keyupCallback(this, e);
600
+ }
601
+
215
602
  if (this.opts.autoformat)
216
603
  {
217
604
  // if empty
218
- if (key == 8 || key == 46) return this.formatEmpty(e);
605
+ if (key === 8 || key === 46)
606
+ {
607
+ return this.formatEmpty(e);
608
+ }
219
609
 
220
610
  // new line p
221
- if (key == 13 && !e.shiftKey && !e.ctrlKey && !e.metaKey) return this.formatNewLine(e);
611
+ if (key === 13 && !e.shiftKey && !e.ctrlKey && !e.metaKey)
612
+ {
613
+ return this.formatNewLine(e);
614
+ }
222
615
  }
223
- //console.log(e);
616
+
224
617
  this.syncCode();
225
618
 
226
619
  }, this));
@@ -229,8 +622,14 @@ var RTOOLBAR = {};
229
622
  this.buildToolbar();
230
623
 
231
624
  // resizer
232
- if (this.opts.autoresize === false) this.buildResizer();
233
- else this.observeAutoResize();
625
+ if (this.opts.autoresize === false)
626
+ {
627
+ this.buildResizer();
628
+ }
629
+ else
630
+ {
631
+ this.observeAutoResize();
632
+ }
234
633
 
235
634
  // shortcuts
236
635
  this.shortcuts();
@@ -240,6 +639,7 @@ var RTOOLBAR = {};
240
639
 
241
640
  // observers
242
641
  this.observeImages();
642
+ this.observeTables();
243
643
 
244
644
  // fullscreen on start
245
645
  if (this.opts.fullscreen)
@@ -249,7 +649,10 @@ var RTOOLBAR = {};
249
649
  }
250
650
 
251
651
  // focus
252
- if (this.opts.focus) this.focus();
652
+ if (this.opts.focus)
653
+ {
654
+ this.focus();
655
+ }
253
656
 
254
657
  // fixed
255
658
  if (this.opts.fixed)
@@ -257,6 +660,13 @@ var RTOOLBAR = {};
257
660
  this.observeScroll();
258
661
  $(document).scroll($.proxy(this.observeScroll, this));
259
662
  }
663
+
664
+ // callback
665
+ if (typeof this.opts.callback === 'function')
666
+ {
667
+ this.opts.callback(this);
668
+ }
669
+
260
670
  },
261
671
  shortcuts: function()
262
672
  {
@@ -264,40 +674,95 @@ var RTOOLBAR = {};
264
674
  {
265
675
  var key = e.keyCode || e.which;
266
676
 
677
+ // callback keydown
678
+ if (typeof this.opts.keydownCallback === 'function')
679
+ {
680
+ this.opts.keydownCallback(this, e);
681
+ }
682
+
267
683
  if (e.ctrlKey)
268
684
  {
269
- if (key == 90) this._shortcuts(e, 'undo'); // Ctrl + z
270
- else if (key == 90 && e.shiftKey) this._shortcuts(e, 'redo'); // Ctrl + Shift + z
271
- else if (key == 77) this._shortcuts(e, 'removeFormat'); // Ctrl + m
272
- else if (key == 66) this._shortcuts(e, 'bold'); // Ctrl + b
273
- else if (key == 73) this._shortcuts(e, 'italic'); // Ctrl + i
274
- else if (key == 74) this._shortcuts(e, 'insertunorderedlist'); // Ctrl + j
275
- else if (key == 75) this._shortcuts(e, 'insertorderedlist'); // Ctrl + k
276
- else if (key == 76) this._shortcuts(e, 'superscript'); // Ctrl + l
685
+ if (key === 90)
686
+ {
687
+ this._shortcuts(e, 'undo'); // Ctrl + z
688
+ }
689
+ else if (key === 90 && e.shiftKey)
690
+ {
691
+ this._shortcuts(e, 'redo'); // Ctrl + Shift + z
692
+ }
693
+ else if (key === 77)
694
+ {
695
+ this._shortcuts(e, 'removeFormat'); // Ctrl + m
696
+ }
697
+ else if (key === 66)
698
+ {
699
+ this._shortcuts(e, 'bold'); // Ctrl + b
700
+ }
701
+ else if (key === 73)
702
+ {
703
+ this._shortcuts(e, 'italic'); // Ctrl + i
704
+ }
705
+ else if (key === 74)
706
+ {
707
+ this._shortcuts(e, 'insertunorderedlist'); // Ctrl + j
708
+ }
709
+ else if (key === 75)
710
+ {
711
+ this._shortcuts(e, 'insertorderedlist'); // Ctrl + k
712
+ }
713
+ else if (key === 76)
714
+ {
715
+ this._shortcuts(e, 'superscript'); // Ctrl + l
716
+ }
717
+ else if (key === 72)
718
+ {
719
+ this._shortcuts(e, 'subscript'); // Ctrl + h
720
+ }
277
721
  }
278
722
 
279
- if (!e.shiftKey && key == 9) this._shortcuts(e, 'indent'); // Tab
280
- else if (e.shiftKey && key == 9 ) this._shortcuts(e, 'outdent'); // Shift + tab
723
+ if (!e.shiftKey && key === 9)
724
+ {
725
+ this._shortcuts(e, 'indent'); // Tab
726
+ }
727
+ else if (e.shiftKey && key === 9 )
728
+ {
729
+ this._shortcuts(e, 'outdent'); // Shift + tab
730
+ }
731
+
732
+ // safari shift key + enter
733
+ if ($.browser.webkit && navigator.userAgent.indexOf('Chrome') === -1)
734
+ {
735
+ return this.safariShiftKeyEnter(e, key);
736
+ }
281
737
 
282
738
  }, this));
283
739
 
284
740
  },
285
741
  _shortcuts: function(e, cmd)
286
742
  {
287
- if (e.preventDefault) e.preventDefault();
743
+ if (e.preventDefault)
744
+ {
745
+ e.preventDefault();
746
+ }
288
747
  this.execCommand(cmd, null);
289
748
  },
290
749
  getPath: function()
291
750
  {
292
- if (this.opts.path !== false) return this.opts.path;
751
+ if (this.opts.path !== false)
752
+ {
753
+ return this.opts.path;
754
+ }
293
755
 
294
756
  $('script').each($.proxy(function(i,s)
295
757
  {
296
758
  if (s.src)
297
759
  {
298
- // Match redactor.js or redactor.min.js, followed by an optional querystring (often used for cache purposes)
760
+ // Match redactor.js or redactor.min.js, followed by an optional querystring (often used for cache purposes)
299
761
  var regexp = new RegExp(/\/redactor(\.min)?\.js(\?.*)?/);
300
- if (s.src.match(regexp)) this.opts.path = s.src.replace(regexp, '');
762
+ if (s.src.match(regexp))
763
+ {
764
+ this.opts.path = s.src.replace(regexp, '');
765
+ }
301
766
  }
302
767
  }, this));
303
768
 
@@ -330,26 +795,45 @@ var RTOOLBAR = {};
330
795
  if (this.doc !== null)
331
796
  {
332
797
  this.write(this.setDoc(html));
333
- if ($.browser.mozilla) this.doc.execCommand("useCSS", false, true);
798
+ if ($.browser.mozilla)
799
+ {
800
+ this.doc.execCommand("useCSS", false, true);
801
+ }
334
802
  return $(this.doc).find('#page');
335
803
  }
336
- else return false;
804
+ else
805
+ {
806
+ return false;
807
+ }
337
808
  },
338
809
  setDoc: function(html)
339
810
  {
340
- var frameHtml = '<!DOCTYPE html>\n';
341
- frameHtml += '<html><head><link media="all" type="text/css" href="' + this.opts.path + '/css/' + this.opts.css + '" rel="stylesheet"></head>';
342
- frameHtml += '<body><div id="page" contenteditable="true">';
343
- frameHtml += html;
344
- frameHtml += '</div></body></html>';
811
+ var frameHtml = '<!DOCTYPE html>\n' +
812
+ '<html><head><link media="all" type="text/css" href="' + this.opts.path + '/css/' + this.opts.css + '" rel="stylesheet"></head>' +
813
+ '<body><div id="page" contenteditable="true" dir="' + this.opts.direction + '">' +
814
+ html +
815
+ '</div></body></html>';
816
+
345
817
  return frameHtml;
346
818
  },
347
819
  getDoc: function(frame)
348
820
  {
349
- if (frame.contentDocument) return frame.contentDocument;
350
- else if (frame.contentWindow && frame.contentWindow.document) return frame.contentWindow.document;
351
- else if (frame.document) return frame.document;
352
- else return null;
821
+ if (frame.contentDocument)
822
+ {
823
+ return frame.contentDocument;
824
+ }
825
+ else if (frame.contentWindow && frame.contentWindow.document)
826
+ {
827
+ return frame.contentWindow.document;
828
+ }
829
+ else if (frame.document)
830
+ {
831
+ return frame.document;
832
+ }
833
+ else
834
+ {
835
+ return null;
836
+ }
353
837
  },
354
838
  focus: function()
355
839
  {
@@ -357,7 +841,7 @@ var RTOOLBAR = {};
357
841
  },
358
842
  syncCode: function()
359
843
  {
360
- var html = this.formating(this.$editor.html());
844
+ var html = this.formatting(this.$editor.html());
361
845
  this.$el.val(html);
362
846
  },
363
847
 
@@ -380,6 +864,7 @@ var RTOOLBAR = {};
380
864
  insertHtml: function(html)
381
865
  {
382
866
  this.execCommand('inserthtml', html);
867
+ this.observeImages();
383
868
  },
384
869
  destroy: function()
385
870
  {
@@ -389,17 +874,18 @@ var RTOOLBAR = {};
389
874
  this.$box.remove();
390
875
  this.$el.val(html).show();
391
876
 
392
- this.dropdowns.forEach(function(dropdown, i)
877
+ for (var i = 0; i < this.dropdowns.length; i++)
393
878
  {
394
- dropdown.remove();
879
+ this.dropdowns[i].remove();
395
880
  delete(this.dropdowns[i]);
396
- }, this);
881
+ }
882
+
397
883
  },
398
884
  handler: function()
399
885
  {
400
886
  $.ajax({
401
887
  url: this.opts.handler,
402
- type: 'post',
888
+ type: 'POST',
403
889
  data: 'redactor=' + escape(encodeURIComponent(this.getCode())),
404
890
  success: $.proxy(function(data)
405
891
  {
@@ -413,17 +899,32 @@ var RTOOLBAR = {};
413
899
  // end API functions
414
900
 
415
901
  // OBSERVERS
902
+ observeFocus: function()
903
+ {
904
+ if ($(this.doc).find('body').height() < $(this.$frame.get(0).contentWindow).height())
905
+ {
906
+ $(this.doc).click($.proxy(function(e) { this.$editor.focus(); }, this));
907
+ }
908
+ },
416
909
  observeImages: function()
417
910
  {
418
- if ($.browser.mozilla) this.doc.execCommand("enableObjectResizing", false, "false");
911
+ if ($.browser.mozilla)
912
+ {
913
+ this.doc.execCommand("enableObjectResizing", false, "false");
914
+ }
419
915
 
420
- $(this.doc).find('img').attr('unselectable', 'on').each($.proxy(function(i,s)
916
+ $(this.doc).find('img').each($.proxy(function(i,s)
421
917
  {
918
+ if ($.browser.msie) $(s).attr('unselectable', 'on');
422
919
  this.resizeImage(s);
423
920
 
424
921
  }, this));
425
922
 
426
923
  },
924
+ observeTables: function()
925
+ {
926
+ $(this.doc).find('body').find('table').click($.proxy(this.tableObserver, this));
927
+ },
427
928
  observeScroll: function()
428
929
  {
429
930
  var scrolltop = $(document).scrollTop();
@@ -432,24 +933,37 @@ var RTOOLBAR = {};
432
933
  if (scrolltop > boxtop)
433
934
  {
434
935
  this.fixed = true;
435
- this.$toolbar.css({position: 'fixed', width: '100%'});
936
+ this.$toolbar.css({ position: 'fixed', width: '100%' });
436
937
  }
437
938
  else
438
939
  {
439
940
  this.fixed = false;
440
- this.$toolbar.css({position: 'relative', width: 'auto'});
941
+ this.$toolbar.css({ position: 'relative', width: 'auto' });
441
942
  }
442
943
  },
443
944
  observeAutoResize: function()
444
945
  {
445
- this.$editor.css({ 'min-height':this.$el.height()+'px' });
446
- this.$frame.css({ 'overflow-x':'auto', 'overflow-y':'hidden' });
447
- this.$frame.load($.proxy(this.setAutoSize, this));
946
+ this.$editor.css({ 'min-height': this.$el.height() + 'px' });
947
+ $(this.doc).find('body').css({ 'overflow': 'hidden' });
948
+ this.setAutoSize(false);
448
949
  $(this.doc).keyup($.proxy(this.setAutoSize, this));
449
950
  },
450
- setAutoSize: function()
951
+ setAutoSize: function(e)
451
952
  {
452
- this.$frame.height(this.$editor.outerHeight(true)+30);
953
+ var key = false;
954
+ if (e !== false)
955
+ {
956
+ key = e.keyCode || e.which;
957
+ }
958
+
959
+ if (e === false || key === 13)
960
+ {
961
+ this.$frame.height(this.$editor.outerHeight(true)+30);
962
+ }
963
+ else if (key === 8 || key === 46)
964
+ {
965
+ this.$frame.height(this.$editor.outerHeight(true));
966
+ }
453
967
  },
454
968
 
455
969
 
@@ -460,17 +974,31 @@ var RTOOLBAR = {};
460
974
  {
461
975
  try
462
976
  {
463
- if ($.browser.msie) this.focus();
977
+ if ($.browser.msie)
978
+ {
979
+ this.focus();
980
+ }
464
981
 
465
- if (cmd == 'inserthtml' && $.browser.msie) this.doc.selection.createRange().pasteHTML(param);
466
- else if (cmd == 'formatblock' && $.browser.msie) this.doc.execCommand(cmd, false, '<' +param + '>');
982
+ if (cmd === 'inserthtml' && $.browser.msie)
983
+ {
984
+ this.doc.selection.createRange().pasteHTML(param);
985
+ }
986
+ else if (cmd === 'formatblock' && $.browser.msie)
987
+ {
988
+ this.doc.execCommand(cmd, false, '<' +param + '>');
989
+ }
467
990
  else
468
991
  {
469
992
  this.doc.execCommand(cmd, false, param);
470
993
  }
471
994
 
472
995
  this.syncCode();
473
- this.focus();
996
+ this.focus();
997
+
998
+ if (typeof this.opts.execCommandCallback === 'function')
999
+ {
1000
+ this.opts.execCommandCallback(this, cmd);
1001
+ }
474
1002
  }
475
1003
  catch (e) { }
476
1004
 
@@ -481,29 +1009,38 @@ var RTOOLBAR = {};
481
1009
  formatNewLine: function(e)
482
1010
  {
483
1011
  var parent = this.getParentNode();
484
- if (parent.nodeName == 'DIV' && parent.id == 'page')
1012
+ if (parent.nodeName === 'DIV' && parent.id === 'page')
485
1013
  {
486
- if (e.preventDefault) e.preventDefault();
1014
+ if (e.preventDefault)
1015
+ {
1016
+ e.preventDefault();
1017
+ }
487
1018
 
488
- element = $(this.getCurrentNode());
489
- if (element.get(0).tagName == 'DIV' && (element.html() == '' || element.html() == '<br>'))
1019
+ var element = $(this.getCurrentNode());
1020
+ if (element.get(0).tagName === 'DIV' && (element.html() === '' || element.html() === '<br>'))
490
1021
  {
491
- newElement = $('<p>').append(element.clone().get(0).childNodes);
1022
+ var newElement = $('<p>').append(element.clone().get(0).childNodes);
492
1023
  element.replaceWith(newElement);
493
1024
  newElement.html('<br />');
494
1025
  this.setFocusNode(newElement.get(0));
495
1026
 
496
1027
  this.syncCode();
497
1028
  return false;
498
- }
499
- else this.syncCode();
1029
+ }
1030
+ else
1031
+ {
1032
+ this.syncCode();
1033
+ }
500
1034
 
501
1035
  // convert links
502
- if (this.opts.convertLinks) this.$editor.linkify();
1036
+ if (this.opts.convertLinks)
1037
+ {
1038
+ this.$editor.linkify();
1039
+ }
503
1040
  }
504
1041
  else
505
1042
  {
506
- this.syncCode();
1043
+ this.syncCode();
507
1044
  return true;
508
1045
  }
509
1046
  },
@@ -511,17 +1048,22 @@ var RTOOLBAR = {};
511
1048
  // SAFARI SHIFT KEY + ENTER
512
1049
  safariShiftKeyEnter: function(e, key)
513
1050
  {
514
- if (e.shiftKey && key == 13)
1051
+ if (e.shiftKey && key === 13)
515
1052
  {
516
- if (e.preventDefault) e.preventDefault();
1053
+ e.preventDefault();
517
1054
 
518
1055
  var node1 = $('<span><br /></span>');
519
1056
  this.insertNodeAtCaret(node1.get(0));
520
1057
  this.setFocusNode(node1.get(0));
521
1058
 
522
1059
  this.syncCode();
1060
+
523
1061
  return false;
524
1062
  }
1063
+ else
1064
+ {
1065
+ return true;
1066
+ }
525
1067
  },
526
1068
 
527
1069
  // FORMAT EMPTY
@@ -529,86 +1071,53 @@ var RTOOLBAR = {};
529
1071
  {
530
1072
  var html = $.trim(this.$editor.html());
531
1073
 
532
- if ($.browser.mozilla) html = html.replace(/<br>/gi, '');
1074
+ if ($.browser.mozilla)
1075
+ {
1076
+ html = html.replace(/<br>/gi, '');
1077
+ }
533
1078
 
534
1079
  if (html === '')
535
1080
  {
536
- if (e.preventDefault) e.preventDefault();
1081
+ if (e.preventDefault)
1082
+ {
1083
+ e.preventDefault();
1084
+ }
537
1085
 
538
1086
  var nodehtml = this.opts.allEmptyHtml;
539
- if ($.browser.mozilla) nodehtml = this.opts.mozillaEmptyHtml;
1087
+ if ($.browser.mozilla)
1088
+ {
1089
+ nodehtml = this.opts.mozillaEmptyHtml;
1090
+ }
540
1091
 
541
1092
  var node = $(nodehtml).get(0);
542
1093
  this.$editor.html(node);
543
1094
  this.setFocusNode(node);
544
1095
 
545
- this.syncCode();
1096
+ this.syncCode();
546
1097
  return false;
547
1098
  }
548
- else this.syncCode();
549
- },
550
-
551
- // PARAGRAPHY
552
- paragraphy: function (str)
553
- {
554
- str = $.trim(str);
555
- if (str === '')
1099
+ else
556
1100
  {
557
- if (!$.browser.mozilla) return this.opts.allEmptyHtml;
558
- else return this.opts.mozillaEmptyHtml;
559
- }
560
-
561
- // convert div to p
562
- if (this.opts.convertDivs) str = str.replace(/<div(.*?)>([\w\W]*?)<\/div>/gi, '<p>$2</p>');
563
-
564
- // inner functions
565
- var X = function(x, a, b) { return x.replace(new RegExp(a, 'g'), b); };
566
- var R = function(a, b) { return X(str, a, b); };
567
-
568
- // block elements
569
- 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])';
570
-
571
- str += '\n';
572
-
573
- R('<br />\\s*<br />', '\n\n');
574
- R('(<' + blocks + '[^>]*>)', '\n$1');
575
- R('(</' + blocks + '>)', '$1\n\n');
576
- R('\r\n|\r', '\n'); // newlines
577
- R('\n\n+', '\n\n'); // remove duplicates
578
- R('\n?((.|\n)+?)$', '<p>$1</p>\n'); // including one at the end
579
- R('<p>\\s*?</p>', ''); // remove empty p
580
- R('<p>(<div[^>]*>\\s*)', '$1<p>');
581
- R('<p>([^<]+)\\s*?(</(div|address|form)[^>]*>)', '<p>$1</p>$2');
582
- R('<p>\\s*(</?' + blocks + '[^>]*>)\\s*</p>', '$1');
583
- R('<p>(<li.+?)</p>', '$1');
584
- R('<p>\\s*(</?' + blocks + '[^>]*>)', '$1');
585
- R('(</?' + blocks + '[^>]*>)\\s*</p>', '$1');
586
- R('(</?' + blocks + '[^>]*>)\\s*<br />', '$1');
587
- R('<br />(\\s*</?(p|li|div|dl|dd|dt|th|pre|td|ul|ol)[^>]*>)', '$1');
588
-
589
- // pre
590
- if (str.indexOf('<pre') != -1)
591
- {
592
- R('(<pre(.|\n)*?>)((.|\n)*?)</pre>', function(m0, m1, m2, m3)
593
- {
594
- return X(m1, '\\\\([\'\"\\\\])', '$1') + X(X(X(m3, '<p>', '\n'), '</p>|<br />', ''), '\\\\([\'\"\\\\])', '$1') + '</pre>';
595
- });
1101
+ this.syncCode();
596
1102
  }
597
-
598
- return R('\n</p>$', '</p>');
599
1103
  },
600
1104
 
601
1105
  // PREPARE FORMATER
602
1106
  preformater: function(html)
603
1107
  {
604
- html = html.replace(/<br>/gi,'<br />');
605
-
606
- html = html.replace(/<blockquote\b[^>]*>([\w\W]*?)<p>([\w\W]*?)<\/p>([\w\W]*?)<\/blockquote[^>]*>/gi,'<blockquote>$1$2<br />$3</blockquote>');
607
-
608
- html = html.replace(/<strong\b[^>]*>([\w\W]*?)<\/strong[^>]*>/gi,'<b>$1</b>');
609
- html = html.replace(/<em\b[^>]*>([\w\W]*?)<\/em[^>]*>/gi,'<i>$1</i>');
610
- html = html.replace(/<del\b[^>]*>([\w\W]*?)<\/del[^>]*>/gi,'<strike>$1</strike>');
611
-
1108
+ if (html !== null)
1109
+ {
1110
+ html = html.replace(/<br>/gi,'<br />');
1111
+ //html = html.replace(/<blockquote\b[^>]*>([\w\W]*?)<p>([\w\W]*?)<\/p>([\w\W]*?)<\/blockquote[^>]*>/gi,'<blockquote>$1$2<br />$3</blockquote>');
1112
+ html = html.replace(/<strong\b[^>]*>([\w\W]*?)<\/strong[^>]*>/gi,'<b>$1</b>');
1113
+ html = html.replace(/<em\b[^>]*>([\w\W]*?)<\/em[^>]*>/gi,'<i>$1</i>');
1114
+ html = html.replace(/<del\b[^>]*>([\w\W]*?)<\/del[^>]*>/gi,'<strike>$1</strike>');
1115
+ }
1116
+ else
1117
+ {
1118
+ html = '';
1119
+ }
1120
+
612
1121
  return html;
613
1122
  },
614
1123
 
@@ -616,7 +1125,6 @@ var RTOOLBAR = {};
616
1125
  reformater: function(html)
617
1126
  {
618
1127
  html = html.replace(/<br>/gi,'<br />');
619
-
620
1128
  html = html.replace(/<b\b[^>]*>([\w\W]*?)<\/b[^>]*>/gi,'<strong>$1</strong>');
621
1129
  html = html.replace(/<i\b[^>]*>([\w\W]*?)<\/i[^>]*>/gi,'<em>$1</em>');
622
1130
  html = html.replace(/<strike\b[^>]*>([\w\W]*?)<\/strike[^>]*>/gi,'<del>$1</del>');
@@ -627,121 +1135,259 @@ var RTOOLBAR = {};
627
1135
 
628
1136
  return html;
629
1137
  },
630
-
631
- // REMOVE CLASSES AND STYLES
632
- cleanUpClasses: function(html)
1138
+
1139
+ // REMOVE TAGS
1140
+ stripTags: function(html)
633
1141
  {
634
- html = html.replace(/\s*class="TOC(.*?)"/gi, "" );
635
- html = html.replace(/\s*class="Heading(.*?)"/gi, "" );
636
- html = html.replace(/\s*class="Body(.*?)"/gi, "" );
637
-
638
- return html;
1142
+ var allowed = ["code", "span", "div", "label", "a", "br", "p", "b", "i", "del", "strike", "img", "video", "audio", "iframe", "object", "embed", "param", "blockquote", "mark", "cite", "small", "ul", "ol", "li", "hr", "dl", "dt", "dd", "sup", "sub", "big", "pre", "code", "figure", "figcaption", "strong", "em", "table", "tr", "td", "th", "tbody", "thead", "tfoot", "h1", "h2", "h3", "h4", "h5", "h6"];
1143
+ var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi;
1144
+ return html.replace(tags, function ($0, $1)
1145
+ {
1146
+ return $.inArray($1.toLowerCase(), allowed) > '-1' ? $0 : '';
1147
+ });
639
1148
  },
640
- cleanUpStyles: function(html)
641
- {
642
-
643
- html = html.replace( /\s*mso-[^:]+:[^;"]+;?/gi, "" );
644
- html = html.replace( /\s*margin(.*?)pt\s*;/gi, "" );
645
- html = html.replace( /\s*margin(.*?)cm\s*;/gi, "" );
646
- html = html.replace( /\s*text-indent:(.*?)\s*;/gi, "" );
647
- html = html.replace( /\s*line-height:(.*?)\s*;/gi, "" );
648
- html = html.replace( /\s*page-break-before: [^\s;]+;?"/gi, "\"" );
649
- html = html.replace( /\s*font-variant: [^\s;]+;?"/gi, "\"" );
650
- html = html.replace( /\s*tab-stops:[^;"]*;?/gi, "" );
651
- html = html.replace( /\s*tab-stops:[^"]*/gi, "" );
652
- html = html.replace( /\s*face="[^"]*"/gi, "" );
653
- html = html.replace( /\s*face=[^ >]*/gi, "" );
654
- html = html.replace( /\s*font:(.*?);/gi, "" );
655
- html = html.replace( /\s*font-size:(.*?);/gi, "" );
656
- html = html.replace( /\s*font-weight:(.*?);/gi, "" );
657
- html = html.replace( /\s*font-family:[^;"]*;?/gi, "" );
658
- html = html.replace(/<span style="Times New Roman&quot;">\s\n<\/span>/gi, '');
659
-
660
- return html;
661
-
662
- },
663
- cleanUp: function(html)
1149
+ cleanStyles: function (properties, str, m)
664
1150
  {
665
- // clean comments
666
- html = html.replace(/(<\!\-\-([\w\W]*?)\-\->)/ig, "");
1151
+
1152
+ var attr = m.split('=');
1153
+ var prop = attr[1].split(';');
667
1154
 
668
- if (this.opts.convertDivs)
669
- {
670
- html = html.replace(/<div(.*?)>([\w\W]*?)<\/div>/gi, '<p$1>$2</p>');
671
- }
672
-
673
- // clean dirty
674
- html = html.replace(/ lang="([\w\W]*?)"/gi, '');
675
- html = html.replace(/<a name="(.*?)">([\w\W]*?)<\/a>/gi, '');
676
- html = html.replace(/\&nbsp;\&nbsp;\&nbsp;/gi, ' ');
677
- html = html.replace(/\&nbsp;\&nbsp;/gi, ' ');
678
- html = html.replace(/<o:p>(.*?)<\/o:p>/gi, '');
679
-
680
-
681
- // empty style
682
- html = html.replace( /\s*style="\s*"/gi, '' );
683
-
684
- // spans
685
- html = html.replace(/<span>&nbsp;<\/span>/gi, '');
686
- html = html.replace(/<span>([\w\W]*?)<\/span>/gi, '$1');
1155
+ var t = '';
1156
+ $.each(prop, function(z,s)
1157
+ {
1158
+ if (typeof s == 'undefined') return true;
1159
+ if (s == '"' || s == "'") return true;
687
1160
 
688
- return html;
689
- },
690
- removeTags: function(html)
691
- {
692
- return html.replace(/<(?!\s*\/?(code|span|div|label|a|br|p|b|i|del|strike|img|video|audio|iframe|object|embed|param|blockquote|mark|cite|small|ul|ol|li|hr|dl|dt|dd|sup|sub|big|pre|code|figure|figcaption|strong|em|table|tr|td|th|tbody|thead|tfoot|h1|h2|h3|h4|h5|h6)\b)[^>]+>/gi,"");
1161
+ s = s.replace(/(^"|^')/,'').replace(/("$|'$)/,'').replace(/"(.*?)"/gi, '');
1162
+ s = $.trim(s);
1163
+
1164
+ var p = s.split(':');
1165
+
1166
+ if (typeof p[1] !== 'undefined' && (p[1].search('pt') === -1 && p[1].search('cm') === -1))
1167
+ {
1168
+ if ($.inArray($.trim(p[0]), properties) != '-1') t += s + '; ';
1169
+ }
1170
+ });
1171
+
1172
+ return str.replace(m, 'style="' + t + '"');
693
1173
  },
1174
+
694
1175
 
695
1176
  // PASTE CLEANUP
696
- pasteCleanUp: function()
1177
+ pasteCleanUp: function(marker)
697
1178
  {
698
1179
  var html = this.$editor.html();
699
1180
 
700
- html = html.replace(/<span id="pastemarkerend">&nbsp;<\/span>/, '#marker#');
1181
+ // remove comments and php tags
1182
+ html = html.replace(/<!--[\s\S]*?-->|<\?(?:php)?[\s\S]*?\?>/gi, '')
1183
+
1184
+ // remove formatting
1185
+ html = this.formattingRemove(html);
1186
+
1187
+ // remove tags
1188
+ html = this.stripTags(html);
701
1189
 
702
- html = this.formating(html);
703
- html = this.cleanUp(html);
1190
+ // remove classes
1191
+ if (this.opts.removeClasses)
1192
+ {
1193
+ html = html.replace(/ class="([\w\W]*?)"/gi, '');
1194
+ }
1195
+ else
1196
+ {
1197
+ html = html.replace(/\s*class="TOC(.*?)"/gi, "" );
1198
+ html = html.replace(/\s*class="Heading(.*?)"/gi, "" );
1199
+ html = html.replace(/\s*class="Body(.*?)"/gi, "" );
1200
+ html = html.replace(/\sclass="Nonformat"/gi, '');
1201
+ html = html.replace(/\sclass="Mso(.*?)"/gi, '');
1202
+ html = html.replace(/\sclass="Apple(.*?)"/gi, '');
1203
+ html = html.replace(/"Times New Roman"/gi, '');
1204
+ }
1205
+
1206
+ var attributes = ['width', 'height', 'src', 'style', 'href', 'frameborder', 'class', 'id', 'rel', 'unselectable'];
1207
+ var properties = ['color', 'background-color', 'font-style', 'margin', 'margin-top', 'margin-bottom', 'margin-left', 'margin-right', 'text-align', 'width', 'height', 'cursor', 'float'];
1208
+
1209
+ // remove attributes
1210
+ var matches = html.match(/([\w\-.:]+)\s*=\s*("[^"]*"|'[^']*'|[\w\-.:]+)/gi);
1211
+ $.each(matches, $.proxy(function(i,m)
1212
+ {
1213
+ var attr = m.split('=');
1214
+ if ($.inArray(attr[0], attributes) == '-1')
1215
+ {
1216
+ html = html.replace(m, '');
1217
+ }
1218
+
1219
+ // remove styles
1220
+ if (this.opts.removeStyles === false && attr[0] == 'style') html = this.cleanStyles(properties, html, m);
1221
+
1222
+ }, this));
1223
+
1224
+ // remove styles
1225
+ if (this.opts.removeStyles === false)
1226
+ {
1227
+ html = html.replace(/background-color:(\s+)transparent;\s/gi, '');
1228
+ html = html.replace(/font-style:(\s+)normal;\s/gi, '');
1229
+ }
1230
+ else
1231
+ {
1232
+ html = html.replace(/ style="([\w\W]*?)"/gi, '');
1233
+ }
704
1234
 
705
- if (this.opts.removeClasses) html = html.replace(/ class="([\w\W]*?)"/gi, '');
706
- else html = this.cleanUpClasses(html);
1235
+ // remove empty styles
1236
+ html = html.replace(/((\s{2,})?|\s)style=(""|'')/gi, '');
707
1237
 
708
- if (this.opts.removeStyles) html = html.replace(/ style="([\w\W]*?)"/gi, '');
709
- else html = this.cleanUpStyles(html);
710
-
711
- html = this.cleanUp(html);
712
- html = this.formating(html);
1238
+ // remove nbsp
1239
+ html = html.replace(/(&nbsp;){1,}/gi, '&nbsp;');
713
1240
 
714
- html = html.replace(/<b(.*?)id="internal-source-marker(.*?)">([\w\W]*?)<\/b>/gi, "$3");
715
-
716
- html = html.replace(/#marker#/, '<span id="pastemarkerend">&nbsp;</span>');
1241
+ // remove empty span
1242
+ html = html.replace(/<span(\s)?>(\s)?<\/span>/gi, ' ');
1243
+
1244
+ // remove double white spaces
1245
+ html = html.replace(/\s{2,}/g, ' ');
1246
+
1247
+ // remove span without styles
1248
+ html = html.replace(/<span>([\w\W]*?)<\/span>/gi, '$1');
1249
+ html = html.replace(/<span>([\w\W]*?)<\/span>/gi, '$1');
1250
+ html = html.replace(/<span(\s)?>([\w\W]*?)<\/span>/gi, '$2');
1251
+
1252
+ // empty tags
1253
+ html = this.formattingEmptyTags(html);
1254
+
1255
+ // add formatting before
1256
+ html = this.formattingAddBefore(html);
1257
+
1258
+ // add formatting after
1259
+ html = this.formattingAddAfter(html);
1260
+
1261
+ // indenting
1262
+ html = this.formattingIndenting(html);
1263
+
1264
+ // dirty paragraphs
1265
+ html = html.replace(/<p><div>/gi, "");
1266
+ html = html.replace(/<p>\s+\n+<(.*?)/gi, "<$1");
1267
+ html = html.replace(/<\/(.*?)>\s+\n+<\/p>/gi, "</$1>");
1268
+ html = html.replace(/<p style="(.*?)">(\s)?<\/p>/gi, '');
1269
+ html = html.replace(/<p style="(.*?)"><\/p>/gi, '');
1270
+
1271
+ // remove google docs marker
1272
+ html = html.replace(/<b\sid="internal-source-marker(.*?)">([\w\W]*?)<\/b>/gi, "$2");
1273
+
1274
+ // trim spaces
1275
+ html = html.replace(/; ">/gi, ';">');
717
1276
 
1277
+ // SET HTML
718
1278
  this.$editor.html(html);
719
1279
 
720
- var node = $(this.doc.body).find('#pastemarkerend').get(0);
1280
+ // RETURN FOCUS
1281
+ var node = $(this.doc.body).find('#pastemarkerend' + marker).get(0);
721
1282
  this.setFocusNode(node);
722
1283
 
723
1284
  this.syncCode();
724
- this.observeImages();
1285
+
1286
+
1287
+ setTimeout($.proxy(function()
1288
+ {
1289
+ // remove pastemarker
1290
+ $(this.doc.body).find('span[rel=pastemarkerend]').remove();
1291
+
1292
+ if (this.opts.autoresize === true) this.setAutoSize(false);
1293
+
1294
+ this.observeImages();
1295
+ this.observeTables();
1296
+
1297
+ }, this), 100);
1298
+
1299
+
725
1300
  },
726
1301
 
727
1302
  // TEXTAREA CODE FORMATTING
728
- formating: function (html)
1303
+ formattingRemove: function(html)
1304
+ {
1305
+ html = html.replace(/\s{2,}/g, ' ');
1306
+ html = html.replace(/\n/g, ' ');
1307
+ html = html.replace(/[\t]*/g, '');
1308
+ html = html.replace(/\n\s*\n/g, "\n");
1309
+ html = html.replace(/^[\s\n]*/g, '');
1310
+ html = html.replace(/[\s\n]*$/g, '');
1311
+ html = html.replace(/>\s+</g, '><');
1312
+
1313
+ return html;
1314
+ },
1315
+ formattingIndenting: function(html)
1316
+ {
1317
+ html = html.replace(/<li/g, "\t<li");
1318
+ html = html.replace(/<tr/g, "\t<tr");
1319
+ html = html.replace(/<td/g, "\t\t<td");
1320
+ html = html.replace(/<\/tr>/g, "\t</tr>");
1321
+
1322
+ return html;
1323
+ },
1324
+ formattingEmptyTags: function(html)
1325
+ {
1326
+ 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>"];
1327
+ for (var i = 0; i < etags.length; ++i)
1328
+ {
1329
+ var bbb = etags[i];
1330
+ html = html.replace(new RegExp(bbb,'gi'), "");
1331
+ }
1332
+
1333
+ return html;
1334
+ },
1335
+ formattingAddBefore: function(html)
1336
+ {
1337
+ var lb = '\r\n';
1338
+ 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"];
1339
+ for (var i = 0; i < btags.length; ++i)
1340
+ {
1341
+ var eee = btags[i];
1342
+ html = html.replace(new RegExp(eee,'gi'),lb+eee);
1343
+ }
1344
+
1345
+ return html;
1346
+ },
1347
+ formattingAddAfter: function(html)
1348
+ {
1349
+ var lb = '\r\n';
1350
+ 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>'];
1351
+ for (var i = 0; i < atags.length; ++i)
1352
+ {
1353
+ var aaa = atags[i];
1354
+ html = html.replace(new RegExp(aaa,'gi'),aaa+lb);
1355
+ }
1356
+
1357
+ return html;
1358
+ },
1359
+ formatting: function(html)
729
1360
  {
730
1361
  // lowercase
731
1362
  if ($.browser.msie)
732
1363
  {
733
- html = html.replace(/<*(\/ *)?(\w+)/g, function(w) { return w.toLowerCase(); });
734
- html = html.replace(/style="(.*?)"/g, function(w) { return w.toLowerCase(); });
1364
+ var match = html.match(/<(.*?)>/gi);
1365
+ $.each(match, function(i,s)
1366
+ {
1367
+ html = html.replace(s, s.toLowerCase());
1368
+ })
1369
+ html = html.replace(/style="(.*?)"/gi, function(w) { return w.toLowerCase(); });
735
1370
  html = html.replace(/ jQuery(.*?)=\"(.*?)\"/gi, '');
736
1371
  }
737
1372
 
738
- html = html.replace(/<font([\w\W]*?)color="(.*?)">([\w\W]*?)<\/font\>/gi, '<span style="color: $2;">$3</span>');
1373
+ html = html.replace(/<span([\w\W]*?)style="color:(.*?);"><span([\w\W]*?)style="background-color:(.*?);">([\w\W]*?)<\/span><\/span>/gi, '<span style="color: $2; background-color: $4;">$5</span>');
1374
+ html = html.replace(/<span([\w\W]*?)style="background-color:(.*?);"><span([\w\W]*?)style="color:(.*?);">([\w\W]*?)<\/span><\/span>/gi, '<span style="color: $2; background-color: $4;">$5</span>');
1375
+
1376
+ html = html.replace(/<span([\w\W]*?)color="(.*?)">([\w\W]*?)<\/span\>/gi, '<span$1style="color: $2;">$3</span>');
1377
+ html = html.replace(/<font([\w\W]*?)color="(.*?)">([\w\W]*?)<\/font\>/gi, '<span$1style="color: $2;">$3</span>');
1378
+ html = html.replace(/<span style="(.*?)"\s+style="(.*?)"[\s]*>([\w\W]*?)<\/span\>/gi, '<span style="$1;$2">$3</span>');
739
1379
  html = html.replace(/<font([\w\W]*?)>([\w\W]*?)<\/font\>/gi, "<span$1>$2</span>");
740
- html = html.replace(/<span>([\w\W]*?)<\/span>/gi, '$1');
1380
+ html = html.replace(/<span>([\w\W]*?)<\/span>/gi, '$1');
1381
+
1382
+ if (this.opts.xhtml)
1383
+ {
1384
+ html = html.replace(/<br>/gi,'<br />');
1385
+ html = html.replace(/<br ?\/?>$/gi,'');
1386
+ html = html.replace(/^<br ?\/?>/gi,'');
1387
+ html = html.replace(/(<img [^>]+[^\/])>/gi,'$1 />');
1388
+ }
741
1389
 
742
1390
  // mini clean
743
- html = html.replace(/ class="Apple-style-span"/gi, '');
744
- html = html.replace(/ class="Apple-tab-span"/gi, '');
745
1391
  html = html.replace(/<p><p>/g, '<p>');
746
1392
  html = html.replace(/<\/p><\/p>/g, '</p>');
747
1393
  html = html.replace(/<hr(.*?)>/g, '<hr />');
@@ -753,42 +1399,19 @@ var RTOOLBAR = {};
753
1399
  html = html.replace( /<p(.*?)>&nbsp;<\/p>/gi, '');
754
1400
 
755
1401
  // remove formatting
756
- html = html.replace(/[\t]*/g, '');
757
- html = html.replace(/\n\s*\n/g, "\n");
758
- html = html.replace(/^[\s\n]*/, '');
759
- html = html.replace(/[\s\n]*$/, '');
1402
+ html = this.formattingRemove(html);
760
1403
 
761
1404
  // empty tags
762
- var etags = ["<pre></pre>","<blockquote>\\s*</blockquote>","<em>\\s*</em>","<b>\\s*</b>","<ul></ul>","<ol></ol>","<li></li>","<table></table>","<tr></tr>","<span>\\s*<span>", "<span>&nbsp;<span>", "<p>\\s*</p>", "<p>&nbsp;</p>", "<p>\\s*<br>\\s*</p>", "<div>\\s*</div>", "<div>\\s*<br>\\s*</div>"];
763
- for (var i = 0; i < etags.length; ++i)
764
- {
765
- var bbb = etags[i];
766
- html = html.replace(new RegExp(bbb,'gi'), "");
767
- }
768
-
769
-
1405
+ html = this.formattingEmptyTags(html);
1406
+
770
1407
  // add formatting before
771
- var lb = '\r\n';
772
- var btags = ["<form","<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"];
773
- for (var i = 0; i < btags.length; ++i)
774
- {
775
- var eee = btags[i];
776
- html = html.replace(new RegExp(eee,'gi'),lb+eee);
777
- }
1408
+ html = this.formattingAddBefore(html);
778
1409
 
779
1410
  // add formatting after
780
- var atags = ['</p>', '</div>', '</ul>', '</ol>', '</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>'];
781
- for (var i = 0; i < atags.length; ++i)
782
- {
783
- var aaa = atags[i];
784
- html = html.replace(new RegExp(aaa,'gi'),aaa+lb);
785
- }
1411
+ html = this.formattingAddAfter(html);
786
1412
 
787
1413
  // indenting
788
- html = html.replace(/<li/g, "\t<li");
789
- html = html.replace(/<tr/g, "\t<tr");
790
- html = html.replace(/<td/g, "\t\t<td");
791
- html = html.replace(/<\/tr>/g, "\t</tr>");
1414
+ html = this.formattingIndenting(html);
792
1415
 
793
1416
  return html;
794
1417
  },
@@ -803,8 +1426,8 @@ var RTOOLBAR = {};
803
1426
  this.$frame.hide();
804
1427
 
805
1428
  html = this.$editor.html();
806
- html = $.trim(this.formating(html));
807
-
1429
+ html = $.trim(this.formatting(html));
1430
+
808
1431
  this.$el.val(html).show().focus();
809
1432
 
810
1433
  this.setBtnActive('html');
@@ -820,8 +1443,14 @@ var RTOOLBAR = {};
820
1443
 
821
1444
  if (this.$editor.html() === '')
822
1445
  {
823
- if (!$.browser.mozilla) html = this.opts.allEmptyHtml;
824
- else html = this.opts.mozillaEmptyHtml;
1446
+ if (!$.browser.mozilla)
1447
+ {
1448
+ html = this.opts.allEmptyHtml;
1449
+ }
1450
+ else
1451
+ {
1452
+ html = this.opts.mozillaEmptyHtml;
1453
+ }
825
1454
 
826
1455
  this.setCode(html);
827
1456
  }
@@ -830,14 +1459,21 @@ var RTOOLBAR = {};
830
1459
 
831
1460
  this.setBtnInactive('html');
832
1461
  this.opts.visual = true;
1462
+
833
1463
  this.observeImages();
1464
+ this.observeTables();
1465
+
1466
+ if (this.opts.autoresize === true) this.setAutoSize(false);
834
1467
  }
835
1468
  },
836
1469
 
837
1470
  // AUTOSAVE
838
1471
  autoSave: function()
839
1472
  {
840
- if (this.opts.autosave === false) return false;
1473
+ if (this.opts.autosave === false)
1474
+ {
1475
+ return false;
1476
+ }
841
1477
 
842
1478
  setInterval($.proxy(function()
843
1479
  {
@@ -849,40 +1485,66 @@ var RTOOLBAR = {};
849
1485
  // TOOLBAR
850
1486
  buildToolbar: function()
851
1487
  {
852
- if (this.opts.toolbar === false) return false;
1488
+ if (this.opts.toolbar === false)
1489
+ {
1490
+ return false;
1491
+ }
853
1492
 
854
1493
  this.$toolbar = $('<ul>').addClass('redactor_toolbar');
855
1494
  this.$box.prepend(this.$toolbar);
856
1495
 
857
- $.each(RTOOLBAR[this.opts.toolbar], $.proxy(function(key,s)
1496
+ $.each(this.opts.buttons, $.proxy(function(i,key)
858
1497
  {
859
- if (this.opts.fileUpload === false && key == 'file') return true;
860
-
861
- var li = $('<li>');
862
1498
 
863
- if (key == 'fullscreen') $(li).addClass('redactor_toolbar_right');
864
-
865
- var a = this.buildButton(key, s);
866
-
867
- // dropdown
868
- if (key == 'backcolor' || key == 'fontcolor' || typeof(s.dropdown) != 'undefined')
1499
+ if (key !== '|' && typeof this.opts.toolbar[key] !== 'undefined')
869
1500
  {
870
- var dropdown = $('<div class="redactor_dropdown" style="display: none;">');
1501
+ var s = this.opts.toolbar[key];
1502
+
1503
+ if (this.opts.fileUpload === false && key === 'file')
1504
+ {
1505
+ return true;
1506
+ }
1507
+
1508
+ var li = $('<li>');
871
1509
 
872
- if (key == 'backcolor' || key == 'fontcolor') dropdown = this.buildColorPicker(dropdown, key);
873
- else dropdown = this.buildDropdown(dropdown, s.dropdown);
874
-
875
- this.dropdowns.push(dropdown.appendTo($(document.body)));
876
-
877
- // observing dropdown
878
- this.hdlHideDropDown = $.proxy(function(e) { this.hideDropDown(e, dropdown, key); }, this);
879
- this.hdlShowDropDown = $.proxy(function(e) { this.showDropDown(e, dropdown, key); }, this);
880
-
881
- a.click(this.hdlShowDropDown);
1510
+ if (key === 'fullscreen')
1511
+ {
1512
+ $(li).addClass('redactor_toolbar_right');
1513
+ }
1514
+
1515
+ var a = this.buildButton(key, s);
1516
+
1517
+ // dropdown
1518
+ if (key === 'backcolor' || key === 'fontcolor' || typeof(s.dropdown) !== 'undefined')
1519
+ {
1520
+ var dropdown = $('<div class="redactor_dropdown" style="display: none;">');
1521
+
1522
+ if (key === 'backcolor' || key === 'fontcolor')
1523
+ {
1524
+ dropdown = this.buildColorPicker(dropdown, key);
1525
+ }
1526
+ else
1527
+ {
1528
+ dropdown = this.buildDropdown(dropdown, s.dropdown);
1529
+ }
1530
+
1531
+ this.dropdowns.push(dropdown.appendTo($(document.body)));
1532
+
1533
+ // observing dropdown
1534
+ this.hdlHideDropDown = $.proxy(function(e) { this.hideDropDown(e, dropdown, key); }, this);
1535
+ this.hdlShowDropDown = $.proxy(function(e) { this.showDropDown(e, dropdown, key); }, this);
1536
+
1537
+ a.click(this.hdlShowDropDown);
1538
+ }
1539
+
1540
+ this.$toolbar.append($(li).append(a));
882
1541
  }
883
1542
 
884
- this.$toolbar.append($(li).append(a));
885
- if (typeof(s.separator) != 'undefined') this.$toolbar.append($('<li class="redactor_separator"></li>'));
1543
+
1544
+ if (key === '|')
1545
+ {
1546
+ this.$toolbar.append($('<li class="redactor_separator"></li>'));
1547
+ }
886
1548
 
887
1549
  }, this));
888
1550
 
@@ -893,8 +1555,20 @@ var RTOOLBAR = {};
893
1555
  buildButton: function(key, s)
894
1556
  {
895
1557
  var button = $('<a href="javascript:void(null);" title="' + s.title + '" class="redactor_btn_' + key + '"><span>&nbsp;</span></a>');
896
- if (typeof(s.func) == 'undefined') button.click($.proxy(function() { this.execCommand(s.exec, key); }, this));
897
- else if (s.func != 'show') button.click($.proxy(function(e) { this[s.func](e); }, this));
1558
+
1559
+ if (typeof s.func === 'undefined')
1560
+ {
1561
+ button.click($.proxy(function() { this.execCommand(s.exec, key); }, this));
1562
+ }
1563
+ else if (s.func !== 'show')
1564
+ {
1565
+ button.click($.proxy(function(e) { this[s.func](e); }, this));
1566
+ }
1567
+
1568
+ if (typeof s.callback !== 'undefined')
1569
+ {
1570
+ button.click($.proxy(function(e) { s.callback(this, e, key); }, this));
1571
+ }
898
1572
 
899
1573
  return button;
900
1574
  },
@@ -903,16 +1577,28 @@ var RTOOLBAR = {};
903
1577
  $.each(obj, $.proxy(
904
1578
  function (x, d)
905
1579
  {
906
- if (typeof(d.style) == 'undefined') d.style = '';
1580
+ if (typeof(d.className) === 'undefined')
1581
+ {
1582
+ d.className = '';
1583
+ }
907
1584
 
908
1585
  var drop_a;
909
- if (d.name == 'separator') drop_a = $('<a class="redactor_separator_drop">');
1586
+ if (typeof d.name !== 'undefined' && d.name === 'separator')
1587
+ {
1588
+ drop_a = $('<a class="redactor_separator_drop">');
1589
+ }
910
1590
  else
911
1591
  {
912
- drop_a = $('<a href="javascript:void(null);" style="' + d.style + '">' + d.title + '</a>');
1592
+ drop_a = $('<a href="javascript:void(null);" class="' + d.className + '">' + d.title + '</a>');
913
1593
 
914
- if (typeof(d.func) == 'undefined') $(drop_a).click($.proxy(function() { this.execCommand(d.exec, x); }, this));
915
- else $(drop_a).click($.proxy(function(e) { this[d.func](e); }, this));
1594
+ if (typeof(d.func) === 'undefined')
1595
+ {
1596
+ $(drop_a).click($.proxy(function() { this.execCommand(d.exec, x); }, this));
1597
+ }
1598
+ else
1599
+ {
1600
+ $(drop_a).click($.proxy(function(e) { this[d.func](e); }, this));
1601
+ }
916
1602
  }
917
1603
 
918
1604
  $(dropdown).append(drop_a);
@@ -926,12 +1612,21 @@ var RTOOLBAR = {};
926
1612
  buildColorPicker: function(dropdown, key)
927
1613
  {
928
1614
  var mode;
929
- if (key == 'backcolor')
1615
+ if (key === 'backcolor')
930
1616
  {
931
- if ($.browser.msie) mode = 'BackColor';
932
- else mode = 'hilitecolor';
1617
+ if ($.browser.msie)
1618
+ {
1619
+ mode = 'BackColor';
1620
+ }
1621
+ else
1622
+ {
1623
+ mode = 'hilitecolor';
1624
+ }
1625
+ }
1626
+ else
1627
+ {
1628
+ mode = 'forecolor';
933
1629
  }
934
- else mode = 'forecolor';
935
1630
 
936
1631
  $(dropdown).width(210);
937
1632
 
@@ -944,13 +1639,41 @@ var RTOOLBAR = {};
944
1639
  $(dropdown).append(swatch);
945
1640
 
946
1641
  var _self = this;
947
- $(swatch).click(function() { _self.execCommand(mode, $(this).attr('rel')); });
1642
+ $(swatch).click(function()
1643
+ {
1644
+ if ($.browser.mozilla)
1645
+ {
1646
+ if (mode == 'hilitecolor')
1647
+ {
1648
+ _self.execCommand('useCSS', false, false);
1649
+ _self.execCommand(mode, $(this).attr('rel'));
1650
+ _self.execCommand('useCSS', false, true);
1651
+ }
1652
+ else
1653
+ {
1654
+ _self.execCommand('styleWithCSS', false, false);
1655
+ _self.execCommand(mode, $(this).attr('rel'));
1656
+ _self.execCommand('styleWithCSS', false, true);
1657
+ }
1658
+ }
1659
+ else
1660
+ {
1661
+ _self.execCommand(mode, $(this).attr('rel'));
1662
+ }
1663
+
1664
+ });
948
1665
  }
949
1666
 
950
1667
  var elnone = $('<a href="javascript:void(null);" class="redactor_color_none"></a>').html(RLANG.none);
951
1668
 
952
- if (key == 'backcolor') elnone.click($.proxy(this.setBackgroundNone, this));
953
- else elnone.click($.proxy(this.setColorNone, this));
1669
+ if (key === 'backcolor')
1670
+ {
1671
+ elnone.click($.proxy(this.setBackgroundNone, this));
1672
+ }
1673
+ else
1674
+ {
1675
+ elnone.click($.proxy(this.setColorNone, this));
1676
+ }
954
1677
 
955
1678
  $(dropdown).append(elnone);
956
1679
 
@@ -966,26 +1689,34 @@ var RTOOLBAR = {};
966
1689
  $(this.getParentNode()).attr('color', '').css('color', '');
967
1690
  this.syncCode();
968
1691
  },
1692
+
969
1693
 
970
1694
  // DROPDOWNS
971
1695
  showDropDown: function(e, dropdown, key)
972
1696
  {
973
- this.hideAllDropDown();
974
-
975
- this.setBtnActive(key);
976
- this.getBtn(key).addClass('dropact');
977
-
978
- var left = this.getBtn(key).offset().left;
979
-
980
-
981
- if (this.opts.fixed && this.fixed)
1697
+ if (this.getBtn(key).hasClass('dropact'))
982
1698
  {
983
- $(dropdown).css({ position: 'fixed', left: left + 'px', top: '30px' }).show();
1699
+ this.hideAllDropDown();
984
1700
  }
985
- else
986
- {
987
- var top = this.$toolbar.offset().top + 30;
988
- $(dropdown).css({ position: 'absolute', left: left + 'px', top: top + 'px' }).show();
1701
+ else
1702
+ {
1703
+ this.hideAllDropDown();
1704
+
1705
+ this.setBtnActive(key);
1706
+ this.getBtn(key).addClass('dropact');
1707
+
1708
+ var left = this.getBtn(key).offset().left;
1709
+
1710
+
1711
+ if (this.opts.fixed && this.fixed)
1712
+ {
1713
+ $(dropdown).css({ position: 'fixed', left: left + 'px', top: '30px' }).show();
1714
+ }
1715
+ else
1716
+ {
1717
+ var top = this.$toolbar.offset().top + 30;
1718
+ $(dropdown).css({ position: 'absolute', left: left + 'px', top: top + 'px' }).show();
1719
+ }
989
1720
  }
990
1721
 
991
1722
  },
@@ -1007,18 +1738,36 @@ var RTOOLBAR = {};
1007
1738
  // SELECTION AND NODE MANIPULATION
1008
1739
  getSelection: function ()
1009
1740
  {
1010
- if (this.$frame.get(0).contentWindow.getSelection) return this.$frame.get(0).contentWindow.getSelection();
1011
- else if (this.$frame.get(0).contentWindow.document.selection) return this.$frame.get(0).contentWindow.document.selection.createRange();
1741
+ if (this.$frame.get(0).contentWindow.getSelection)
1742
+ {
1743
+ return this.$frame.get(0).contentWindow.getSelection();
1744
+ }
1745
+ else if (this.$frame.get(0).contentWindow.document.selection)
1746
+ {
1747
+ return this.$frame.get(0).contentWindow.document.selection.createRange();
1748
+ }
1012
1749
  },
1013
1750
  getParentNode: function()
1014
1751
  {
1015
- if (window.getSelection) return this.getSelection().getRangeAt(0).startContainer.parentNode;
1016
- else if (document.selection) return this.getSelection().parentElement();
1752
+ if (window.getSelection)
1753
+ {
1754
+ return this.getSelection().getRangeAt(0).startContainer.parentNode;
1755
+ }
1756
+ else if (document.selection)
1757
+ {
1758
+ return this.getSelection().parentElement();
1759
+ }
1017
1760
  },
1018
1761
  getCurrentNode: function()
1019
1762
  {
1020
- if (window.getSelection) return this.getSelection().getRangeAt(0).startContainer;
1021
- else if (document.selection) return this.getSelection();
1763
+ if (window.getSelection)
1764
+ {
1765
+ return this.getSelection().getRangeAt(0).startContainer;
1766
+ }
1767
+ else if (document.selection)
1768
+ {
1769
+ return this.getSelection();
1770
+ }
1022
1771
  },
1023
1772
  setFocusNode: function(node, toStart)
1024
1773
  {
@@ -1038,7 +1787,7 @@ var RTOOLBAR = {};
1038
1787
  },
1039
1788
  insertNodeAtCaret: function (node)
1040
1789
  {
1041
- if (typeof window.getSelection != "undefined")
1790
+ if (typeof window.getSelection !== "undefined")
1042
1791
  {
1043
1792
  var sel = this.getSelection();
1044
1793
  if (sel.rangeCount)
@@ -1053,9 +1802,9 @@ var RTOOLBAR = {};
1053
1802
  sel.addRange(range);
1054
1803
  }
1055
1804
  }
1056
- else if (typeof document.selection != "undefined" && document.selection.type != "Control")
1805
+ else if (typeof document.selection !== "undefined" && document.selection.type !== "Control")
1057
1806
  {
1058
- var html = (node.nodeType == 1) ? node.outerHTML : node.data;
1807
+ var html = (node.nodeType === 1) ? node.outerHTML : node.data;
1059
1808
  var id = "marker_" + ("" + Math.random()).slice(2);
1060
1809
  html += '<span id="' + id + '"></span>';
1061
1810
  var textRange = this.getSelection();
@@ -1122,10 +1871,13 @@ var RTOOLBAR = {};
1122
1871
  this.$editor = this.enable(html);
1123
1872
 
1124
1873
  $(this.doc).click($.proxy(this.hideAllDropDown, this));
1874
+
1125
1875
  // focus always on page
1126
- $(this.doc).click($.proxy(function(e) { this.$editor.focus(); }, this));
1876
+ this.observeFocus();
1127
1877
 
1128
1878
  this.observeImages();
1879
+ this.observeTables();
1880
+
1129
1881
  this.$box.find('.redactor_resizer').hide();
1130
1882
 
1131
1883
  this.fullScreenResize();
@@ -1152,12 +1904,18 @@ var RTOOLBAR = {};
1152
1904
  this.$editor = this.enable(html);
1153
1905
 
1154
1906
  this.observeImages();
1155
- this.observeAutoResize();
1907
+ this.observeTables();
1908
+
1909
+ if (this.opts.autoresize)
1910
+ {
1911
+ this.observeAutoResize();
1912
+ }
1156
1913
  this.$box.find('.redactor_resizer').show();
1157
1914
 
1158
1915
  $(this.doc).click($.proxy(this.hideAllDropDown, this));
1916
+
1159
1917
  // focus always on page
1160
- $(this.doc).click($.proxy(function(e) { this.$editor.focus(); }, this));
1918
+ this.observeFocus();
1161
1919
 
1162
1920
  this.syncCode();
1163
1921
 
@@ -1168,13 +1926,12 @@ var RTOOLBAR = {};
1168
1926
  },
1169
1927
  fullScreenResize: function()
1170
1928
  {
1171
- if (this.opts.fullscreen === false) return;
1172
-
1173
- var hfix = 42;
1174
- if (this.opts.air) hfix = 2;
1175
-
1176
- var height = $(window).height() - hfix;
1929
+ if (this.opts.fullscreen === false)
1930
+ {
1931
+ return false;
1932
+ }
1177
1933
 
1934
+ var height = $(window).height() - 42;
1178
1935
  this.$box.width($(window).width() - 2);
1179
1936
  this.$frame.height(height);
1180
1937
  this.$el.height(height);
@@ -1183,17 +1940,22 @@ var RTOOLBAR = {};
1183
1940
  // RESIZE
1184
1941
  buildResizer: function()
1185
1942
  {
1186
- if (this.opts.resize === false) return false;
1943
+ if (this.opts.resize === false)
1944
+ {
1945
+ return false;
1946
+ }
1187
1947
 
1188
1948
  this.$resizer = $('<div class="redactor_resizer">&mdash;</div>');
1189
- this.$box.append(this.$resizer);
1190
-
1949
+ this.$box.append(this.$resizer);
1191
1950
  this.$resizer.mousedown($.proxy(this.initResize, this));
1192
1951
 
1193
1952
  },
1194
1953
  initResize: function(e)
1195
1954
  {
1196
- if (e.preventDefault) e.preventDefault();
1955
+ if (e.preventDefault)
1956
+ {
1957
+ e.preventDefault();
1958
+ }
1197
1959
 
1198
1960
  this.splitter = e.target;
1199
1961
 
@@ -1227,15 +1989,29 @@ var RTOOLBAR = {};
1227
1989
  },
1228
1990
  resize: function(e)
1229
1991
  {
1230
- if (e.preventDefault) e.preventDefault();
1992
+ if (e.preventDefault)
1993
+ {
1994
+ e.preventDefault();
1995
+ }
1231
1996
 
1232
1997
  var y = e.pageY;
1233
- if (this.null_point === false) this.null_point = y;
1234
- if (this.h_new === false) this.h_new = this.element_resize.height();
1998
+
1999
+ if (this.null_point === false)
2000
+ {
2001
+ this.null_point = y;
2002
+ }
2003
+
2004
+ if (this.h_new === false)
2005
+ {
2006
+ this.h_new = this.element_resize.height();
2007
+ }
1235
2008
 
1236
2009
  var s_new = (this.h_new + y - this.null_point) - 10;
1237
2010
 
1238
- if (s_new <= 30) return true;
2011
+ if (s_new <= 30)
2012
+ {
2013
+ return true;
2014
+ }
1239
2015
 
1240
2016
  if (s_new >= 0)
1241
2017
  {
@@ -1267,11 +2043,14 @@ var RTOOLBAR = {};
1267
2043
  var min_w = 1;
1268
2044
  var min_h = 1;
1269
2045
 
1270
- $(resize).hover(function(){$(resize).css('cursor', 'nw-resize');}, function(){$(resize).css('cursor','default');clicked=false;});
2046
+ $(resize).hover(function() { $(resize).css('cursor', 'nw-resize'); }, function() { $(resize).css('cursor','default'); clicked=false; });
1271
2047
 
1272
2048
  $(resize).mousedown(function(e)
1273
2049
  {
1274
- if (e.preventDefault) e.preventDefault();
2050
+ if (e.preventDefault)
2051
+ {
2052
+ e.preventDefault();
2053
+ }
1275
2054
 
1276
2055
  clicked = true;
1277
2056
  clicker = true;
@@ -1284,11 +2063,16 @@ var RTOOLBAR = {};
1284
2063
  {
1285
2064
  clicked = false;
1286
2065
  this.syncCode();
2066
+ if (this.opts.autoresize === true) this.setAutoSize(false);
2067
+
1287
2068
  }, this));
1288
2069
 
1289
2070
  $(resize).click($.proxy(function(e)
1290
2071
  {
1291
- if (clicker) this.imageEdit(e);
2072
+ if (clicker)
2073
+ {
2074
+ this.imageEdit(e);
2075
+ }
1292
2076
 
1293
2077
  }, this));
1294
2078
 
@@ -1303,13 +2087,17 @@ var RTOOLBAR = {};
1303
2087
 
1304
2088
  var div_h = $(resize).height();
1305
2089
 
1306
- var new_h = parseInt(div_h)+mouse_y;
2090
+ var new_h = parseInt(div_h, 10) + mouse_y;
1307
2091
  var new_w = new_h*ratio;
1308
2092
 
1309
-
1310
-
1311
- if(x==1 || (typeof(x) == "number" && new_w < x && new_w > min_w) ){ $(resize).width(new_w); }
1312
- if(y==1 || (typeof(y) == "number" && new_h < y && new_h > min_h) ){ $(resize).height(new_h); }
2093
+ if (x === 1 || (typeof(x) === "number" && new_w < x && new_w > min_w))
2094
+ {
2095
+ $(resize).width(new_w);
2096
+ }
2097
+ if (y === 1 || (typeof(y) === "number" && new_h < y && new_h > min_h))
2098
+ {
2099
+ $(resize).height(new_h);
2100
+ }
1313
2101
  start_x = Math.round(e.pageX - $(this).eq(0).offset().left);
1314
2102
  start_y = Math.round(e.pageY - $(this).eq(0).offset().top);
1315
2103
  }
@@ -1319,12 +2107,16 @@ var RTOOLBAR = {};
1319
2107
  // TABLE
1320
2108
  showTable: function()
1321
2109
  {
1322
- this.modalInit(RLANG.table, this.opts.path + '/plugins/table.html', 300, $.proxy(function()
1323
- {
1324
- $('#redactor_table_rows').focus();
1325
- $('#redactor_insert_table_btn').click($.proxy(this.insertTable, this));
1326
-
1327
- }, this));
2110
+ this.modalInit(RLANG.table, 'table', 300, $.proxy(function()
2111
+ {
2112
+ $('#redactor_insert_table_btn').click($.proxy(this.insertTable, this));
2113
+ }, this),
2114
+
2115
+ function()
2116
+ {
2117
+ $('#redactor_table_rows').focus();
2118
+ }
2119
+ );
1328
2120
  },
1329
2121
  insertTable: function()
1330
2122
  {
@@ -1350,14 +2142,22 @@ var RTOOLBAR = {};
1350
2142
  $(table_box).append(table);
1351
2143
  var html = $(table_box).html();
1352
2144
 
1353
- if ($.browser.msie) html += '<p></p>';
1354
- else html += '<p>&nbsp;</p>';
2145
+ if ($.browser.msie)
2146
+ {
2147
+ html += '<p></p>';
2148
+ }
2149
+ else
2150
+ {
2151
+ html += '<p>&nbsp;</p>';
2152
+ }
1355
2153
 
1356
2154
  this.execCommand('inserthtml', html);
1357
2155
  this.modalClose();
1358
2156
 
1359
2157
  this.$table = $(this.doc).find('body').find('#table' + tableid);
1360
2158
  this.$table.click($.proxy(this.tableObserver, this));
2159
+
2160
+ if (this.opts.autoresize === true) this.setAutoSize(false);
1361
2161
  },
1362
2162
  tableObserver: function(e)
1363
2163
  {
@@ -1400,7 +2200,10 @@ var RTOOLBAR = {};
1400
2200
  },
1401
2201
  addHead: function()
1402
2202
  {
1403
- if ($(this.$table).find('thead').size() !== 0) this.deleteHead();
2203
+ if ($(this.$table).find('thead').size() !== 0)
2204
+ {
2205
+ this.deleteHead();
2206
+ }
1404
2207
  else
1405
2208
  {
1406
2209
  var tr = $(this.$table).find('tr').first().clone();
@@ -1437,8 +2240,14 @@ var RTOOLBAR = {};
1437
2240
  {
1438
2241
  var new_tr = $(this.$current_tr).clone();
1439
2242
  new_tr.find('td').html('&nbsp;');
1440
- if (type == 'after') $(this.$current_tr).after(new_tr);
1441
- else $(this.$current_tr).before(new_tr);
2243
+ if (type === 'after')
2244
+ {
2245
+ $(this.$current_tr).after(new_tr);
2246
+ }
2247
+ else
2248
+ {
2249
+ $(this.$current_tr).before(new_tr);
2250
+ }
1442
2251
 
1443
2252
  this.syncCode();
1444
2253
  },
@@ -1450,7 +2259,10 @@ var RTOOLBAR = {};
1450
2259
 
1451
2260
  this.$current_tr.find('td').each(function(i,s)
1452
2261
  {
1453
- if ($(s).hasClass('current')) index = i;
2262
+ if ($(s).hasClass('current'))
2263
+ {
2264
+ index = i;
2265
+ }
1454
2266
  });
1455
2267
 
1456
2268
  this.$table_tr.each(function(i,s)
@@ -1460,8 +2272,14 @@ var RTOOLBAR = {};
1460
2272
  var td = current.clone();
1461
2273
  td.html('&nbsp;');
1462
2274
 
1463
- if (type == 'after') $(current).after(td);
1464
- else $(current).before(td);
2275
+ if (type === 'after')
2276
+ {
2277
+ $(current).after(td);
2278
+ }
2279
+ else
2280
+ {
2281
+ $(current).before(td);
2282
+ }
1465
2283
 
1466
2284
  });
1467
2285
 
@@ -1471,27 +2289,39 @@ var RTOOLBAR = {};
1471
2289
  // INSERT VIDEO
1472
2290
  showVideo: function()
1473
2291
  {
1474
- if ($.browser.msie) this.markerIE();
1475
-
1476
- this.modalInit(RLANG.video, this.opts.path + '/plugins/video.html', 600, $.proxy(function()
2292
+ if ($.browser.msie)
1477
2293
  {
1478
- $('#redactor_insert_video_area').focus();
1479
- $('#redactor_insert_video_btn').click($.proxy(this.insertVideo, this));
2294
+ this.markerIE();
2295
+ }
1480
2296
 
1481
- }, this));
2297
+ this.modalInit(RLANG.video, 'video', 600, $.proxy(function()
2298
+ {
2299
+ $('#redactor_insert_video_btn').click($.proxy(this.insertVideo, this));
2300
+ }, this),
2301
+
2302
+ function()
2303
+ {
2304
+ $('#redactor_insert_video_area').focus();
2305
+ }
2306
+ );
1482
2307
  },
1483
2308
  insertVideo: function()
1484
2309
  {
1485
2310
  var data = $('#redactor_insert_video_area').val();
2311
+ data = this.stripTags(data);
1486
2312
 
1487
2313
  if ($.browser.msie)
1488
2314
  {
1489
2315
  $(this.doc.getElementById('span' + this.spanid)).after(data).remove();
1490
2316
  this.syncCode();
1491
2317
  }
1492
- else this.execCommand('inserthtml', data);
2318
+ else
2319
+ {
2320
+ this.execCommand('inserthtml', data);
2321
+ }
1493
2322
 
1494
2323
  this.modalClose();
2324
+ if (this.opts.autoresize === true) this.setAutoSize(false);
1495
2325
  },
1496
2326
 
1497
2327
  // INSERT IMAGE
@@ -1506,14 +2336,17 @@ var RTOOLBAR = {};
1506
2336
  $('#redactor_image_edit_src').attr('href', $el.attr('src'));
1507
2337
  $('#redactor_form_image_align').val($el.css('float'));
1508
2338
 
1509
- if ($(parent).get(0).tagName == 'A') $('#redactor_file_link').val($(parent).attr('href'));
2339
+ if ($(parent).get(0).tagName === 'A')
2340
+ {
2341
+ $('#redactor_file_link').val($(parent).attr('href'));
2342
+ }
1510
2343
 
1511
2344
  $('#redactor_image_delete_btn').click($.proxy(function() { this.imageDelete($el); }, this));
1512
2345
  $('#redactorSaveBtn').click($.proxy(function() { this.imageSave($el); }, this));
1513
2346
 
1514
2347
  }, this);
1515
2348
 
1516
- this.modalInit(RLANG.image, this.opts.path + '/plugins/image_edit.html', 380, handler);
2349
+ this.modalInit(RLANG.image, 'image_edit', 380, handler);
1517
2350
 
1518
2351
  },
1519
2352
  imageDelete: function(el)
@@ -1530,15 +2363,24 @@ var RTOOLBAR = {};
1530
2363
 
1531
2364
  var floating = $('#redactor_form_image_align').val();
1532
2365
 
1533
- if (floating == 'left') $(el).css({ 'float': 'left', margin: '0 10px 10px 0' });
1534
- else if (floating == 'right') $(el).css({ 'float': 'right', margin: '0 0 10px 10px' });
1535
- else $(el).css({ 'float': 'none', margin: '0' });
2366
+ if (floating === 'left')
2367
+ {
2368
+ $(el).css({ 'float': 'left', margin: '0 10px 10px 0' });
2369
+ }
2370
+ else if (floating === 'right')
2371
+ {
2372
+ $(el).css({ 'float': 'right', margin: '0 0 10px 10px' });
2373
+ }
2374
+ else
2375
+ {
2376
+ $(el).css({ 'float': 'none', margin: '0' });
2377
+ }
1536
2378
 
1537
2379
  // as link
1538
2380
  var link = $.trim($('#redactor_file_link').val());
1539
2381
  if (link !== '')
1540
2382
  {
1541
- if ($(parent).get(0).tagName != 'A')
2383
+ if ($(parent).get(0).tagName !== 'A')
1542
2384
  {
1543
2385
  $(el).replaceWith('<a href="' + link + '">' + this.outerHTML(el) + '</a>');
1544
2386
  }
@@ -1555,7 +2397,10 @@ var RTOOLBAR = {};
1555
2397
  },
1556
2398
  showImage: function()
1557
2399
  {
1558
- if ($.browser.msie) this.markerIE();
2400
+ if ($.browser.msie)
2401
+ {
2402
+ this.markerIE();
2403
+ }
1559
2404
 
1560
2405
  var handler = $.proxy(function()
1561
2406
  {
@@ -1606,7 +2451,7 @@ var RTOOLBAR = {};
1606
2451
  {
1607
2452
  var tabs = $('#redactor_tabs a');
1608
2453
  tabs.eq(0).remove();
1609
- tabs.eq(1).addClass('redactor_tabs_act');
2454
+ tabs.eq(1).addClass('redactor_tabs_act');
1610
2455
  $('#redactor_tab2').show();
1611
2456
  }
1612
2457
  }
@@ -1614,31 +2459,50 @@ var RTOOLBAR = {};
1614
2459
  $('#redactor_upload_btn').click($.proxy(this.imageUploadCallbackLink, this));
1615
2460
 
1616
2461
  }, this);
2462
+
2463
+ var endCallback = $.proxy(function()
2464
+ {
2465
+ if (this.opts.imageUpload === false && this.opts.imageGetJson === false)
2466
+ {
2467
+ $('#redactor_file_link').focus();
2468
+ }
2469
+ }, this);
1617
2470
 
1618
- this.modalInit(RLANG.image, this.opts.path + '/plugins/image.html', 570, handler, true);
2471
+ this.modalInit(RLANG.image, 'image', 570, handler, endCallback, true);
1619
2472
 
1620
2473
  },
1621
2474
  imageSetThumb: function(e)
1622
2475
  {
1623
- this._imageSet('<img alt="" src="' + $(e.target).attr('rel') + '" />');
2476
+ this._imageSet('<img alt="" src="' + $(e.target).attr('rel') + '" />', true);
1624
2477
  },
1625
2478
  imageUploadCallbackLink: function()
1626
2479
  {
1627
2480
  if ($('#redactor_file_link').val() !== '')
1628
2481
  {
1629
- var data = '<img src="' + $('#redactor_file_link').val() + '" />';
1630
-
1631
- this._imageSet(data);
2482
+ var data = '<img src="' + $('#redactor_file_link').val() + '" />';
2483
+ this._imageSet(data, true);
2484
+ }
2485
+ else
2486
+ {
2487
+ this.modalClose();
1632
2488
  }
1633
- else this.modalClose();
1634
2489
  },
1635
2490
  imageUploadCallback: function(data)
1636
2491
  {
1637
2492
  this._imageSet(data);
1638
2493
  },
1639
- _imageSet: function(html)
2494
+ _imageSet: function(json, link)
1640
2495
  {
1641
- html = '<p>' + html + '</p>';
2496
+ var html = '', data = '';
2497
+ if (link !== true)
2498
+ {
2499
+ data = $.parseJSON(json);
2500
+ html = '<p><img src="' + data.filelink + '" /></p>';
2501
+ }
2502
+ else
2503
+ {
2504
+ html = json;
2505
+ }
1642
2506
 
1643
2507
  this.focus();
1644
2508
 
@@ -1652,7 +2516,16 @@ var RTOOLBAR = {};
1652
2516
  this.execCommand('inserthtml', html);
1653
2517
  }
1654
2518
 
2519
+ // upload image callback
2520
+ if (link !== true && typeof this.opts.imageUploadCallback === 'function')
2521
+ {
2522
+ this.opts.imageUploadCallback(this, data);
2523
+ }
2524
+
1655
2525
  this.modalClose();
2526
+
2527
+ if (this.opts.autoresize === true) this.setAutoSize(false);
2528
+
1656
2529
  this.observeImages();
1657
2530
  },
1658
2531
 
@@ -1662,106 +2535,118 @@ var RTOOLBAR = {};
1662
2535
  var handler = $.proxy(function()
1663
2536
  {
1664
2537
  var sel = this.getSelection();
2538
+ var url = '', text = '';
1665
2539
 
1666
2540
  if ($.browser.msie)
1667
2541
  {
1668
2542
  var parent = this.getParentNode();
1669
- if (parent.nodeName == 'A')
2543
+ if (parent.nodeName === 'A')
1670
2544
  {
1671
2545
  this.insert_link_node = $(parent);
1672
- var text = this.insert_link_node.text();
1673
- var url = this.insert_link_node.attr('href');
2546
+ text = this.insert_link_node.text();
2547
+ url = this.insert_link_node.attr('href');
1674
2548
  }
1675
2549
  else
1676
2550
  {
1677
- if (this.oldIE()) var text = sel.text;
1678
- else var text = sel.toString();
1679
-
1680
- var url = '';
1681
-
2551
+ if (this.oldIE())
2552
+ {
2553
+ text = sel.text;
2554
+ }
2555
+ else
2556
+ {
2557
+ text = sel.toString();
2558
+ }
2559
+
1682
2560
  this.spanid = Math.floor(Math.random() * 99999);
1683
2561
 
1684
2562
  var html = '<span id="span' + this.spanid + '">' + text + '</span>';
1685
- if (text != '') html = '<span id="span' + this.spanid + '">' + text + '</span>';
2563
+
2564
+ if (text !== '')
2565
+ {
2566
+ html = '<span id="span' + this.spanid + '">' + text + '</span>';
2567
+ }
2568
+
1686
2569
  this.execCommand('inserthtml', html);
1687
2570
  }
1688
2571
  }
1689
2572
  else
1690
- {
1691
- if (sel && sel.anchorNode.parentNode.tagName == 'A')
2573
+ {
2574
+ if (sel && sel.anchorNode && sel.anchorNode.parentNode.tagName === 'A')
1692
2575
  {
1693
- var url = sel.anchorNode.parentNode.href;
1694
- var text = sel.anchorNode.parentNode.text;
1695
- if (sel.toString() === '') this.insert_link_node = sel.anchorNode.parentNode;
2576
+ url = sel.anchorNode.parentNode.href;
2577
+ text = sel.anchorNode.parentNode.text;
2578
+ if (sel.toString() === '')
2579
+ {
2580
+ this.insert_link_node = sel.anchorNode.parentNode;
2581
+ }
1696
2582
  }
1697
2583
  else
1698
2584
  {
1699
- var text = sel.toString();
1700
- var url = '';
2585
+ text = sel.toString();
2586
+ url = '';
1701
2587
  }
1702
2588
  }
1703
2589
 
1704
2590
  $('.redactor_link_text').val(text);
1705
- $('#redactor_link_url').val(url).focus();
1706
2591
 
1707
- $('#redactor_insert_link_btn').click($.proxy(this.insertLink, this));
2592
+ var turl = url.replace(top.location.href, '');
1708
2593
 
1709
- if (this.opts.linkFileUpload === false)
2594
+ if (url.search('mailto:') === 0)
1710
2595
  {
1711
- $('#redactor_tabs a').eq(3).remove();
2596
+ this.setModalTab(2);
2597
+
2598
+ $('#redactor_tab_selected').val(2);
2599
+ $('#redactor_link_mailto').val(url.replace('mailto:', ''));
1712
2600
  }
1713
- else
2601
+ else if (turl.search(/^#/gi) === 0)
1714
2602
  {
1715
- // dragupload
1716
- if ($('#redactor_file').size() != 0)
1717
- {
1718
- $('#redactor_file').dragupload(
1719
- {
1720
- url: this.opts.linkFileUpload,
1721
- success: $.proxy(this.insertLinkFile, this)
1722
- });
1723
- }
1724
-
1725
- // ajax upload
1726
- this.uploadInit('redactor_file', { auto: true, url: this.opts.linkFileUpload, success: $.proxy(this.insertLinkFile, this) });
2603
+ this.setModalTab(3);
2604
+
2605
+ $('#redactor_tab_selected').val(3);
2606
+ $('#redactor_link_anchor').val(turl.replace(/^#/gi, ''));
1727
2607
  }
2608
+ else
2609
+ {
2610
+ $('#redactor_link_url').val(url);
2611
+ }
2612
+
2613
+ $('#redactor_insert_link_btn').click($.proxy(this.insertLink, this));
2614
+
1728
2615
 
1729
2616
  }, this);
1730
2617
 
1731
- this.modalInit(RLANG.link, this.opts.path + '/plugins/link.html', 460, handler);
2618
+ var endCallback = function(url)
2619
+ {
2620
+ $('#redactor_link_url').focus();
2621
+ };
2622
+
2623
+ this.modalInit(RLANG.link, 'link', 460, handler, endCallback);
1732
2624
 
1733
2625
  },
1734
2626
  insertLink: function()
1735
2627
  {
1736
2628
  var tab_selected = $('#redactor_tab_selected').val();
1737
-
1738
2629
  var link = '', text = '';
1739
2630
 
1740
- if (tab_selected == 1) // url
2631
+ if (tab_selected === '1') // url
1741
2632
  {
1742
2633
  link = $('#redactor_link_url').val();
1743
2634
  text = $('#redactor_link_url_text').val();
1744
2635
  }
1745
- else if (tab_selected == 2) // mailto
2636
+ else if (tab_selected === '2') // mailto
1746
2637
  {
1747
2638
  link = 'mailto:' + $('#redactor_link_mailto').val();
1748
2639
  text = $('#redactor_link_mailto_text').val();
1749
2640
  }
1750
- else if (tab_selected == 3) // anchor
2641
+ else if (tab_selected === '3') // anchor
1751
2642
  {
1752
2643
  link = '#' + $('#redactor_link_anchor').val();
1753
2644
  text = $('#redactor_link_anchor_text').val();
1754
- }
2645
+ }
1755
2646
 
1756
2647
  this._insertLink('<a href="' + link + '">' + text + '</a> ', $.trim(text), link);
1757
2648
 
1758
2649
  },
1759
- insertLinkFile: function(data)
1760
- {
1761
- text = $('#redactor_link_file_text').val();
1762
-
1763
- this._insertLink('<a href="' + data + '">' + text + '</a> ', $.trim(text), data);
1764
- },
1765
2650
  _insertLink: function(a, text, link)
1766
2651
  {
1767
2652
  if (text != '')
@@ -1779,7 +2664,10 @@ var RTOOLBAR = {};
1779
2664
  $(this.doc.getElementById('span' + this.spanid)).replaceWith(a);
1780
2665
  this.syncCode();
1781
2666
  }
1782
- else this.execCommand('inserthtml', a);
2667
+ else
2668
+ {
2669
+ this.execCommand('inserthtml', a);
2670
+ }
1783
2671
  }
1784
2672
  }
1785
2673
 
@@ -1789,10 +2677,28 @@ var RTOOLBAR = {};
1789
2677
  // INSERT FILE
1790
2678
  showFile: function()
1791
2679
  {
1792
- if ($.browser.msie) this.markerIE();
2680
+ if ($.browser.msie)
2681
+ {
2682
+ this.markerIE();
2683
+ }
1793
2684
 
1794
2685
  var handler = $.proxy(function()
1795
2686
  {
2687
+ var sel = this.getSelection();
2688
+
2689
+ var text = '';
2690
+
2691
+ if (this.oldIE())
2692
+ {
2693
+ text = sel.text;
2694
+ }
2695
+ else
2696
+ {
2697
+ text = sel.toString();
2698
+ }
2699
+
2700
+ $('#redactor_filename').val(text);
2701
+
1796
2702
  $('#redactor_file').dragupload(
1797
2703
  {
1798
2704
  url: this.opts.fileUpload,
@@ -1809,30 +2715,60 @@ var RTOOLBAR = {};
1809
2715
  }, this)});
1810
2716
  }, this);
1811
2717
 
1812
- this.modalInit(RLANG.file, this.opts.path + '/plugins/file.html', 500, handler);
2718
+ this.modalInit(RLANG.file, 'file', 500, handler);
1813
2719
  },
1814
- fileUploadCallback: function(data)
2720
+ fileUploadCallback: function(json)
1815
2721
  {
2722
+ var data = $.parseJSON(json);
2723
+ var text = $('#redactor_filename').val();
2724
+
2725
+ if (text === '')
2726
+ {
2727
+ text = data.filename;
2728
+ }
2729
+
2730
+ var link = '<a href="' + data.filelink + '">' + text + '</a>';
2731
+
1816
2732
  // chrome fix
1817
- if ($.browser.webkit && !!window.chrome) data = data + '&nbsp;';
2733
+ if ($.browser.webkit && !!window.chrome)
2734
+ {
2735
+ link = link + '&nbsp;';
2736
+ }
1818
2737
 
1819
2738
  if ($.browser.msie)
1820
2739
  {
1821
- $(this.doc.getElementById('span' + this.spanid)).after(data).remove();
2740
+ if (text !== '')
2741
+ {
2742
+ $(this.doc.getElementById('span' + this.spanid)).replaceWith(link);
2743
+ }
2744
+ else
2745
+ {
2746
+ $(this.doc.getElementById('span' + this.spanid)).after(link).remove();
2747
+ }
2748
+
1822
2749
  this.syncCode();
1823
2750
  }
1824
- else this.execCommand('inserthtml', data);
2751
+ else
2752
+ {
2753
+ this.execCommand('inserthtml', link);
2754
+ }
1825
2755
 
2756
+ // file upload callback
2757
+ if (typeof this.opts.fileUploadCallback === 'function')
2758
+ {
2759
+ this.opts.fileUploadCallback(this, data);
2760
+ }
2761
+
1826
2762
  this.modalClose();
1827
2763
  },
1828
2764
 
1829
2765
 
1830
2766
 
1831
2767
  // MODAL
1832
- modalInit: function(title, url, width, handler, scroll)
2768
+ modalInit: function(title, url, width, handler, endCallback, scroll)
1833
2769
  {
1834
2770
  // modal overlay
1835
- if ($('#redactor_modal_overlay').size() == 0)
2771
+ if ($('#redactor_modal_overlay').size() === 0)
1836
2772
  {
1837
2773
  this.overlay = $('<div id="redactor_modal_overlay" style="display: none;"></div>');
1838
2774
  $('body').prepend(this.overlay);
@@ -1844,7 +2780,7 @@ var RTOOLBAR = {};
1844
2780
  $('#redactor_modal_overlay').click($.proxy(this.modalClose, this));
1845
2781
  }
1846
2782
 
1847
- if ($('#redactor_modal').size() == 0)
2783
+ if ($('#redactor_modal').size() === 0)
1848
2784
  {
1849
2785
  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>');
1850
2786
  $('body').append(this.modal);
@@ -1852,64 +2788,58 @@ var RTOOLBAR = {};
1852
2788
 
1853
2789
  $('#redactor_modal_close').click($.proxy(this.modalClose, this));
1854
2790
 
1855
- this.hdlModalClose = $.proxy(function(e) { if( e.keyCode == 27) this.modalClose(); }, this);
2791
+ this.hdlModalClose = $.proxy(function(e) { if ( e.keyCode === 27) { this.modalClose(); } }, this);
1856
2792
 
1857
2793
  $(document).keyup(this.hdlModalClose);
1858
2794
  $(this.doc).keyup(this.hdlModalClose);
1859
2795
 
1860
- $.ajax({
1861
- dataType: 'html',
1862
- type: 'get',
1863
- url: url,
1864
- success: $.proxy(function(data)
2796
+ $('#redactor_modal_inner').html(this.opts['modal_' + url]);
2797
+ $('#redactor_modal_header').html(title);
2798
+
2799
+ // tabs
2800
+ if ($('#redactor_tabs').size() !== 0)
2801
+ {
2802
+ $('#redactor_tabs a').each(function(i,s)
1865
2803
  {
1866
- // parse lang
1867
- $.each(RLANG, function(i,s)
2804
+ i++;
2805
+ $(s).click(function()
1868
2806
  {
1869
- var re = new RegExp("%RLANG\." + i + "%","gi");
1870
- data = data.replace(re, s);
2807
+ $('#redactor_tabs a').removeClass('redactor_tabs_act');
2808
+ $(this).addClass('redactor_tabs_act');
2809
+ $('.redactor_tab').hide();
2810
+ $('#redactor_tab' + i).show();
2811
+ $('#redactor_tab_selected').val(i);
2812
+
2813
+ var height = $('#redactor_modal').outerHeight();
2814
+ $('#redactor_modal').css('margin-top', '-' + (height+10)/2 + 'px');
1871
2815
  });
2816
+ });
2817
+ }
1872
2818
 
1873
- $('#redactor_modal_inner').html(data);
1874
- $('#redactor_modal_header').html(title);
1875
-
1876
- // tabs
1877
- if ($('#redactor_tabs').size() != 0)
1878
- {
1879
- $('#redactor_tabs a').each(function(i,s)
1880
- {
1881
- i++;
1882
- $(s).click(function()
1883
- {
1884
- $('#redactor_tabs a').removeClass('redactor_tabs_act');
1885
- $(this).addClass('redactor_tabs_act');
1886
- $('.redactor_tab').hide();
1887
- $('#redactor_tab' + i).show();
1888
- $('#redactor_tab_selected').val(i);
1889
-
1890
- var height = $('#redactor_modal').outerHeight();
1891
- $('#redactor_modal').css('margin-top', '-' + (height+10)/2 + 'px');
1892
- });
1893
- });
1894
- }
2819
+ $('#redactor_btn_modal_close').click($.proxy(this.modalClose, this));
2820
+
2821
+ // callback
2822
+ if (typeof(handler) === 'function')
2823
+ {
2824
+ handler();
2825
+ }
2826
+
2827
+ // setup
2828
+ var height = $('#redactor_modal').outerHeight();
2829
+
2830
+ $('#redactor_modal').css({ width: width + 'px', height: 'auto', marginTop: '-' + (height+10)/2 + 'px', marginLeft: '-' + (width+60)/2 + 'px' }).fadeIn('fast');
1895
2831
 
1896
- $('#redactor_btn_modal_close').click($.proxy(this.modalClose, this));
1897
-
1898
- // callback
1899
- if (typeof(handler) == 'function') handler();
1900
-
1901
- // setup
1902
- var height = $('#redactor_modal').outerHeight();
1903
-
1904
- $('#redactor_modal').css({ width: width + 'px', height: 'auto', marginTop: '-' + (height+10)/2 + 'px', marginLeft: '-' + (width+60)/2 + 'px' }).fadeIn('fast');
2832
+ // end callback
2833
+ if (typeof(endCallback) === 'function')
2834
+ {
2835
+ endCallback();
2836
+ }
1905
2837
 
1906
- if (scroll === true)
1907
- {
1908
- $('#redactor_image_box').height(300).css('overflow', 'auto');
1909
- }
2838
+ if (scroll === true)
2839
+ {
2840
+ $('#redactor_image_box').height(300).css('overflow', 'auto');
2841
+ }
1910
2842
 
1911
- }, this)
1912
- });
1913
2843
  },
1914
2844
  modalClose: function()
1915
2845
  {
@@ -1931,6 +2861,14 @@ var RTOOLBAR = {};
1931
2861
  }, this));
1932
2862
 
1933
2863
  },
2864
+ setModalTab: function(num)
2865
+ {
2866
+ $('.redactor_tab').hide();
2867
+ var tabs = $('#redactor_tabs a');
2868
+ tabs.removeClass('redactor_tabs_act');
2869
+ tabs.eq(num-1).addClass('redactor_tabs_act');
2870
+ $('#redactor_tab' + num).show();
2871
+ },
1934
2872
 
1935
2873
  // UPLOAD
1936
2874
  uploadInit: function(element, options)
@@ -1948,7 +2886,7 @@ var RTOOLBAR = {};
1948
2886
  $.extend(this.uploadOptions, options);
1949
2887
 
1950
2888
  // Test input or form
1951
- if ($('#' + element).size() != 0 && $('#' + element).get(0).tagName == 'INPUT')
2889
+ if ($('#' + element).size() !== 0 && $('#' + element).get(0).tagName === 'INPUT')
1952
2890
  {
1953
2891
  this.uploadOptions.input = $('#' + element);
1954
2892
  this.element = $($('#' + element).get(0).form);
@@ -1989,7 +2927,10 @@ var RTOOLBAR = {};
1989
2927
  document.body.appendChild(d);
1990
2928
 
1991
2929
  // Start
1992
- if (this.uploadOptions.start) this.uploadOptions.start();
2930
+ if (this.uploadOptions.start)
2931
+ {
2932
+ this.uploadOptions.start();
2933
+ }
1993
2934
 
1994
2935
  $('#' + this.id).load($.proxy(this.uploadLoaded, this));
1995
2936
 
@@ -2029,15 +2970,31 @@ var RTOOLBAR = {};
2029
2970
  uploadLoaded : function()
2030
2971
  {
2031
2972
  var i = $('#' + this.id);
2032
-
2033
- if (i.contentDocument) var d = i.contentDocument;
2034
- else if (i.contentWindow) var d = i.contentWindow.document;
2035
- else var d = window.frames[this.id].document;
2973
+ var d;
2974
+
2975
+ if (i.contentDocument)
2976
+ {
2977
+ d = i.contentDocument;
2978
+ }
2979
+ else if (i.contentWindow)
2980
+ {
2981
+ d = i.contentWindow.document;
2982
+ }
2983
+ else
2984
+ {
2985
+ d = window.frames[this.id].document;
2986
+ }
2036
2987
 
2037
- if (d.location.href == "about:blank") return true;
2988
+ if (d.location.href === "about:blank")
2989
+ {
2990
+ return true;
2991
+ }
2038
2992
 
2039
2993
  // Success
2040
- if (this.uploadOptions.success) this.uploadOptions.success(d.body.innerHTML);
2994
+ if (this.uploadOptions.success)
2995
+ {
2996
+ this.uploadOptions.success(d.body.innerHTML);
2997
+ }
2041
2998
 
2042
2999
  this.element.attr('action', this.element_action);
2043
3000
  this.element.attr('target', '');
@@ -2052,7 +3009,11 @@ var RTOOLBAR = {};
2052
3009
  },
2053
3010
  oldIE: function()
2054
3011
  {
2055
- if ($.browser.msie && parseInt($.browser.version, 10) < 9) return true;
3012
+ if ($.browser.msie && parseInt($.browser.version, 10) < 9)
3013
+ {
3014
+ return true;
3015
+ }
3016
+
2056
3017
  return false;
2057
3018
  },
2058
3019
  outerHTML: function(s)
@@ -2061,7 +3022,7 @@ var RTOOLBAR = {};
2061
3022
  },
2062
3023
  normalize: function(str)
2063
3024
  {
2064
- return parseInt(str.replace('px',''));
3025
+ return parseInt(str.replace('px',''), 10);
2065
3026
  }
2066
3027
 
2067
3028
  };
@@ -2088,6 +3049,11 @@ var RTOOLBAR = {};
2088
3049
  return this.data('redactor').getCode();
2089
3050
  };
2090
3051
 
3052
+ $.fn.getText = function()
3053
+ {
3054
+ return this.data('redactor').$editor.text();
3055
+ };
3056
+
2091
3057
  $.fn.setCode = function(html)
2092
3058
  {
2093
3059
  this.data('redactor').setCode(html);
@@ -2103,7 +3069,7 @@ var RTOOLBAR = {};
2103
3069
  this.data('redactor').destroy();
2104
3070
  this.removeData('redactor');
2105
3071
  };
2106
-
3072
+
2107
3073
  $.fn.setFocus = function()
2108
3074
  {
2109
3075
  this.data('redactor').focus();
@@ -2123,6 +3089,8 @@ var RTOOLBAR = {};
2123
3089
  */
2124
3090
  (function($){
2125
3091
 
3092
+ "use strict";
3093
+
2126
3094
  // Initialization
2127
3095
  $.fn.dragupload = function(options)
2128
3096
  {
@@ -2171,6 +3139,22 @@ var RTOOLBAR = {};
2171
3139
  // drag leave
2172
3140
  this.dropareabox.bind('dragleave', $.proxy(function() { return this.ondragleave(); }, this));
2173
3141
 
3142
+ var uploadProgress = $.proxy(function(e)
3143
+ {
3144
+ var percent = parseInt(e.loaded / e.total * 100, 10);
3145
+ this.dropareabox.text('Loading ' + percent + '%');
3146
+
3147
+ }, this);
3148
+
3149
+ var xhr = jQuery.ajaxSettings.xhr();
3150
+
3151
+ if (xhr.upload)
3152
+ {
3153
+ xhr.upload.addEventListener('progress', uploadProgress, false);
3154
+ }
3155
+
3156
+ var provider = function () { return xhr; };
3157
+
2174
3158
  // drop
2175
3159
  this.dropareabox.get(0).ondrop = $.proxy(function(event)
2176
3160
  {
@@ -2187,15 +3171,23 @@ var RTOOLBAR = {};
2187
3171
  dataType: 'html',
2188
3172
  url: this.opts.url,
2189
3173
  data: fd,
2190
- //xhr: provider,
3174
+ xhr: provider,
2191
3175
  cache: false,
2192
3176
  contentType: false,
2193
3177
  processData: false,
2194
3178
  type: 'POST',
2195
3179
  success: $.proxy(function(data)
2196
3180
  {
2197
- if (this.opts.success !== false) this.opts.success(data);
2198
- if (this.opts.preview === true) this.dropareabox.html(data);
3181
+ if (this.opts.success !== false)
3182
+ {
3183
+ this.opts.success(data);
3184
+ }
3185
+
3186
+ if (this.opts.preview === true)
3187
+ {
3188
+ this.dropareabox.html(data);
3189
+ }
3190
+
2199
3191
  }, this)
2200
3192
  });
2201
3193
 
@@ -2220,6 +3212,8 @@ var RTOOLBAR = {};
2220
3212
  // Define: Linkify plugin from stackoverflow
2221
3213
  (function($){
2222
3214
 
3215
+ "use strict";
3216
+
2223
3217
  var url1 = /(^|&lt;|\s)(www\..+?\..+?)(\s|&gt;|$)/g,
2224
3218
  url2 = /(^|&lt;|\s)(((https?|ftp):\/\/|mailto:).+?)(\s|&gt;|$)/g,
2225
3219
 
@@ -2230,7 +3224,7 @@ var RTOOLBAR = {};
2230
3224
  while(i--)
2231
3225
  {
2232
3226
  var n = childNodes[i];
2233
- if (n.nodeType == 3)
3227
+ if (n.nodeType === 3)
2234
3228
  {
2235
3229
  var html = n.nodeValue;
2236
3230
  if (html)
@@ -2244,7 +3238,7 @@ var RTOOLBAR = {};
2244
3238
  $(n).after(html).remove();
2245
3239
  }
2246
3240
  }
2247
- else if (n.nodeType == 1 && !/^(a|button|textarea)$/i.test(n.tagName))
3241
+ else if (n.nodeType === 1 && !/^(a|button|textarea)$/i.test(n.tagName))
2248
3242
  {
2249
3243
  linkifyThis.call(n);
2250
3244
  }