comfortable_mexican_sofa 1.0.24 → 1.0.25

Sign up to get free protection for your applications and to get access to all the features.
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);