2
* WYSIWYG - jQuery plugin 0.5
4
* Copyright (c) 2008-2009 Juan M Martinez
5
* http://plugins.jquery.com/project/jWYSIWYG
7
* Dual licensed under the MIT and GPL licenses:
8
* http://www.opensource.org/licenses/mit-license.php
9
* http://www.gnu.org/licenses/gpl.html
15
$.fn.document = function()
17
var element = this[0];
19
if ( element.nodeName.toLowerCase() == 'iframe' )
20
return element.contentWindow.document;
22
return ( $.browser.msie )
23
? document.frames[element.id].document
24
: element.contentWindow.document // contentDocument;
30
$.fn.documentSelection = function()
32
var element = this[0];
34
if ( element.contentWindow.document.selection )
35
return element.contentWindow.document.selection.createRange().text;
37
return element.contentWindow.getSelection().toString();
40
$.fn.wysiwyg = function( options )
42
if ( arguments.length > 0 && arguments[0].constructor == String )
44
var action = arguments[0].toString();
47
for ( var i = 1; i < arguments.length; i++ )
48
params[i - 1] = arguments[i];
50
if ( action in Wysiwyg )
52
return this.each(function()
54
$.data(this, 'wysiwyg')
57
Wysiwyg[action].apply(this, params);
66
* If the user set custom controls, we catch it, and merge with the
67
* defaults controls later.
69
if ( options && options.controls )
71
var controls = options.controls;
72
delete options.controls;
75
var options = $.extend({
76
html : '<'+'?xml version="1.0" encoding="UTF-8"?'+'><!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="font-family: Arial, Helvetica, sans-serif !important; font-size: 13px; height: 100%; line-height: 1.5em !important;">INITIAL_CONTENT</body></html>',
81
autoSave : true, // http://code.google.com/p/jwysiwyg/issues/detail?id=11
82
rmUnwantedBr : true, // http://code.google.com/p/jwysiwyg/issues/detail?id=15
89
options.messages = $.extend(true, options.messages, Wysiwyg.MSGS_EN);
90
options.controls = $.extend(true, options.controls, Wysiwyg.TOOLBAR);
92
for ( var control in controls )
94
if ( control in options.controls )
95
$.extend(options.controls[control], controls[control]);
97
options.controls[control] = controls[control];
100
// not break the chain
101
return this.each(function()
103
Wysiwyg(this, options);
107
function Wysiwyg( element, options )
109
return this instanceof Wysiwyg
110
? this.init(element, options)
111
: new Wysiwyg(element, options);
115
insertImage : function( szURL, attributes )
117
var self = $.data(this, 'wysiwyg');
119
if ( self.constructor == Wysiwyg && szURL && szURL.length > 0 )
123
self.editorDoc.execCommand('insertImage', false, '#jwysiwyg#');
124
var img = self.getElementByAttributeValue('img', 'src', '#jwysiwyg#');
130
for ( var attribute in attributes )
132
img.setAttribute(attribute, attributes[attribute]);
138
self.editorDoc.execCommand('insertImage', false, szURL);
143
createLink : function( szURL )
145
var self = $.data(this, 'wysiwyg');
147
if ( self.constructor == Wysiwyg && szURL && szURL.length > 0 )
149
var selection = $(self.editor).documentSelection();
151
if ( selection.length > 0 )
153
self.editorDoc.execCommand('unlink', false, []);
154
self.editorDoc.execCommand('createLink', false, szURL);
156
else if ( self.options.messages.nonSelection )
157
alert(self.options.messages.nonSelection);
161
setContent : function( newContent )
163
var self = $.data(this, 'wysiwyg');
164
self.setContent( newContent );
170
var self = $.data(this, 'wysiwyg');
176
nonSelection : 'select the text you wish to link'
180
bold : { visible : true, tags : ['b', 'strong'], css : { fontWeight : 'bold' } },
181
italic : { visible : true, tags : ['i', 'em'], css : { fontStyle : 'italic' } },
182
strikeThrough : { visible : false, tags : ['s', 'strike'], css : { textDecoration : 'line-through' } },
183
underline : { visible : false, tags : ['u'], css : { textDecoration : 'underline' } },
185
separator00 : { visible : false, separator : true },
187
justifyLeft : { visible : false, css : { textAlign : 'left' } },
188
justifyCenter : { visible : false, tags : ['center'], css : { textAlign : 'center' } },
189
justifyRight : { visible : false, css : { textAlign : 'right' } },
190
justifyFull : { visible : false, css : { textAlign : 'justify' } },
192
separator01 : { visible : false, separator : true },
194
indent : { visible : false },
195
outdent : { visible : false },
197
separator02 : { visible : false, separator : true },
199
subscript : { visible : false, tags : ['sub'] },
200
superscript : { visible : false, tags : ['sup'] },
202
separator03 : { visible : false, separator : true },
204
undo : { visible : false },
205
redo : { visible : false },
207
separator04 : { visible : false, separator : true },
209
insertOrderedList : { visible : false, tags : ['ol'] },
210
insertUnorderedList : { visible : false, tags : ['ul'] },
211
insertHorizontalRule : { visible : false, tags : ['hr'] },
213
separator05 : { separator : true },
219
var selection = $(this.editor).documentSelection();
221
if ( selection.length > 0 )
223
if ( $.browser.msie )
224
this.editorDoc.execCommand('createLink', true, null);
227
var szURL = prompt('URL', 'http://');
229
if ( szURL && szURL.length > 0 )
231
this.editorDoc.execCommand('unlink', false, []);
232
this.editorDoc.execCommand('createLink', false, szURL);
236
else if ( this.options.messages.nonSelection )
237
alert(this.options.messages.nonSelection);
247
if ( $.browser.msie )
248
this.editorDoc.execCommand('insertImage', true, null);
251
var szURL = prompt('URL', 'http://');
253
if ( szURL && szURL.length > 0 )
254
this.editorDoc.execCommand('insertImage', false, szURL);
261
separator06 : { separator : true },
263
h1mozilla : { visible : true && $.browser.mozilla, className : 'h1', command : 'heading', arguments : ['h1'], tags : ['h1'] },
264
h2mozilla : { visible : true && $.browser.mozilla, className : 'h2', command : 'heading', arguments : ['h2'], tags : ['h2'] },
265
h3mozilla : { visible : true && $.browser.mozilla, className : 'h3', command : 'heading', arguments : ['h3'], tags : ['h3'] },
267
h1 : { visible : true && !( $.browser.mozilla ), className : 'h1', command : 'formatBlock', arguments : ['Heading 1'], tags : ['h1'] },
268
h2 : { visible : true && !( $.browser.mozilla ), className : 'h2', command : 'formatBlock', arguments : ['Heading 2'], tags : ['h2'] },
269
h3 : { visible : true && !( $.browser.mozilla ), className : 'h3', command : 'formatBlock', arguments : ['Heading 3'], tags : ['h3'] },
271
separator07 : { visible : false, separator : true },
273
cut : { visible : false },
274
copy : { visible : false },
275
paste : { visible : false },
277
separator08 : { separator : true && !( $.browser.msie ) },
279
increaseFontSize : { visible : true && !( $.browser.msie ), tags : ['big'] },
280
decreaseFontSize : { visible : true && !( $.browser.msie ), tags : ['small'] },
282
separator09 : { separator : true },
290
this.setContent( $(this.original).val() );
291
$(this.original).hide();
296
$(this.original).show();
299
this.viewHTML = !( this.viewHTML );
307
this.editorDoc.execCommand('removeFormat', false, []);
308
this.editorDoc.execCommand('unlink', false, []);
314
$.extend(Wysiwyg.prototype,
322
init : function( element, options )
326
this.editor = element;
327
this.options = options || {};
329
$.data(element, 'wysiwyg', this);
331
var newX = element.width || element.clientWidth;
332
var newY = element.height || element.clientHeight;
334
if ( element.nodeName.toLowerCase() == 'textarea' )
336
this.original = element;
338
if ( newX == 0 && element.cols )
339
newX = ( element.cols * 8 ) + 21;
341
if ( newY == 0 && element.rows )
342
newY = ( element.rows * 16 ) + 16;
344
var editor = this.editor = $('<iframe></iframe>').css({
345
minHeight : ( newY - 6 ).toString() + 'px',
346
width : ( newX - 8 ).toString() + 'px'
347
}).attr('id', $(element).attr('id') + 'IFrame');
349
if ( $.browser.msie )
352
.css('height', ( newY ).toString() + 'px');
355
var editor = $('<span></span>').css({
356
width : ( newX - 6 ).toString() + 'px',
357
height : ( newY - 8 ).toString() + 'px'
358
}).attr('id', $(element).attr('id') + 'IFrame');
360
editor.outerHTML = this.editor.outerHTML;
365
var panel = this.panel = $('<ul></ul>').addClass('panel');
367
this.appendControls();
368
this.element = $('<div></div>').css({
369
width : ( newX > 0 ) ? ( newX ).toString() + 'px' : '100%'
370
}).addClass('wysiwyg')
372
.append( $('<div><!-- --></div>').css({ clear : 'both' }) )
376
// .css('display', 'none')
378
.before(this.element);
380
this.viewHTML = false;
382
this.initialHeight = newY - 8;
385
* @link http://code.google.com/p/jwysiwyg/issues/detail?id=52
387
this.initialContent = $(element).val();
391
if ( this.initialContent.length == 0 )
394
if ( this.options.autoSave )
395
$('form').submit(function() { self.saveContent(); });
397
$('form').bind('reset', function()
399
self.setContent( self.initialContent );
404
initFrame : function()
410
* @link http://code.google.com/p/jwysiwyg/issues/detail?id=14
412
if ( this.options.css && this.options.css.constructor == String )
413
style = '<link rel="stylesheet" type="text/css" media="screen" href="' + this.options.css + '" />';
415
this.editorDoc = $(this.editor).document();
416
this.editorDoc_designMode = false;
419
this.editorDoc.designMode = 'on';
420
this.editorDoc_designMode = true;
422
// Will fail on Gecko if the editor is placed in an hidden container element
423
// The design mode will be set ones the editor is focused
425
$(this.editorDoc).focus(function()
431
this.editorDoc.open();
432
this.editorDoc.write(
434
.replace(/INITIAL_CONTENT/, this.initialContent)
435
.replace(/STYLE_SHEET/, style)
437
this.editorDoc.close();
438
this.editorDoc.contentEditable = 'true';
440
if ( $.browser.msie )
443
* Remove the horrible border it has on IE.
445
setTimeout(function() { $(self.editorDoc.body).css('border', 'none'); }, 0);
448
$(this.editorDoc).click(function( event )
450
self.checkTargets( event.target ? event.target : event.srcElement);
454
* @link http://code.google.com/p/jwysiwyg/issues/detail?id=20
456
$(this.original).focus(function()
458
$(self.editorDoc.body).focus();
461
if ( this.options.autoSave )
464
* @link http://code.google.com/p/jwysiwyg/issues/detail?id=11
466
$(this.editorDoc).keydown(function() { self.saveContent(); })
467
.keyup(function() { self.saveContent(); })
468
.mousedown(function() { self.saveContent(); });
471
if ( this.options.css )
473
setTimeout(function()
475
if ( self.options.css.constructor == String )
481
* $('<link rel="stylesheet" type="text/css" media="screen" />')
482
* .attr('href', self.options.css)
487
$(self.editorDoc).find('body').css(self.options.css);
491
$(this.editorDoc).keydown(function( event )
493
if ( $.browser.msie && self.options.brIE && event.keyCode == 13 )
495
var rng = self.getRange();
496
rng.pasteHTML('<br />');
505
designMode : function()
507
if ( !( this.editorDoc_designMode ) )
510
this.editorDoc.designMode = 'on';
511
this.editorDoc_designMode = true;
516
getSelection : function()
518
return ( window.getSelection ) ? window.getSelection() : document.selection;
521
getRange : function()
523
var selection = this.getSelection();
525
if ( !( selection ) )
528
return ( selection.rangeCount > 0 ) ? selection.getRangeAt(0) : selection.createRange();
531
getContent : function()
533
return $( $(this.editor).document() ).find('body').html();
536
setContent : function( newContent )
538
$( $(this.editor).document() ).find('body').html(newContent);
541
saveContent : function()
545
var content = this.getContent();
547
if ( this.options.rmUnwantedBr )
548
content = ( content.substr(-4) == '<br>' ) ? content.substr(0, content.length - 4) : content;
550
$(this.original).val(content);
554
appendMenu : function( cmd, args, className, fn )
557
var args = args || [];
559
$('<li></li>').append(
560
$('<a><!-- --></a>').addClass(className || cmd)
561
).mousedown(function() {
562
if ( fn ) fn.apply(self); else self.editorDoc.execCommand(cmd, false, args);
563
if ( self.options.autoSave ) self.saveContent();
564
}).appendTo( this.panel );
567
appendMenuSeparator : function()
569
$('<li class="separator"></li>').appendTo( this.panel );
572
appendControls : function()
574
for ( var name in this.options.controls )
576
var control = this.options.controls[name];
578
if ( control.separator )
580
if ( control.visible !== false )
581
this.appendMenuSeparator();
583
else if ( control.visible )
586
control.command || name, control.arguments || [],
587
control.className || control.command || name || 'empty', control.exec
593
checkTargets : function( element )
595
for ( var name in this.options.controls )
597
var control = this.options.controls[name];
598
var className = control.className || control.command || name || 'empty';
600
$('.' + className, this.panel).removeClass('active');
607
if ( elm.nodeType != 1 )
610
if ( $.inArray(elm.tagName.toLowerCase(), control.tags) != -1 )
611
$('.' + className, this.panel).addClass('active');
612
} while ( elm = elm.parentNode );
617
var elm = $(element);
620
if ( elm[0].nodeType != 1 )
623
for ( var cssProperty in control.css )
624
if ( elm.css(cssProperty).toString().toLowerCase() == control.css[cssProperty] )
625
$('.' + className, this.panel).addClass('active');
626
} while ( elm = elm.parent() );
631
getElementByAttributeValue : function( tagName, attributeName, attributeValue )
633
var elements = this.editorDoc.getElementsByTagName(tagName);
635
for ( var i = 0; i < elements.length; i++ )
637
var value = elements[i].getAttribute(attributeName);
639
if ( $.browser.msie )
641
/** IE add full path, so I check by the last chars. */
642
value = value.substr(value.length - attributeValue.length);
645
if ( value == attributeValue )
b'\\ No newline at end of file'