comfortable_mexican_sofa 1.0.24 → 1.0.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.24
1
+ 1.0.25
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{comfortable_mexican_sofa}
8
- s.version = "1.0.24"
8
+ s.version = "1.0.25"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Oleg Khabarov", "The Working Group Inc"]
12
- s.date = %q{2010-11-16}
12
+ s.date = %q{2010-11-17}
13
13
  s.description = %q{}
14
14
  s.email = %q{oleg@theworkinggroup.ca}
15
15
  s.extra_rdoc_files = [
@@ -88,6 +88,7 @@ Gem::Specification.new do |s|
88
88
  "lib/comfortable_mexican_sofa/cms_tag/helper.rb",
89
89
  "lib/comfortable_mexican_sofa/cms_tag/page_datetime.rb",
90
90
  "lib/comfortable_mexican_sofa/cms_tag/page_integer.rb",
91
+ "lib/comfortable_mexican_sofa/cms_tag/page_rich_text.rb",
91
92
  "lib/comfortable_mexican_sofa/cms_tag/page_string.rb",
92
93
  "lib/comfortable_mexican_sofa/cms_tag/page_text.rb",
93
94
  "lib/comfortable_mexican_sofa/cms_tag/partial.rb",
@@ -112,6 +113,11 @@ Gem::Specification.new do |s|
112
113
  "public/javascripts/comfortable_mexican_sofa/cms.js",
113
114
  "public/javascripts/comfortable_mexican_sofa/jquery-ui.js",
114
115
  "public/javascripts/comfortable_mexican_sofa/jquery.js",
116
+ "public/javascripts/comfortable_mexican_sofa/jwysiwyg/jquery.wysiwyg.css",
117
+ "public/javascripts/comfortable_mexican_sofa/jwysiwyg/jquery.wysiwyg.gif",
118
+ "public/javascripts/comfortable_mexican_sofa/jwysiwyg/jquery.wysiwyg.jpg",
119
+ "public/javascripts/comfortable_mexican_sofa/jwysiwyg/jquery.wysiwyg.js",
120
+ "public/javascripts/comfortable_mexican_sofa/jwysiwyg/jquery.wysiwyg.modal.css",
115
121
  "public/javascripts/comfortable_mexican_sofa/plupload/plupload.full.min.js",
116
122
  "public/javascripts/comfortable_mexican_sofa/plupload/plupload.html4.min.js",
117
123
  "public/javascripts/comfortable_mexican_sofa/plupload/plupload.html5.min.js",
@@ -165,6 +171,7 @@ Gem::Specification.new do |s|
165
171
  "test/unit/cms_tags/helper_test.rb",
166
172
  "test/unit/cms_tags/page_datetime_test.rb",
167
173
  "test/unit/cms_tags/page_integer_test.rb",
174
+ "test/unit/cms_tags/page_rich_text.rb",
168
175
  "test/unit/cms_tags/page_string_test.rb",
169
176
  "test/unit/cms_tags/page_text_test.rb",
170
177
  "test/unit/cms_tags/partial_test.rb",
@@ -205,6 +212,7 @@ Gem::Specification.new do |s|
205
212
  "test/unit/cms_tags/helper_test.rb",
206
213
  "test/unit/cms_tags/page_datetime_test.rb",
207
214
  "test/unit/cms_tags/page_integer_test.rb",
215
+ "test/unit/cms_tags/page_rich_text.rb",
208
216
  "test/unit/cms_tags/page_string_test.rb",
209
217
  "test/unit/cms_tags/page_text_test.rb",
210
218
  "test/unit/cms_tags/partial_test.rb",
@@ -0,0 +1,22 @@
1
+ class CmsTag::PageRichText < CmsBlock
2
+
3
+ include CmsTag
4
+
5
+ def self.regex_tag_signature(label = nil)
6
+ label ||= /\w+/
7
+ /\{\{\s*cms:page:(#{label}):rich_text\s*\}\}/
8
+ end
9
+
10
+ def regex_tag_signature
11
+ self.class.regex_tag_signature(label)
12
+ end
13
+
14
+ def content=(value)
15
+ write_attribute(:content, value)
16
+ end
17
+
18
+ def content
19
+ read_attribute(:content)
20
+ end
21
+
22
+ end
@@ -103,6 +103,10 @@ class ComfortableMexicanSofa::FormBuilder < ActionView::Helpers::FormBuilder
103
103
  default_tag_field(tag, :content_field_method => :text_area_tag)
104
104
  end
105
105
 
106
+ def page_rich_text(tag)
107
+ default_tag_field(tag, :content_field_method => :text_area_tag)
108
+ end
109
+
106
110
  # Capturing all calls of cms_tag_* type. For those we'll try to render
107
111
  # a form element. Everything else can trigger MethodNotFound error.
108
112
  def method_missing(method_name, *args)
@@ -47,10 +47,12 @@ ActionView::Helpers::AssetTagHelper.register_javascript_expansion :cms => [
47
47
  'comfortable_mexican_sofa/rails',
48
48
  'comfortable_mexican_sofa/cms',
49
49
  'comfortable_mexican_sofa/plupload/plupload.full.min',
50
- 'comfortable_mexican_sofa/uploader'
50
+ 'comfortable_mexican_sofa/uploader',
51
+ 'comfortable_mexican_sofa/jwysiwyg/jquery.wysiwyg.js'
51
52
  ]
52
53
  ActionView::Helpers::AssetTagHelper.register_stylesheet_expansion :cms => [
53
54
  'comfortable_mexican_sofa/reset',
54
55
  'comfortable_mexican_sofa/structure',
55
- 'comfortable_mexican_sofa/typography'
56
+ 'comfortable_mexican_sofa/typography',
57
+ '../javascripts/comfortable_mexican_sofa/jwysiwyg/jquery.wysiwyg.css'
56
58
  ]
@@ -31,9 +31,17 @@ $.CMS = function(){
31
31
 
32
32
  // Load Page Blocks on layout change
33
33
  $('select#cms_page_cms_layout_id').bind('change.cms', function() {
34
- $.ajax({url: ['/' + $(this).attr('data-path-prefix'), 'pages', $(this).attr('data-page-id'), 'form_blocks'].join('/'), data: ({ layout_id: $(this).val()})})
34
+ $.ajax({
35
+ url: ['/' + $(this).attr('data-path-prefix'), 'pages', $(this).attr('data-page-id'), 'form_blocks'].join('/'),
36
+ data: ({
37
+ layout_id: $(this).val()
38
+ }),
39
+ complete: function(){ $.CMS.enable_rich_text() }
40
+ })
35
41
  })
36
42
 
43
+ $.CMS.enable_rich_text();
44
+
37
45
  }); // End $(document).ready()
38
46
 
39
47
  return {
@@ -46,6 +54,16 @@ $.CMS = function(){
46
54
  }
47
55
  str = str.replace(/[^a-zA-Z0-9 -]/g, '').replace(/\s+/g, '-').toLowerCase();
48
56
  return str;
57
+ },
58
+
59
+ enable_rich_text: function(){
60
+ $('.form_element.cms_tag_page_rich_text textarea').wysiwyg({
61
+ controls: {
62
+ html: { visible: true },
63
+ undo: { visible : false },
64
+ redo: { visible : false }
65
+ }
66
+ });
49
67
  }
50
68
  }
51
69
  }();
@@ -0,0 +1,62 @@
1
+
2
+ div.wysiwyg { border: 1px solid #ccc; padding: 5px; background-color: #fff; }
3
+ div.wysiwyg * { margin: 0; padding: 0; }
4
+
5
+ div.wysiwyg ul.panel li.jwysiwyg-custom-command {overflow:hidden;}
6
+ div.wysiwyg ul.panel li.jwysiwyg-custom-command img { margin-left: 5000px; }
7
+
8
+ div.wysiwyg ul.panel { border-bottom: 1px solid #ccc; float: left; width: 100%; padding: 0; }
9
+ div.wysiwyg ul.panel li { list-style: none; float: left; margin: 1px 2px 3px 0; background: #fff; -moz-user-select: none; -webkit-user-select: none; user-select: none;}
10
+ div.wysiwyg ul.panel li.separator { width: 1px; height: 16px; margin: 0 4px; border-left: 1px solid #ccc; }
11
+ div.wysiwyg ul.panel li { text-indent: -5000px; opacity: 0.85; filter:alpha(opacity=85); display: block; width: 16px; height: 16px; background: url('jquery.wysiwyg.gif') no-repeat -64px -80px; border: 0; cursor: pointer; margin: 1px; }
12
+ div.wysiwyg ul.panel li.wysiwyg-button-hover, div.wysiwyg ul.panel li.active { opacity: 1.00; filter:alpha(opacity=100); }
13
+ div.wysiwyg ul.panel li.active { background-color: #f9f9f9; border: 1px solid #ccc; border-left-color: #aaa; border-top-color: #aaa; margin: 0; }
14
+
15
+ div.wysiwyg ul.panel li.bold { background-position: 0 -16px; }
16
+ div.wysiwyg ul.panel li.italic { background-position: -16px -16px; }
17
+ div.wysiwyg ul.panel li.strikeThrough { background-position: -32px -16px; }
18
+ div.wysiwyg ul.panel li.underline { background-position: -48px -16px; }
19
+
20
+ div.wysiwyg ul.panel li.justifyLeft { background-position: 0 0; }
21
+ div.wysiwyg ul.panel li.justifyCenter { background-position: -16px 0; }
22
+ div.wysiwyg ul.panel li.justifyRight { background-position: -32px 0; }
23
+ div.wysiwyg ul.panel li.justifyFull { background-position: -48px 0; }
24
+
25
+ div.wysiwyg ul.panel li.indent { background-position: -64px 0; }
26
+ div.wysiwyg ul.panel li.outdent { background-position: -80px 0; }
27
+
28
+ div.wysiwyg ul.panel li.subscript { background-position: -64px -16px; }
29
+ div.wysiwyg ul.panel li.superscript { background-position: -80px -16px; }
30
+
31
+ div.wysiwyg ul.panel li.undo { background-position: 0 -64px; }
32
+ div.wysiwyg ul.panel li.redo { background-position: -16px -64px; }
33
+
34
+ div.wysiwyg ul.panel li.insertOrderedList { background-position: -32px -48px; }
35
+ div.wysiwyg ul.panel li.insertUnorderedList { background-position: -16px -48px; }
36
+ div.wysiwyg ul.panel li.insertHorizontalRule { background-position: 0 -48px; }
37
+
38
+ div.wysiwyg ul.panel li.h1 { background-position: 0 -32px; }
39
+ div.wysiwyg ul.panel li.h2 { background-position: -16px -32px; }
40
+ div.wysiwyg ul.panel li.h3 { background-position: -32px -32px; }
41
+ div.wysiwyg ul.panel li.h4 { background-position: -48px -32px; }
42
+ div.wysiwyg ul.panel li.h5 { background-position: -64px -32px; }
43
+ div.wysiwyg ul.panel li.h6 { background-position: -80px -32px; }
44
+
45
+ div.wysiwyg ul.panel li.cut { background-position: -32px -64px; }
46
+ div.wysiwyg ul.panel li.copy { background-position: -48px -64px; }
47
+ div.wysiwyg ul.panel li.paste { background-position: -64px -64px; }
48
+ div.wysiwyg ul.panel li.insertTable { background-position: -64px -48px; }
49
+
50
+ div.wysiwyg ul.panel li.increaseFontSize { background-position: -16px -80px; }
51
+ div.wysiwyg ul.panel li.decreaseFontSize { background-position: -32px -80px; }
52
+
53
+ div.wysiwyg ul.panel li.createLink { background-position: -80px -48px; }
54
+ div.wysiwyg ul.panel li.insertImage { background-position: -80px -80px; }
55
+
56
+ div.wysiwyg ul.panel li.html { background-position: -47px -46px; }
57
+ div.wysiwyg ul.panel li.removeFormat { background-position: -80px -63px; }
58
+
59
+ div.wysiwyg ul.panel li.empty { background-position: -64px -80px; }
60
+
61
+ div.wysiwyg iframe { border: 0; clear: left; margin: 4px 0 0 1px; }
62
+
@@ -0,0 +1,1393 @@
1
+ /**
2
+ * WYSIWYG - jQuery plugin 0.93
3
+ * (koken)
4
+ *
5
+ * Copyright (c) 2008-2009 Juan M Martinez, 2010 Akzhan Abdulin and all contrbutors
6
+ * http://plugins.jquery.com/project/jWYSIWYG
7
+ *
8
+ * Dual licensed under the MIT and GPL licenses:
9
+ * http://www.opensource.org/licenses/mit-license.php
10
+ * http://www.gnu.org/licenses/gpl.html
11
+ *
12
+ * $Id: $
13
+ */
14
+
15
+ /*jslint browser: true, forin: true */
16
+
17
+ (function ($)
18
+ {
19
+ /**
20
+ * @constructor
21
+ * @private
22
+ */
23
+ var Wysiwyg = function (element, options)
24
+ {
25
+ this.init(element, options);
26
+ };
27
+
28
+ var innerDocument = function (elts)
29
+ {
30
+ var element = $(elts).get(0);
31
+
32
+ if (element.nodeName.toLowerCase() == 'iframe')
33
+ {
34
+ return element.contentWindow.document;
35
+ /*
36
+ return ( $.browser.msie )
37
+ ? document.frames[element.id].document
38
+ : element.contentWindow.document // contentDocument;
39
+ */
40
+ }
41
+ return element;
42
+ };
43
+
44
+ var documentSelection = function ()
45
+ {
46
+ var element = this.get(0);
47
+
48
+ if (element.contentWindow.document.selection)
49
+ {
50
+ return element.contentWindow.document.selection.createRange().text;
51
+ }
52
+ else
53
+ {
54
+ return element.contentWindow.getSelection().toString();
55
+ }
56
+ };
57
+
58
+ $.fn.wysiwyg = function (options)
59
+ {
60
+ if (arguments.length > 0 && arguments[0].constructor == String)
61
+ {
62
+ var action = arguments[0].toString();
63
+ var params = [];
64
+
65
+ if (action == 'enabled')
66
+ {
67
+ return this.data('wysiwyg') !== null;
68
+ }
69
+ for (var i = 1; i < arguments.length; i++)
70
+ {
71
+ params[i - 1] = arguments[i];
72
+ }
73
+ var retValue = null;
74
+
75
+ // .filter('textarea') is a fix for bug 29 ( http://github.com/akzhan/jwysiwyg/issues/issue/29 )
76
+ this.filter('textarea').each(function()
77
+ {
78
+ $.data(this, 'wysiwyg').designMode();
79
+ retValue = Wysiwyg[action].apply(this, params);
80
+ });
81
+ return retValue;
82
+ }
83
+
84
+ if (this.data('wysiwyg'))
85
+ {
86
+ return this;
87
+ }
88
+
89
+ var controls = { };
90
+
91
+ /**
92
+ * If the user set custom controls, we catch it, and merge with the
93
+ * defaults controls later.
94
+ */
95
+
96
+ if (options && options.controls)
97
+ {
98
+ controls = options.controls;
99
+ delete options.controls;
100
+ }
101
+
102
+ options = $.extend({}, $.fn.wysiwyg.defaults, options);
103
+ options.controls = $.extend(true, options.controls, $.fn.wysiwyg.controls);
104
+ for (var control in controls)
105
+ {
106
+ if (control in options.controls)
107
+ {
108
+ $.extend(options.controls[control], controls[control]);
109
+ }
110
+ else
111
+ {
112
+ options.controls[control] = controls[control];
113
+ }
114
+ }
115
+
116
+ // not break the chain
117
+ return this.each(function ()
118
+ {
119
+ new Wysiwyg(this, options);
120
+ });
121
+ };
122
+
123
+ $.fn.wysiwyg.defaults = {
124
+ html: '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">STYLE_SHEET</head><body style="margin: 0px;">INITIAL_CONTENT</body></html>',
125
+ formTableHtml: '<form class="wysiwyg"><fieldset><legend>Insert table</legend><label>Count of columns: <input type="text" name="colCount" value="3" /></label><label><br />Count of rows: <input type="text" name="rowCount" value="3" /></label><input type="submit" class="button" value="Insert table" /> <input type="reset" value="Cancel" /></fieldset></form>',
126
+ formImageHtml:'<form class="wysiwyg"><fieldset><legend>Insert Image</legend><label>Image URL: <input type="text" name="url" value="http://" /></label><label>Image Title: <input type="text" name="imagetitle" value="" /></label><label>Image Description: <input type="text" name="description" value="" /></label><input type="submit" class="button" value="Insert Image" /> <input type="reset" value="Cancel" /></fieldset></form>',
127
+ formWidth: 440,
128
+ formHeight: 270,
129
+ tableFiller: 'Lorem ipsum',
130
+ css: { },
131
+ debug: false,
132
+ autoSave: true,
133
+ // http://code.google.com/p/jwysiwyg/issues/detail?id=11
134
+ rmUnwantedBr: true,
135
+ // http://code.google.com/p/jwysiwyg/issues/detail?id=15
136
+ brIE: true,
137
+ iFrameClass: null,
138
+ messages:
139
+ {
140
+ nonSelection: 'select the text you wish to link'
141
+ },
142
+ events: { },
143
+ controls: { },
144
+ resizeOptions: false
145
+ };
146
+
147
+ /**
148
+ * Custom control support by Alec Gorge ( http://github.com/alecgorge )
149
+ */
150
+ // need a global, static namespace
151
+ $.wysiwyg = {
152
+ addControl : function (name, settings) {
153
+ // sample settings
154
+ /*
155
+ var example = {
156
+ icon: '/path/to/icon',
157
+ tooltip: 'my custom item',
158
+ callback: function(selectedText, wysiwygInstance) {
159
+ //Do whatever you want to do in here.
160
+ }
161
+ };
162
+ */
163
+
164
+ var custom = {};
165
+ custom[name] = {visible: false, custom: true, options: settings};
166
+
167
+ $.extend($.fn.wysiwyg.controls, $.fn.wysiwyg.controls, custom);
168
+ }
169
+ };
170
+
171
+ $.fn.wysiwyg.controls = {
172
+ bold: {
173
+ visible: true,
174
+ tags: ['b', 'strong'],
175
+ css: {
176
+ fontWeight: 'bold'
177
+ },
178
+ tooltip: 'Bold'
179
+ },
180
+ italic: {
181
+ visible: true,
182
+ tags: ['i', 'em'],
183
+ css: {
184
+ fontStyle: 'italic'
185
+ },
186
+ tooltip: 'Italic'
187
+ },
188
+ strikeThrough: {
189
+ visible: true,
190
+ tags: ['s', 'strike'],
191
+ css: {
192
+ textDecoration: 'line-through'
193
+ },
194
+ tooltip: 'Strike-through'
195
+ },
196
+ underline: {
197
+ visible: true,
198
+ tags: ['u'],
199
+ css: {
200
+ textDecoration: 'underline'
201
+ },
202
+ tooltip: 'Underline'
203
+ },
204
+ justifyLeft: {
205
+ visible: true,
206
+ groupIndex: 1,
207
+ css: {
208
+ textAlign: 'left'
209
+ },
210
+ tooltip: 'Justify Left'
211
+ },
212
+ justifyCenter: {
213
+ visible: true,
214
+ tags: ['center'],
215
+ css: {
216
+ textAlign: 'center'
217
+ },
218
+ tooltip: 'Justify Center'
219
+ },
220
+ justifyRight: {
221
+ visible: true,
222
+ css: {
223
+ textAlign: 'right'
224
+ },
225
+ tooltip: 'Justify Right'
226
+ },
227
+ justifyFull: {
228
+ visible: true,
229
+ css: {
230
+ textAlign: 'justify'
231
+ },
232
+ tooltip: 'Justify Full'
233
+ },
234
+ indent: {
235
+ groupIndex: 2,
236
+ visible: true,
237
+ tooltip: 'Indent'
238
+ },
239
+ outdent: {
240
+ visible: true,
241
+ tooltip: 'Outdent'
242
+ },
243
+ subscript: {
244
+ groupIndex: 3,
245
+ visible: true,
246
+ tags: ['sub'],
247
+ tooltip: 'Subscript'
248
+ },
249
+ superscript: {
250
+ visible: true,
251
+ tags: ['sup'],
252
+ tooltip: 'Superscript'
253
+ },
254
+ undo: {
255
+ groupIndex: 4,
256
+ visible: true,
257
+ tooltip: 'Undo'
258
+ },
259
+ redo: {
260
+ visible: true,
261
+ tooltip: 'Redo'
262
+ },
263
+ insertOrderedList: {
264
+ groupIndex: 5,
265
+ visible: true,
266
+ tags: ['ol'],
267
+ tooltip: 'Insert Ordered List'
268
+ },
269
+ insertUnorderedList: {
270
+ visible: true,
271
+ tags: ['ul'],
272
+ tooltip: 'Insert Unordered List'
273
+ },
274
+ insertHorizontalRule: {
275
+ visible: true,
276
+ tags: ['hr'],
277
+ tooltip: 'Insert Horizontal Rule'
278
+ },
279
+ createLink: {
280
+ groupIndex: 6,
281
+ visible: true,
282
+ exec: function ()
283
+ {
284
+ var selection = documentSelection.call($(this.editor));
285
+
286
+ if (selection && selection.length > 0)
287
+ {
288
+ if ($.browser.msie)
289
+ {
290
+ this.focus();
291
+ this.editorDoc.execCommand('createLink', true, null);
292
+ }
293
+ else
294
+ {
295
+ var szURL = prompt('URL', 'http://');
296
+ if (szURL && szURL.length > 0)
297
+ {
298
+ this.editorDoc.execCommand('unlink', false, null);
299
+ this.editorDoc.execCommand('createLink', false, szURL);
300
+ }
301
+ }
302
+ }
303
+ else if (this.options.messages.nonSelection)
304
+ {
305
+ alert(this.options.messages.nonSelection);
306
+ }
307
+ },
308
+ tags: ['a'],
309
+ tooltip: 'Create link'
310
+ },
311
+ insertImage: {
312
+ visible: true,
313
+ exec: function ()
314
+ {
315
+ var self = this;
316
+ if ($.modal)
317
+ {
318
+ $.modal($.fn.wysiwyg.defaults.formImageHtml, {
319
+ onShow: function(dialog)
320
+ {
321
+ $('input:submit', dialog.data).click(function(e)
322
+ {
323
+ e.preventDefault();
324
+ var szURL = $('input[name="url"]', dialog.data).val();
325
+ var title = $('input[name="imagetitle"]', dialog.data).val();
326
+ var description = $('input[name="description"]', dialog.data).val();
327
+ var img="<img src='" + szURL + "' title='" + title + "' alt='" + description + "' />";
328
+ self.insertHtml(img);
329
+ $.modal.close();
330
+ });
331
+ $('input:reset', dialog.data).click(function(e)
332
+ {
333
+ e.preventDefault();
334
+ $.modal.close();
335
+ });
336
+ },
337
+ maxWidth: $.fn.wysiwyg.defaults.formWidth,
338
+ maxHeight: $.fn.wysiwyg.defaults.formHeight,
339
+ overlayClose: true
340
+ });
341
+ }
342
+ else
343
+ {
344
+ if ($.fn.dialog){
345
+ var dialog = $($.fn.wysiwyg.defaults.formImageHtml).appendTo('body');
346
+ dialog.dialog({
347
+ modal: true,
348
+ width: $.fn.wysiwyg.defaults.formWidth,
349
+ height: $.fn.wysiwyg.defaults.formHeight,
350
+ open: function(ev, ui)
351
+ {
352
+ $('input:submit', $(this)).click(function(e)
353
+ {
354
+ e.preventDefault();
355
+ var szURL = $('input[name="url"]', dialog).val();
356
+ var title = $('input[name="imagetitle"]', dialog).val();
357
+ var description = $('input[name="description"]', dialog).val();
358
+ var img="<img src='" + szURL + "' title='" + title + "' alt='" + description + "' />";
359
+ self.insertHtml(img);
360
+ $(dialog).dialog("close");
361
+ });
362
+ $('input:reset', $(this)).click(function(e)
363
+ {
364
+ e.preventDefault();
365
+ $(dialog).dialog("close");
366
+ });
367
+ },
368
+ close: function(ev, ui){
369
+ $(this).dialog("destroy");
370
+
371
+ }
372
+ });
373
+ }
374
+ else
375
+ {
376
+ if ($.browser.msie)
377
+ {
378
+ this.focus();
379
+ this.editorDoc.execCommand('insertImage', true, null);
380
+ }
381
+ else
382
+ {
383
+ var szURL = prompt('URL', 'http://');
384
+ if (szURL && szURL.length > 0)
385
+ {
386
+ this.editorDoc.execCommand('insertImage', false, szURL);
387
+ }
388
+ }
389
+ }
390
+
391
+
392
+ }
393
+
394
+ },
395
+ tags: ['img'],
396
+ tooltip: 'Insert image'
397
+ },
398
+ insertTable: {
399
+ visible: true,
400
+ exec: function ()
401
+ {
402
+ var self = this;
403
+ if ($.fn.modal)
404
+ {
405
+ $.modal($.fn.wysiwyg.defaults.formTableHtml, {
406
+ onShow: function(dialog)
407
+ {
408
+ $('input:submit', dialog.data).click(function(e)
409
+ {
410
+ e.preventDefault();
411
+ var rowCount = $('input[name="rowCount"]', dialog.data).val();
412
+ var colCount = $('input[name="colCount"]', dialog.data).val();
413
+ self.insertTable(colCount, rowCount, $.fn.wysiwyg.defaults.tableFiller);
414
+ $.modal.close();
415
+ });
416
+ $('input:reset', dialog.data).click(function(e)
417
+ {
418
+ e.preventDefault();
419
+ $.modal.close();
420
+ });
421
+ },
422
+ maxWidth: $.fn.wysiwyg.defaults.formWidth,
423
+ maxHeight: $.fn.wysiwyg.defaults.formHeight,
424
+ overlayClose: true
425
+ });
426
+ }
427
+ else
428
+ {
429
+ if ($.fn.dialog){
430
+ var dialog = $($.fn.wysiwyg.defaults.formTableHtml).appendTo('body');
431
+ dialog.dialog({
432
+ modal: true,
433
+ width: $.fn.wysiwyg.defaults.formWidth,
434
+ height: $.fn.wysiwyg.defaults.formHeight,
435
+ open: function(event, ui){
436
+ $('input:submit', $(this)).click(function(e)
437
+ {
438
+ e.preventDefault();
439
+ var rowCount = $('input[name="rowCount"]', dialog).val();
440
+ var colCount = $('input[name="colCount"]', dialog).val();
441
+ self.insertTable(colCount, rowCount, $.fn.wysiwyg.defaults.tableFiller);
442
+ $(dialog).dialog("close");
443
+ });
444
+ $('input:reset', $(this)).click(function(e)
445
+ {
446
+ e.preventDefault();
447
+ $(dialog).dialog("close");
448
+ });
449
+ },
450
+ close: function(event, ui){
451
+ $(this).dialog("destroy");
452
+
453
+ }
454
+ });
455
+ }
456
+ else
457
+ {
458
+ var colCount = prompt('Count of columns', '3');
459
+ var rowCount = prompt('Count of rows', '3');
460
+ this.insertTable(colCount, rowCount, $.fn.wysiwyg.defaults.tableFiller);
461
+ }
462
+ }
463
+ },
464
+ tags: ['table'],
465
+ tooltip: 'Insert table'
466
+ },
467
+ h1: {
468
+ visible: true,
469
+ groupIndex: 7,
470
+ className: 'h1',
471
+ command: ($.browser.msie || $.browser.safari) ? 'FormatBlock' : 'heading',
472
+ 'arguments': ($.browser.msie || $.browser.safari) ? '<h1>' : 'h1',
473
+ tags: ['h1'],
474
+ tooltip: 'Header 1'
475
+ },
476
+ h2: {
477
+ visible: true,
478
+ className: 'h2',
479
+ command: ($.browser.msie || $.browser.safari) ? 'FormatBlock' : 'heading',
480
+ 'arguments': ($.browser.msie || $.browser.safari) ? '<h2>' : 'h2',
481
+ tags: ['h2'],
482
+ tooltip: 'Header 2'
483
+ },
484
+ h3: {
485
+ visible: true,
486
+ className: 'h3',
487
+ command: ($.browser.msie || $.browser.safari) ? 'FormatBlock' : 'heading',
488
+ 'arguments': ($.browser.msie || $.browser.safari) ? '<h3>' : 'h3',
489
+ tags: ['h3'],
490
+ tooltip: 'Header 3'
491
+ },
492
+ cut: {
493
+ groupIndex: 8,
494
+ visible: false,
495
+ tooltip: 'Cut'
496
+ },
497
+ copy: {
498
+ visible: false,
499
+ tooltip: 'Copy'
500
+ },
501
+ paste: {
502
+ visible: false,
503
+ tooltip: 'Paste'
504
+ },
505
+ increaseFontSize: {
506
+ groupIndex: 9,
507
+ visible: false && !($.browser.msie),
508
+ tags: ['big'],
509
+ tooltip: 'Increase font size'
510
+ },
511
+ decreaseFontSize: {
512
+ visible: false && !($.browser.msie),
513
+ tags: ['small'],
514
+ tooltip: 'Decrease font size'
515
+ },
516
+ removeFormat: {
517
+ visible: true,
518
+ exec: function ()
519
+ {
520
+ if ($.browser.msie)
521
+ {
522
+ this.focus();
523
+ }
524
+ this.editorDoc.execCommand('formatBlock', false, '<P>'); // remove headings
525
+ this.editorDoc.execCommand('removeFormat', false, null);
526
+ this.editorDoc.execCommand('unlink', false, null);
527
+ },
528
+ tooltip: 'Remove formatting'
529
+ },
530
+ html: {
531
+ groupIndex: 10,
532
+ visible: false,
533
+ exec: function ()
534
+ {
535
+ if (this.viewHTML)
536
+ {
537
+ this.setContent($(this.original).val());
538
+ $(this.original).hide();
539
+ $(this.editor).show();
540
+ }
541
+ else
542
+ {
543
+ var $ed = $(this.editor);
544
+ this.saveContent();
545
+ $(this.original).css({
546
+ width: $(this.element).outerWidth() - 6,
547
+ height: $(this.element).height() - $(this.panel).height() - 6,
548
+ resize: 'none'
549
+ }).show();
550
+ $ed.hide();
551
+ }
552
+
553
+ this.viewHTML = !(this.viewHTML);
554
+ },
555
+ tooltip: 'View source code'
556
+ },
557
+ rtl: {
558
+ visible : false,
559
+ exec : function()
560
+ {
561
+ var selection = $(this.editor).documentSelection();
562
+ if ($("<div />").append(selection).children().length > 0)
563
+ {
564
+ selection = $(selection).attr("dir", "rtl");
565
+ }
566
+ else
567
+ {
568
+ selection = $("<div />").attr("dir", "rtl").append(selection);
569
+ }
570
+ this.editorDoc.execCommand('inserthtml', false, $("<div />").append(selection).html());
571
+ },
572
+ tooltip : "Right to Left"
573
+ },
574
+ ltr: {
575
+ visible : false,
576
+ exec : function()
577
+ {
578
+ var selection = $(this.editor).documentSelection();
579
+ if ($("<div />").append(selection).children().length > 0)
580
+ {
581
+ selection = $(selection).attr("dir", "ltr");
582
+ }
583
+ else
584
+ {
585
+ selection = $("<div />").attr("dir", "ltr").append(selection);
586
+ }
587
+ this.editorDoc.execCommand('inserthtml', false, $("<div />").append(selection).html());
588
+ },
589
+ tooltip : "Left to Right"
590
+ }
591
+ };
592
+
593
+ $.extend(Wysiwyg, {
594
+ insertImage: function (szURL, attributes)
595
+ {
596
+ var self = $.data(this, 'wysiwyg');
597
+ if (self.constructor == Wysiwyg && szURL && szURL.length > 0)
598
+ {
599
+ if ($.browser.msie)
600
+ {
601
+ self.focus();
602
+ }
603
+ if (attributes)
604
+ {
605
+ self.editorDoc.execCommand('insertImage', false, '#jwysiwyg#');
606
+ var img = self.getElementByAttributeValue('img', 'src', '#jwysiwyg#');
607
+
608
+ if (img)
609
+ {
610
+ img.src = szURL;
611
+
612
+ for (var attribute in attributes)
613
+ {
614
+ img.setAttribute(attribute, attributes[attribute]);
615
+ }
616
+ }
617
+ }
618
+ else
619
+ {
620
+ self.editorDoc.execCommand('insertImage', false, szURL);
621
+ }
622
+ }
623
+ return this;
624
+ },
625
+
626
+ createLink: function (szURL)
627
+ {
628
+ var self = $.data(this, 'wysiwyg');
629
+
630
+ if (self.constructor == Wysiwyg && szURL && szURL.length > 0)
631
+ {
632
+ var selection = documentSelection.call($(self.editor));
633
+
634
+ if (selection && selection.length > 0)
635
+ {
636
+ if ($.browser.msie)
637
+ {
638
+ self.focus();
639
+ }
640
+ self.editorDoc.execCommand('unlink', false, null);
641
+ self.editorDoc.execCommand('createLink', false, szURL);
642
+ }
643
+ else if (self.options.messages.nonSelection)
644
+ {
645
+ alert(self.options.messages.nonSelection);
646
+ }
647
+ }
648
+ return this;
649
+ },
650
+
651
+ insertHtml: function (szHTML)
652
+ {
653
+ var self = $.data(this, 'wysiwyg');
654
+ self.insertHtml(szHTML);
655
+ return this;
656
+ },
657
+
658
+ insertTable: function(colCount, rowCount, filler)
659
+ {
660
+ $.data(this, 'wysiwyg').insertTable(colCount, rowCount, filler);
661
+ return this;
662
+ },
663
+
664
+ getContent: function()
665
+ {
666
+ var self = $.data(this, 'wysiwyg');
667
+ return self.getContent();
668
+ },
669
+
670
+ setContent: function (newContent)
671
+ {
672
+ var self = $.data(this, 'wysiwyg');
673
+ self.setContent(newContent);
674
+ self.saveContent();
675
+ return this;
676
+ },
677
+
678
+ clear: function ()
679
+ {
680
+ var self = $.data(this, 'wysiwyg');
681
+ self.setContent('');
682
+ self.saveContent();
683
+ return this;
684
+ },
685
+
686
+ removeFormat: function ()
687
+ {
688
+ var self = $.data(this, 'wysiwyg');
689
+ self.removeFormat();
690
+ return this;
691
+ },
692
+
693
+ save: function ()
694
+ {
695
+ var self = $.data(this, 'wysiwyg');
696
+ self.saveContent();
697
+ return this;
698
+ },
699
+
700
+ "document": function()
701
+ {
702
+ var self = $.data(this, 'wysiwyg');
703
+ return $(self.editorDoc);
704
+ },
705
+
706
+ destroy: function ()
707
+ {
708
+ var self = $.data(this, 'wysiwyg');
709
+ self.destroy();
710
+ return this;
711
+ }
712
+ });
713
+
714
+ var addHoverClass = function()
715
+ {
716
+ $(this).addClass('wysiwyg-button-hover');
717
+ };
718
+ var removeHoverClass = function()
719
+ {
720
+ $(this).removeClass('wysiwyg-button-hover');
721
+ };
722
+
723
+ $.extend(Wysiwyg.prototype, {
724
+ original: null,
725
+ options: {
726
+ },
727
+
728
+ element: null,
729
+ rangeSaver: null,
730
+ editor: null,
731
+
732
+ removeFormat: function ()
733
+ {
734
+ if ($.browser.msie)
735
+ {
736
+ this.focus();
737
+ }
738
+ this.editorDoc.execCommand('removeFormat', false, null);
739
+ this.editorDoc.execCommand('unlink', false, null);
740
+ return this;
741
+ },
742
+ destroy: function ()
743
+ {
744
+ // Remove bindings
745
+ var $form = $(this.element).closest('form');
746
+ $form.unbind('submit', this.autoSaveFunction)
747
+ .unbind('reset', this.resetFunction);
748
+ $(this.element).remove();
749
+ $.removeData(this.original, 'wysiwyg');
750
+ $(this.original).show();
751
+ return this;
752
+ },
753
+ focus: function ()
754
+ {
755
+ this.editor.get(0).contentWindow.focus();
756
+ return this;
757
+ },
758
+
759
+ init: function (element, options)
760
+ {
761
+ var self = this;
762
+
763
+ this.editor = element;
764
+ this.options = options || {
765
+ };
766
+
767
+ $.data(element, 'wysiwyg', this);
768
+
769
+ var newX = element.width || element.clientWidth || 0;
770
+ var newY = element.height || element.clientHeight || 0;
771
+
772
+ if (element.nodeName.toLowerCase() == 'textarea')
773
+ {
774
+ this.original = element;
775
+
776
+ if (newX === 0 && element.cols)
777
+ {
778
+ newX = (element.cols * 8) + 21;
779
+
780
+ // fix for issue 30 ( http://github.com/akzhan/jwysiwyg/issues/issue/30 )
781
+ element.cols = 1;
782
+ }
783
+ if (newY === 0 && element.rows)
784
+ {
785
+ newY = (element.rows * 16) + 16;
786
+
787
+ // fix for issue 30 ( http://github.com/akzhan/jwysiwyg/issues/issue/30 )
788
+ element.rows = 1;
789
+ }
790
+ this.editor = $(location.protocol == 'https:' ? '<iframe src="javascript:false;"></iframe>' : '<iframe></iframe>').attr('frameborder', '0');
791
+ if (options.iFrameClass)
792
+ {
793
+ this.editor.addClass(options.iFrameClass);
794
+ }
795
+ else
796
+ {
797
+ this.editor.css({
798
+ minHeight: (newY - 6).toString() + 'px',
799
+
800
+ // fix for issue 12 ( http://github.com/akzhan/jwysiwyg/issues/issue/12 )
801
+ width: (newX > 50) ? (newX - 8).toString() + 'px' : ''
802
+ });
803
+ if ($.browser.msie)
804
+ {
805
+ this.editor.css('height', newY.toString() + 'px');
806
+ }
807
+ }
808
+
809
+ /**
810
+ * http://code.google.com/p/jwysiwyg/issues/detail?id=96
811
+ */
812
+ this.editor.attr('tabindex', $(element).attr('tabindex'));
813
+ }
814
+
815
+ var panel = this.panel = $('<ul role="menu" class="panel"></ul>');
816
+
817
+ this.appendControls();
818
+ this.element = $('<div></div>').addClass('wysiwyg').append(panel).append($('<div><!-- --></div>').css({
819
+ clear: 'both'
820
+ })).append(this.editor);
821
+
822
+ if (!options.iFrameClass)
823
+ {
824
+ this.element.css({
825
+ width: (newX > 0) ? newX.toString() + 'px' : '100%'
826
+ });
827
+ }
828
+
829
+ $(element).hide().before(this.element);
830
+
831
+ this.viewHTML = false;
832
+ this.initialHeight = newY - 8;
833
+
834
+ /**
835
+ * @link http://code.google.com/p/jwysiwyg/issues/detail?id=52
836
+ */
837
+ this.initialContent = $(element).val();
838
+ this.initFrame();
839
+
840
+ this.autoSaveFunction = function ()
841
+ {
842
+ self.saveContent();
843
+ };
844
+
845
+ this.resetFunction = function()
846
+ {
847
+ self.setContent(self.initialContent);
848
+ self.saveContent();
849
+ }
850
+
851
+ if(this.options.resizeOptions && $.fn.resizable)
852
+ {
853
+ this.element.resizable($.extend(true, {
854
+ alsoResize: this.editor
855
+ }, this.options.resizeOptions));
856
+ }
857
+
858
+ var $form = $(element).closest('form');
859
+
860
+ if (this.options.autoSave)
861
+ {
862
+ $form.submit(self.autoSaveFunction);
863
+ }
864
+
865
+ $form.bind('reset', self.resetFunction);
866
+ },
867
+
868
+ initFrame: function ()
869
+ {
870
+ var self = this;
871
+ var style = '';
872
+
873
+ /**
874
+ * @link http://code.google.com/p/jwysiwyg/issues/detail?id=14
875
+ */
876
+ if (this.options.css && this.options.css.constructor == String)
877
+ {
878
+ style = '<link rel="stylesheet" type="text/css" media="screen" href="' + this.options.css + '" />';
879
+ }
880
+
881
+ this.editorDoc = innerDocument(this.editor);
882
+ this.editorDoc_designMode = false;
883
+
884
+ this.designMode();
885
+
886
+ this.editorDoc.open();
887
+ this.editorDoc.write(
888
+ this.options.html
889
+ /**
890
+ * @link http://code.google.com/p/jwysiwyg/issues/detail?id=144
891
+ */
892
+ .replace(/INITIAL_CONTENT/, function ()
893
+ {
894
+ return self.initialContent;
895
+ }).replace(/STYLE_SHEET/, function ()
896
+ {
897
+ return style;
898
+ }));
899
+ this.editorDoc.close();
900
+
901
+ if ($.browser.msie)
902
+ {
903
+ /**
904
+ * Remove the horrible border it has on IE.
905
+ */
906
+ window.setTimeout(function ()
907
+ {
908
+ $(self.editorDoc.body).css('border', 'none');
909
+ }, 0);
910
+ }
911
+
912
+ $(this.editorDoc).click(function (event)
913
+ {
914
+ self.checkTargets(event.target ? event.target : event.srcElement);
915
+ });
916
+
917
+ /**
918
+ * @link http://code.google.com/p/jwysiwyg/issues/detail?id=20
919
+ */
920
+ $(this.original).focus(function ()
921
+ {
922
+ if ($(this).filter(':visible'))
923
+ {
924
+ return;
925
+ }
926
+ self.focus();
927
+ });
928
+
929
+ if (!$.browser.msie)
930
+ {
931
+ $(this.editorDoc).keydown(function (event)
932
+ {
933
+ if (event.ctrlKey)
934
+ {
935
+ switch (event.keyCode)
936
+ {
937
+ case 66:
938
+ // Ctrl + B
939
+ this.execCommand('Bold', false, false);
940
+ return false;
941
+ case 73:
942
+ // Ctrl + I
943
+ this.execCommand('Italic', false, false);
944
+ return false;
945
+ case 85:
946
+ // Ctrl + U
947
+ this.execCommand('Underline', false, false);
948
+ return false;
949
+ }
950
+ }
951
+ return true;
952
+ });
953
+ }
954
+ else if (this.options.brIE)
955
+ {
956
+ $(this.editorDoc).keydown(function (event)
957
+ {
958
+ if (event.keyCode == 13)
959
+ {
960
+ var rng = self.getRange();
961
+ rng.pasteHTML('<br />');
962
+ rng.collapse(false);
963
+ rng.select();
964
+ return false;
965
+ }
966
+ return true;
967
+ });
968
+ }
969
+
970
+ if (this.options.autoSave)
971
+ {
972
+ /**
973
+ * @link http://code.google.com/p/jwysiwyg/issues/detail?id=11
974
+ */
975
+ var handler = function () {
976
+ self.saveContent();
977
+ };
978
+ $(this.editorDoc).keydown(handler).keyup(handler).mousedown(handler).bind($.support.noCloneEvent ? "input" : "paste", handler);
979
+
980
+ }
981
+
982
+ if (this.options.css)
983
+ {
984
+ window.setTimeout(function ()
985
+ {
986
+ if (self.options.css.constructor == String)
987
+ {
988
+ /**
989
+ * $(self.editorDoc)
990
+ * .find('head')
991
+ * .append(
992
+ * $('<link rel="stylesheet" type="text/css" media="screen" />')
993
+ * .attr('href', self.options.css)
994
+ * );
995
+ */
996
+ }
997
+ else
998
+ {
999
+ $(self.editorDoc).find('body').css(self.options.css);
1000
+ }
1001
+ }, 0);
1002
+ }
1003
+
1004
+ if (this.initialContent.length === 0)
1005
+ {
1006
+ this.setContent('<p>initial content</p>');
1007
+ }
1008
+
1009
+ $.each(this.options.events, function(key, handler)
1010
+ {
1011
+ $(self.editorDoc).bind(key, handler);
1012
+ });
1013
+
1014
+ // restores selection properly on focus
1015
+ $(self.editor).blur(function() {
1016
+ self.rangeSaver = self.getInternalRange();
1017
+ });
1018
+
1019
+ $(this.editorDoc.body).addClass('wysiwyg');
1020
+ if(this.options.events && this.options.events.save) {
1021
+ var handler = this.options.events.save;
1022
+ $(self.editorDoc).bind('keyup', handler);
1023
+ $(self.editorDoc).bind('change', handler);
1024
+ if($.support.noCloneEvent) {
1025
+ $(self.editorDoc).bind("input", handler);
1026
+ } else {
1027
+ $(self.editorDoc).bind("paste", handler);
1028
+ $(self.editorDoc).bind("cut", handler);
1029
+ }
1030
+ }
1031
+ },
1032
+
1033
+ focusEditor: function () {
1034
+ //console.log(this.editorDoc.body.focus());//.focus();
1035
+ if (this.rangeSaver != null) {
1036
+ if (window.getSelection) { //non IE and there is already a selection
1037
+ var s = window.getSelection();
1038
+ if (s.rangeCount > 0) s.removeAllRanges();
1039
+ s.addRange(savedRange);
1040
+ }
1041
+ else if (document.createRange) { //non IE and no selection
1042
+ window.getSelection().addRange(savedRange);
1043
+ }
1044
+ else if (document.selection) { //IE
1045
+ savedRange.select();
1046
+ }
1047
+ }
1048
+ },
1049
+
1050
+ execute: function (command, arg) {
1051
+ if(typeof(arg) == "undefined") arg = null;
1052
+ this.editorDoc.execCommand(command, false, arg);
1053
+ },
1054
+
1055
+ designMode: function ()
1056
+ {
1057
+ var attempts = 3;
1058
+ var runner;
1059
+ var self = this;
1060
+ var doc = this.editorDoc;
1061
+ runner = function()
1062
+ {
1063
+ if (innerDocument(self.editor) !== doc)
1064
+ {
1065
+ self.initFrame();
1066
+ return;
1067
+ }
1068
+ try
1069
+ {
1070
+ doc.designMode = 'on';
1071
+ }
1072
+ catch (e)
1073
+ {
1074
+ }
1075
+ attempts--;
1076
+ if (attempts > 0 && $.browser.mozilla)
1077
+ {
1078
+ setTimeout(runner, 100);
1079
+ }
1080
+ };
1081
+ runner();
1082
+ this.editorDoc_designMode = true;
1083
+ },
1084
+
1085
+ getSelection: function ()
1086
+ {
1087
+ return (window.getSelection) ? window.getSelection() : document.selection;
1088
+ },
1089
+
1090
+
1091
+ getInternalSelection: function ()
1092
+ {
1093
+ return (this.editor[0].contentWindow.getSelection) ? this.editor[0].contentWindow.getSelection() : this.editor[0].contentDocument.selection;
1094
+ },
1095
+
1096
+ getRange: function ()
1097
+ {
1098
+ var selection = this.getSelection();
1099
+
1100
+ if (!selection)
1101
+ {
1102
+ return null;
1103
+ }
1104
+
1105
+ return (selection.rangeCount > 0) ? selection.getRangeAt(0) : (selection.createRange ? selection.createRange() : null);
1106
+ },
1107
+
1108
+ getInternalRange: function ()
1109
+ {
1110
+ var selection = this.getInternalSelection();
1111
+
1112
+ if (!selection)
1113
+ {
1114
+ return null;
1115
+ }
1116
+
1117
+ return (selection.rangeCount > 0) ? selection.getRangeAt(0) : (selection.createRange ? selection.createRange() : null);
1118
+ },
1119
+
1120
+ getContent: function ()
1121
+ {
1122
+ return $(innerDocument(this.editor)).find('body').html();
1123
+ },
1124
+
1125
+ setContent: function (newContent)
1126
+ {
1127
+ $(innerDocument(this.editor)).find('body').html(newContent);
1128
+ return this;
1129
+ },
1130
+ insertHtml: function (szHTML)
1131
+ {
1132
+ if (szHTML && szHTML.length > 0)
1133
+ {
1134
+ if ($.browser.msie)
1135
+ {
1136
+ this.focus();
1137
+ this.editorDoc.execCommand('insertImage', false, '#jwysiwyg#');
1138
+ var img = this.getElementByAttributeValue('img', 'src', '#jwysiwyg#');
1139
+ if (img)
1140
+ {
1141
+ $(img).replaceWith(szHTML);
1142
+ }
1143
+ }
1144
+ else
1145
+ {
1146
+ this.editorDoc.execCommand('insertHTML', false, szHTML);
1147
+ }
1148
+ }
1149
+ return this;
1150
+ },
1151
+ insertTable: function(colCount, rowCount, filler)
1152
+ {
1153
+ if (isNaN(rowCount) || isNaN(colCount) || rowCount === null || colCount === null)
1154
+ {
1155
+ return;
1156
+ }
1157
+ colCount = parseInt(colCount, 10);
1158
+ rowCount = parseInt(rowCount, 10);
1159
+ if (filler === null)
1160
+ {
1161
+ filler = '&nbsp;';
1162
+ }
1163
+ filler = '<td>' + filler + '</td>';
1164
+ var html = ['<table border="1" style="width: 100%;"><tbody>'];
1165
+ for (var i = rowCount; i > 0; i--)
1166
+ {
1167
+ html.push('<tr>');
1168
+ for (var j = colCount; j > 0; j--)
1169
+ {
1170
+ html.push(filler);
1171
+ }
1172
+ html.push('</tr>');
1173
+ }
1174
+ html.push('</tbody></table>');
1175
+ return this.insertHtml(html.join(''));
1176
+ },
1177
+ saveContent: function ()
1178
+ {
1179
+ if (this.original)
1180
+ {
1181
+ var content = this.getContent();
1182
+
1183
+ if (this.options.rmUnwantedBr)
1184
+ {
1185
+ content = (content.substr(-4) == '<br>') ? content.substr(0, content.length - 4) : content;
1186
+ }
1187
+
1188
+ $(this.original).val(content);
1189
+ if(this.options.events && this.options.events.save) {
1190
+ this.options.events.save.call(this);
1191
+ }
1192
+ }
1193
+ return this;
1194
+ },
1195
+
1196
+ withoutCss: function ()
1197
+ {
1198
+ if ($.browser.mozilla)
1199
+ {
1200
+ try
1201
+ {
1202
+ this.editorDoc.execCommand('styleWithCSS', false, false);
1203
+ }
1204
+ catch (e)
1205
+ {
1206
+ try
1207
+ {
1208
+ this.editorDoc.execCommand('useCSS', false, true);
1209
+ }
1210
+ catch (e2)
1211
+ {
1212
+ }
1213
+ }
1214
+ }
1215
+ return this;
1216
+ },
1217
+
1218
+ appendMenuCustom: function (name, options)
1219
+ {
1220
+ var self = this;
1221
+
1222
+ $(window).bind("wysiwyg-trigger-"+name, options.callback);
1223
+
1224
+ return $('<li role="menuitem" UNSELECTABLE="on"><img src="' + options.icon + '" class="jwysiwyg-custom-icon" />' + (name) + '</li>')
1225
+ .addClass("custom-command-"+name)
1226
+ .addClass("jwysiwyg-custom-command")
1227
+ .addClass(name)
1228
+ .attr('title', options.tooltip)
1229
+ .hover(addHoverClass, removeHoverClass)
1230
+ .click(function () {
1231
+ self.triggerCallback(name);
1232
+ })
1233
+ .appendTo(this.panel);
1234
+ },
1235
+
1236
+ triggerCallback : function (name) {
1237
+ $(window).trigger("wysiwyg-trigger-"+name, [
1238
+ this.getInternalRange(),
1239
+ this,
1240
+ this.getInternalSelection()
1241
+ ]);
1242
+ $(".custom-command-"+name, this.panel).blur();
1243
+ this.focusEditor();
1244
+ },
1245
+
1246
+ appendMenu: function (cmd, args, className, fn, tooltip)
1247
+ {
1248
+ var self = this;
1249
+ args = args || [];
1250
+
1251
+ return $('<li role="menuitem" UNSELECTABLE="on">' + (className || cmd) + '</li>').addClass(className || cmd).attr('title', tooltip).hover(addHoverClass, removeHoverClass).click(function ()
1252
+ {
1253
+ if (fn)
1254
+ {
1255
+ fn.apply(self);
1256
+ }
1257
+ else
1258
+ {
1259
+ self.focus();
1260
+ self.withoutCss();
1261
+ self.editorDoc.execCommand(cmd, false, args);
1262
+ }
1263
+ if (self.options.autoSave)
1264
+ {
1265
+ self.saveContent();
1266
+ }
1267
+ this.blur();
1268
+ self.focusEditor();
1269
+ }).appendTo(this.panel);
1270
+ },
1271
+
1272
+ appendMenuSeparator: function ()
1273
+ {
1274
+ return $('<li role="separator" class="separator"></li>').appendTo(this.panel);
1275
+ },
1276
+ parseControls: function() {
1277
+ if(this.options.parseControls) {
1278
+ return this.options.parseControls.call(this);
1279
+ }
1280
+ return this.options.controls;
1281
+ },
1282
+ appendControls: function ()
1283
+ {
1284
+ var controls = this.parseControls();
1285
+ var currentGroupIndex = 0;
1286
+ var hasVisibleControls = true; // to prevent separator before first item
1287
+ for (var name in controls)
1288
+ {
1289
+ var control = controls[name];
1290
+ if (control.groupIndex && currentGroupIndex != control.groupIndex)
1291
+ {
1292
+ currentGroupIndex = control.groupIndex;
1293
+ hasVisibleControls = false;
1294
+ }
1295
+ if (!control.visible)
1296
+ {
1297
+ continue;
1298
+ }
1299
+ if (!hasVisibleControls)
1300
+ {
1301
+ this.appendMenuSeparator();
1302
+ hasVisibleControls = true;
1303
+ }
1304
+
1305
+ if(control.custom) {
1306
+ this.appendMenuCustom(name, control.options);
1307
+ }
1308
+ else {
1309
+ this.appendMenu(
1310
+ control.command || name,
1311
+ control['arguments'] || '',
1312
+ control.className || control.command || name || 'empty',
1313
+ control.exec,
1314
+ control.tooltip || control.command || name || ''
1315
+ );
1316
+ }
1317
+ }
1318
+ },
1319
+
1320
+ checkTargets: function (element)
1321
+ {
1322
+ for (var name in this.options.controls)
1323
+ {
1324
+ var control = this.options.controls[name];
1325
+ var className = control.className || control.command || name || 'empty';
1326
+
1327
+ $('.' + className, this.panel).removeClass('active');
1328
+
1329
+ if (control.tags || (control.options && control.options.tags))
1330
+ {
1331
+ var tags = control.tags || (control.options && control.options.tags);
1332
+ var elm = element;
1333
+ do
1334
+ {
1335
+ if (elm.nodeType != 1)
1336
+ {
1337
+ break;
1338
+ }
1339
+
1340
+ if ($.inArray(elm.tagName.toLowerCase(), tags) != -1)
1341
+ {
1342
+ $('.' + className, this.panel).addClass('active');
1343
+ }
1344
+ } while ((elm = elm.parentNode));
1345
+ }
1346
+
1347
+ if (control.css || (control.options && control.options.css))
1348
+ {
1349
+ var css = control.css || (control.options && control.options.css);
1350
+ var el = $(element);
1351
+
1352
+ do
1353
+ {
1354
+ if (el[0].nodeType != 1)
1355
+ {
1356
+ break;
1357
+ }
1358
+
1359
+ for (var cssProperty in css)
1360
+ {
1361
+ if (el.css(cssProperty).toString().toLowerCase() == css[cssProperty])
1362
+ {
1363
+ $('.' + className, this.panel).addClass('active');
1364
+ }
1365
+ }
1366
+ } while ((el = el.parent()));
1367
+ }
1368
+ }
1369
+ },
1370
+
1371
+ getElementByAttributeValue: function (tagName, attributeName, attributeValue)
1372
+ {
1373
+ var elements = this.editorDoc.getElementsByTagName(tagName);
1374
+
1375
+ for (var i = 0; i < elements.length; i++)
1376
+ {
1377
+ var value = elements[i].getAttribute(attributeName);
1378
+
1379
+ if ($.browser.msie)
1380
+ { /** IE add full path, so I check by the last chars. */
1381
+ value = value.substr(value.length - attributeValue.length);
1382
+ }
1383
+
1384
+ if (value == attributeValue)
1385
+ {
1386
+ return elements[i];
1387
+ }
1388
+ }
1389
+
1390
+ return false;
1391
+ }
1392
+ });
1393
+ })(jQuery);