cleditor_rails 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "rails", "3.1.0.rc4"
4
+ gem "capybara", "~> 1.0.0"
5
+ gem "sqlite3"
6
+
7
+ # Asset template engines
8
+ gem 'sprockets', '2.0.0.beta.10'
9
+ gem 'sass'
10
+ gem 'coffee-script'
11
+ gem 'uglifier'
12
+ gem 'nokogiri'
13
+
14
+ gem 'jquery-rails'
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "cleditor_rails/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "cleditor_rails"
7
+ s.version = CleditorRails::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Sean Behan"]
10
+ s.email = ["bseanvt@gmail.com"]
11
+ s.homepage = "https://github.com/bseanvt/selectbox_rails"
12
+ s.summary = %q{jQuery CLEditor for Rails 3.1 Asset Pipeline}
13
+ s.description = %q{jQuery CLEditor for Rails 3.1 Asset Pipeline}
14
+
15
+ s.rubyforge_project = "cleditor_rails"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+ end
@@ -0,0 +1,6 @@
1
+ module CleditorRails
2
+ module Rails
3
+ class Engine < ::Rails::Engine
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,3 @@
1
+ module CleditorRails
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1 @@
1
+ require 'cleditor_rails/engine' if defined?(Rails && Rails::VERSION::MAJOR == 3 && Rails::VERSION::MINOR >=1)
Binary file
Binary file
Binary file
@@ -0,0 +1 @@
1
+ //= require jquery.cleditor
@@ -0,0 +1,1132 @@
1
+ /**
2
+ @preserve CLEditor WYSIWYG HTML Editor v1.3.0
3
+ http://premiumsoftware.net/cleditor
4
+ requires jQuery v1.4.2 or later
5
+
6
+ Copyright 2010, Chris Landowski, Premium Software, LLC
7
+ Dual licensed under the MIT or GPL Version 2 licenses.
8
+ */
9
+
10
+ // ==ClosureCompiler==
11
+ // @compilation_level SIMPLE_OPTIMIZATIONS
12
+ // @output_file_name jquery.cleditor.min.js
13
+ // ==/ClosureCompiler==
14
+
15
+ (function($) {
16
+
17
+ //==============
18
+ // jQuery Plugin
19
+ //==============
20
+
21
+ $.cleditor = {
22
+
23
+ // Define the defaults used for all new cleditor instances
24
+ defaultOptions: {
25
+ width: 500, // width not including margins, borders or padding
26
+ height: 250, // height not including margins, borders or padding
27
+ controls: // controls to add to the toolbar
28
+ "bold italic underline strikethrough subscript superscript | font size " +
29
+ "style | color highlight removeformat | bullets numbering | outdent " +
30
+ "indent | alignleft center alignright justify | undo redo | " +
31
+ "rule image link unlink | cut copy paste pastetext | print source",
32
+ colors: // colors in the color popup
33
+ "FFF FCC FC9 FF9 FFC 9F9 9FF CFF CCF FCF " +
34
+ "CCC F66 F96 FF6 FF3 6F9 3FF 6FF 99F F9F " +
35
+ "BBB F00 F90 FC6 FF0 3F3 6CC 3CF 66C C6C " +
36
+ "999 C00 F60 FC3 FC0 3C0 0CC 36F 63F C3C " +
37
+ "666 900 C60 C93 990 090 399 33F 60C 939 " +
38
+ "333 600 930 963 660 060 366 009 339 636 " +
39
+ "000 300 630 633 330 030 033 006 309 303",
40
+ fonts: // font names in the font popup
41
+ "Arial,Arial Black,Comic Sans MS,Courier New,Narrow,Garamond," +
42
+ "Georgia,Impact,Sans Serif,Serif,Tahoma,Trebuchet MS,Verdana",
43
+ sizes: // sizes in the font size popup
44
+ "1,2,3,4,5,6,7",
45
+ styles: // styles in the style popup
46
+ [["Paragraph", "<p>"], ["Header 1", "<h1>"], ["Header 2", "<h2>"],
47
+ ["Header 3", "<h3>"], ["Header 4","<h4>"], ["Header 5","<h5>"],
48
+ ["Header 6","<h6>"]],
49
+ useCSS: false, // use CSS to style HTML when possible (not supported in ie)
50
+ docType: // Document type contained within the editor
51
+ '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',
52
+ docCSSFile: // CSS file used to style the document contained within the editor
53
+ "",
54
+ bodyStyle: // style to assign to document body contained within the editor
55
+ "margin:4px; font:10pt Arial,Verdana; cursor:text"
56
+ },
57
+
58
+ // Define all usable toolbar buttons - the init string property is
59
+ // expanded during initialization back into the buttons object and
60
+ // seperate object properties are created for each button.
61
+ // e.g. buttons.size.title = "Font Size"
62
+ buttons: {
63
+ // name,title,command,popupName (""=use name)
64
+ init:
65
+ "bold,,|" +
66
+ "italic,,|" +
67
+ "underline,,|" +
68
+ "strikethrough,,|" +
69
+ "subscript,,|" +
70
+ "superscript,,|" +
71
+ "font,,fontname,|" +
72
+ "size,Font Size,fontsize,|" +
73
+ "style,,formatblock,|" +
74
+ "color,Font Color,forecolor,|" +
75
+ "highlight,Text Highlight Color,hilitecolor,color|" +
76
+ "removeformat,Remove Formatting,|" +
77
+ "bullets,,insertunorderedlist|" +
78
+ "numbering,,insertorderedlist|" +
79
+ "outdent,,|" +
80
+ "indent,,|" +
81
+ "alignleft,Align Text Left,justifyleft|" +
82
+ "center,,justifycenter|" +
83
+ "alignright,Align Text Right,justifyright|" +
84
+ "justify,,justifyfull|" +
85
+ "undo,,|" +
86
+ "redo,,|" +
87
+ "rule,Insert Horizontal Rule,inserthorizontalrule|" +
88
+ "image,Insert Image,insertimage,url|" +
89
+ "link,Insert Hyperlink,createlink,url|" +
90
+ "unlink,Remove Hyperlink,|" +
91
+ "cut,,|" +
92
+ "copy,,|" +
93
+ "paste,,|" +
94
+ "pastetext,Paste as Text,inserthtml,|" +
95
+ "print,,|" +
96
+ "source,Show Source"
97
+ },
98
+
99
+ // imagesPath - returns the path to the images folder
100
+ imagesPath: function() { return imagesPath(); }
101
+
102
+ };
103
+
104
+ // cleditor - creates a new editor for each of the matched textareas
105
+ $.fn.cleditor = function(options) {
106
+
107
+ // Create a new jQuery object to hold the results
108
+ var $result = $([]);
109
+
110
+ // Loop through all matching textareas and create the editors
111
+ this.each(function(idx, elem) {
112
+ if (elem.tagName == "TEXTAREA") {
113
+ var data = $.data(elem, CLEDITOR);
114
+ if (!data) data = new cleditor(elem, options);
115
+ $result = $result.add(data);
116
+ }
117
+ });
118
+
119
+ // return the new jQuery object
120
+ return $result;
121
+
122
+ };
123
+
124
+ //==================
125
+ // Private Variables
126
+ //==================
127
+
128
+ var
129
+
130
+ // Misc constants
131
+ BACKGROUND_COLOR = "backgroundColor",
132
+ BUTTON = "button",
133
+ BUTTON_NAME = "buttonName",
134
+ CHANGE = "change",
135
+ CLEDITOR = "cleditor",
136
+ CLICK = "click",
137
+ DISABLED = "disabled",
138
+ DIV_TAG = "<div>",
139
+ TRANSPARENT = "transparent",
140
+ UNSELECTABLE = "unselectable",
141
+
142
+ // Class name constants
143
+ MAIN_CLASS = "cleditorMain", // main containing div
144
+ TOOLBAR_CLASS = "cleditorToolbar", // toolbar div inside main div
145
+ GROUP_CLASS = "cleditorGroup", // group divs inside the toolbar div
146
+ BUTTON_CLASS = "cleditorButton", // button divs inside group div
147
+ DISABLED_CLASS = "cleditorDisabled",// disabled button divs
148
+ DIVIDER_CLASS = "cleditorDivider", // divider divs inside group div
149
+ POPUP_CLASS = "cleditorPopup", // popup divs inside body
150
+ LIST_CLASS = "cleditorList", // list popup divs inside body
151
+ COLOR_CLASS = "cleditorColor", // color popup div inside body
152
+ PROMPT_CLASS = "cleditorPrompt", // prompt popup divs inside body
153
+ MSG_CLASS = "cleditorMsg", // message popup div inside body
154
+
155
+ // Test for ie
156
+ ie = $.browser.msie,
157
+ ie6 = /msie\s6/i.test(navigator.userAgent),
158
+
159
+ // Test for iPhone/iTouch/iPad
160
+ iOS = /iphone|ipad|ipod/i.test(navigator.userAgent),
161
+
162
+ // Popups are created once as needed and shared by all editor instances
163
+ popups = {},
164
+
165
+ // Used to prevent the document click event from being bound more than once
166
+ documentClickAssigned,
167
+
168
+ // Local copy of the buttons object
169
+ buttons = $.cleditor.buttons;
170
+
171
+ //===============
172
+ // Initialization
173
+ //===============
174
+
175
+ // Expand the buttons.init string back into the buttons object
176
+ // and create seperate object properties for each button.
177
+ // e.g. buttons.size.title = "Font Size"
178
+ $.each(buttons.init.split("|"), function(idx, button) {
179
+ var items = button.split(","), name = items[0];
180
+ buttons[name] = {
181
+ stripIndex: idx,
182
+ name: name,
183
+ title: items[1] === "" ? name.charAt(0).toUpperCase() + name.substr(1) : items[1],
184
+ command: items[2] === "" ? name : items[2],
185
+ popupName: items[3] === "" ? name : items[3]
186
+ };
187
+ });
188
+ delete buttons.init;
189
+
190
+ //============
191
+ // Constructor
192
+ //============
193
+
194
+ // cleditor - creates a new editor for the passed in textarea element
195
+ cleditor = function(area, options) {
196
+
197
+ var editor = this;
198
+
199
+ // Get the defaults and override with options
200
+ editor.options = options = $.extend({}, $.cleditor.defaultOptions, options);
201
+
202
+ // Hide the textarea and associate it with this editor
203
+ var $area = editor.$area = $(area)
204
+ .hide()
205
+ .data(CLEDITOR, editor)
206
+ .blur(function() {
207
+ // Update the iframe when the textarea loses focus
208
+ updateFrame(editor, true);
209
+ });
210
+
211
+ // Create the main container and append the textarea
212
+ var $main = editor.$main = $(DIV_TAG)
213
+ .addClass(MAIN_CLASS)
214
+ .width(options.width)
215
+ .height(options.height);
216
+
217
+ // Create the toolbar
218
+ var $toolbar = editor.$toolbar = $(DIV_TAG)
219
+ .addClass(TOOLBAR_CLASS)
220
+ .appendTo($main);
221
+
222
+ // Add the first group to the toolbar
223
+ var $group = $(DIV_TAG)
224
+ .addClass(GROUP_CLASS)
225
+ .appendTo($toolbar);
226
+
227
+ // Add the buttons to the toolbar
228
+ $.each(options.controls.split(" "), function(idx, buttonName) {
229
+ if (buttonName === "") return true;
230
+
231
+ // Divider
232
+ if (buttonName == "|") {
233
+
234
+ // Add a new divider to the group
235
+ var $div = $(DIV_TAG)
236
+ .addClass(DIVIDER_CLASS)
237
+ .appendTo($group);
238
+
239
+ // Create a new group
240
+ $group = $(DIV_TAG)
241
+ .addClass(GROUP_CLASS)
242
+ .appendTo($toolbar);
243
+
244
+ }
245
+
246
+ // Button
247
+ else {
248
+
249
+ // Get the button definition
250
+ var button = buttons[buttonName];
251
+
252
+ // Add a new button to the group
253
+ var $buttonDiv = $(DIV_TAG)
254
+ .data(BUTTON_NAME, button.name)
255
+ .addClass(BUTTON_CLASS)
256
+ .attr("title", button.title)
257
+ .bind(CLICK, $.proxy(buttonClick, editor))
258
+ .appendTo($group)
259
+ .hover(hoverEnter, hoverLeave);
260
+
261
+ // Prepare the button image
262
+ var map = {};
263
+ if (button.css) map = button.css;
264
+ else if (button.image) map.backgroundImage = imageUrl(button.image);
265
+ if (button.stripIndex) map.backgroundPosition = button.stripIndex * -24;
266
+ $buttonDiv.css(map);
267
+
268
+ // Add the unselectable attribute for ie
269
+ if (ie)
270
+ $buttonDiv.attr(UNSELECTABLE, "on");
271
+
272
+ // Create the popup
273
+ if (button.popupName)
274
+ createPopup(button.popupName, options, button.popupClass,
275
+ button.popupContent, button.popupHover);
276
+
277
+ }
278
+
279
+ });
280
+
281
+ // Add the main div to the DOM and append the textarea
282
+ $main.insertBefore($area)
283
+ .append($area);
284
+
285
+ // Bind the document click event handler
286
+ if (!documentClickAssigned) {
287
+ $(document).click(function(e) {
288
+ // Dismiss all non-prompt popups
289
+ var $target = $(e.target);
290
+ if (!$target.add($target.parents()).is("." + PROMPT_CLASS))
291
+ hidePopups();
292
+ });
293
+ documentClickAssigned = true;
294
+ }
295
+
296
+ // Bind the window resize event when the width or height is auto or %
297
+ if (/auto|%/.test("" + options.width + options.height))
298
+ $(window).resize(function() {refresh(editor);});
299
+
300
+ // Create the iframe and resize the controls
301
+ refresh(editor);
302
+
303
+ };
304
+
305
+ //===============
306
+ // Public Methods
307
+ //===============
308
+
309
+ var fn = cleditor.prototype,
310
+
311
+ // Expose the following private functions as methods on the cleditor object.
312
+ // The closure compiler will rename the private functions. However, the
313
+ // exposed method names on the cleditor object will remain fixed.
314
+ methods = [
315
+ ["clear", clear],
316
+ ["disable", disable],
317
+ ["execCommand", execCommand],
318
+ ["focus", focus],
319
+ ["hidePopups", hidePopups],
320
+ ["sourceMode", sourceMode, true],
321
+ ["refresh", refresh],
322
+ ["select", select],
323
+ ["selectedHTML", selectedHTML, true],
324
+ ["selectedText", selectedText, true],
325
+ ["showMessage", showMessage],
326
+ ["updateFrame", updateFrame],
327
+ ["updateTextArea", updateTextArea]
328
+ ];
329
+
330
+ $.each(methods, function(idx, method) {
331
+ fn[method[0]] = function() {
332
+ var editor = this, args = [editor];
333
+ // using each here would cast booleans into objects!
334
+ for(var x = 0; x < arguments.length; x++) {args.push(arguments[x]);}
335
+ var result = method[1].apply(editor, args);
336
+ if (method[2]) return result;
337
+ return editor;
338
+ };
339
+ });
340
+
341
+ // change - shortcut for .bind("change", handler) or .trigger("change")
342
+ fn.change = function(handler) {
343
+ var $this = $(this);
344
+ return handler ? $this.bind(CHANGE, handler) : $this.trigger(CHANGE);
345
+ };
346
+
347
+ //===============
348
+ // Event Handlers
349
+ //===============
350
+
351
+ // buttonClick - click event handler for toolbar buttons
352
+ function buttonClick(e) {
353
+
354
+ var editor = this,
355
+ buttonDiv = e.target,
356
+ buttonName = $.data(buttonDiv, BUTTON_NAME),
357
+ button = buttons[buttonName],
358
+ popupName = button.popupName,
359
+ popup = popups[popupName];
360
+
361
+ // Check if disabled
362
+ if (editor.disabled || $(buttonDiv).attr(DISABLED) == DISABLED)
363
+ return;
364
+
365
+ // Fire the buttonClick event
366
+ var data = {
367
+ editor: editor,
368
+ button: buttonDiv,
369
+ buttonName: buttonName,
370
+ popup: popup,
371
+ popupName: popupName,
372
+ command: button.command,
373
+ useCSS: editor.options.useCSS
374
+ };
375
+
376
+ if (button.buttonClick && button.buttonClick(e, data) === false)
377
+ return false;
378
+
379
+ // Toggle source
380
+ if (buttonName == "source") {
381
+
382
+ // Show the iframe
383
+ if (sourceMode(editor)) {
384
+ delete editor.range;
385
+ editor.$area.hide();
386
+ editor.$frame.show();
387
+ buttonDiv.title = button.title;
388
+ }
389
+
390
+ // Show the textarea
391
+ else {
392
+ editor.$frame.hide();
393
+ editor.$area.show();
394
+ buttonDiv.title = "Show Rich Text";
395
+ }
396
+
397
+ // Enable or disable the toolbar buttons
398
+ // IE requires the timeout
399
+ setTimeout(function() {refreshButtons(editor);}, 100);
400
+
401
+ }
402
+
403
+ // Check for rich text mode
404
+ else if (!sourceMode(editor)) {
405
+
406
+ // Handle popups
407
+ if (popupName) {
408
+ var $popup = $(popup);
409
+
410
+ // URL
411
+ if (popupName == "url") {
412
+
413
+ // Check for selection before showing the link url popup
414
+ if (buttonName == "link" && selectedText(editor) === "") {
415
+ showMessage(editor, "A selection is required when inserting a link.", buttonDiv);
416
+ return false;
417
+ }
418
+
419
+ // Wire up the submit button click event handler
420
+ $popup.children(":button")
421
+ .unbind(CLICK)
422
+ .bind(CLICK, function() {
423
+
424
+ // Insert the image or link if a url was entered
425
+ var $text = $popup.find(":text"),
426
+ url = $.trim($text.val());
427
+ if (url !== "")
428
+ execCommand(editor, data.command, url, null, data.button);
429
+
430
+ // Reset the text, hide the popup and set focus
431
+ $text.val("http://");
432
+ hidePopups();
433
+ focus(editor);
434
+
435
+ });
436
+
437
+ }
438
+
439
+ // Paste as Text
440
+ else if (popupName == "pastetext") {
441
+
442
+ // Wire up the submit button click event handler
443
+ $popup.children(":button")
444
+ .unbind(CLICK)
445
+ .bind(CLICK, function() {
446
+
447
+ // Insert the unformatted text replacing new lines with break tags
448
+ var $textarea = $popup.find("textarea"),
449
+ text = $textarea.val().replace(/\n/g, "<br />");
450
+ if (text !== "")
451
+ execCommand(editor, data.command, text, null, data.button);
452
+
453
+ // Reset the text, hide the popup and set focus
454
+ $textarea.val("");
455
+ hidePopups();
456
+ focus(editor);
457
+
458
+ });
459
+
460
+ }
461
+
462
+ // Show the popup if not already showing for this button
463
+ if (buttonDiv !== $.data(popup, BUTTON)) {
464
+ showPopup(editor, popup, buttonDiv);
465
+ return false; // stop propagination to document click
466
+ }
467
+
468
+ // propaginate to documnt click
469
+ return;
470
+
471
+ }
472
+
473
+ // Print
474
+ else if (buttonName == "print")
475
+ editor.$frame[0].contentWindow.print();
476
+
477
+ // All other buttons
478
+ else if (!execCommand(editor, data.command, data.value, data.useCSS, buttonDiv))
479
+ return false;
480
+
481
+ }
482
+
483
+ // Focus the editor
484
+ focus(editor);
485
+
486
+ }
487
+
488
+ // hoverEnter - mouseenter event handler for buttons and popup items
489
+ function hoverEnter(e) {
490
+ var $div = $(e.target).closest("div");
491
+ $div.css(BACKGROUND_COLOR, $div.data(BUTTON_NAME) ? "#FFF" : "#FFC");
492
+ }
493
+
494
+ // hoverLeave - mouseleave event handler for buttons and popup items
495
+ function hoverLeave(e) {
496
+ $(e.target).closest("div").css(BACKGROUND_COLOR, "transparent");
497
+ }
498
+
499
+ // popupClick - click event handler for popup items
500
+ function popupClick(e) {
501
+
502
+ var editor = this,
503
+ popup = e.data.popup,
504
+ target = e.target;
505
+
506
+ // Check for message and prompt popups
507
+ if (popup === popups.msg || $(popup).hasClass(PROMPT_CLASS))
508
+ return;
509
+
510
+ // Get the button info
511
+ var buttonDiv = $.data(popup, BUTTON),
512
+ buttonName = $.data(buttonDiv, BUTTON_NAME),
513
+ button = buttons[buttonName],
514
+ command = button.command,
515
+ value,
516
+ useCSS = editor.options.useCSS;
517
+
518
+ // Get the command value
519
+ if (buttonName == "font")
520
+ // Opera returns the fontfamily wrapped in quotes
521
+ value = target.style.fontFamily.replace(/"/g, "");
522
+ else if (buttonName == "size") {
523
+ if (target.tagName == "DIV")
524
+ target = target.children[0];
525
+ value = target.innerHTML;
526
+ }
527
+ else if (buttonName == "style")
528
+ value = "<" + target.tagName + ">";
529
+ else if (buttonName == "color")
530
+ value = hex(target.style.backgroundColor);
531
+ else if (buttonName == "highlight") {
532
+ value = hex(target.style.backgroundColor);
533
+ if (ie) command = 'backcolor';
534
+ else useCSS = true;
535
+ }
536
+
537
+ // Fire the popupClick event
538
+ var data = {
539
+ editor: editor,
540
+ button: buttonDiv,
541
+ buttonName: buttonName,
542
+ popup: popup,
543
+ popupName: button.popupName,
544
+ command: command,
545
+ value: value,
546
+ useCSS: useCSS
547
+ };
548
+
549
+ if (button.popupClick && button.popupClick(e, data) === false)
550
+ return;
551
+
552
+ // Execute the command
553
+ if (data.command && !execCommand(editor, data.command, data.value, data.useCSS, buttonDiv))
554
+ return false;
555
+
556
+ // Hide the popup and focus the editor
557
+ hidePopups();
558
+ focus(editor);
559
+
560
+ }
561
+
562
+ //==================
563
+ // Private Functions
564
+ //==================
565
+
566
+ // checksum - returns a checksum using the Adler-32 method
567
+ function checksum(text)
568
+ {
569
+ var a = 1, b = 0;
570
+ for (var index = 0; index < text.length; ++index) {
571
+ a = (a + text.charCodeAt(index)) % 65521;
572
+ b = (b + a) % 65521;
573
+ }
574
+ return (b << 16) | a;
575
+ }
576
+
577
+ // clear - clears the contents of the editor
578
+ function clear(editor) {
579
+ editor.$area.val("");
580
+ updateFrame(editor);
581
+ }
582
+
583
+ // createPopup - creates a popup and adds it to the body
584
+ function createPopup(popupName, options, popupTypeClass, popupContent, popupHover) {
585
+
586
+ // Check if popup already exists
587
+ if (popups[popupName])
588
+ return popups[popupName];
589
+
590
+ // Create the popup
591
+ var $popup = $(DIV_TAG)
592
+ .hide()
593
+ .addClass(POPUP_CLASS)
594
+ .appendTo("body");
595
+
596
+ // Add the content
597
+
598
+ // Custom popup
599
+ if (popupContent)
600
+ $popup.html(popupContent);
601
+
602
+ // Color
603
+ else if (popupName == "color") {
604
+ var colors = options.colors.split(" ");
605
+ if (colors.length < 10)
606
+ $popup.width("auto");
607
+ $.each(colors, function(idx, color) {
608
+ $(DIV_TAG).appendTo($popup)
609
+ .css(BACKGROUND_COLOR, "#" + color);
610
+ });
611
+ popupTypeClass = COLOR_CLASS;
612
+ }
613
+
614
+ // Font
615
+ else if (popupName == "font")
616
+ $.each(options.fonts.split(","), function(idx, font) {
617
+ $(DIV_TAG).appendTo($popup)
618
+ .css("fontFamily", font)
619
+ .html(font);
620
+ });
621
+
622
+ // Size
623
+ else if (popupName == "size")
624
+ $.each(options.sizes.split(","), function(idx, size) {
625
+ $(DIV_TAG).appendTo($popup)
626
+ .html("<font size=" + size + ">" + size + "</font>");
627
+ });
628
+
629
+ // Style
630
+ else if (popupName == "style")
631
+ $.each(options.styles, function(idx, style) {
632
+ $(DIV_TAG).appendTo($popup)
633
+ .html(style[1] + style[0] + style[1].replace("<", "</"));
634
+ });
635
+
636
+ // URL
637
+ else if (popupName == "url") {
638
+ $popup.html('Enter URL:<br><input type=text value="http://" size=35><br><input type=button value="Submit">');
639
+ popupTypeClass = PROMPT_CLASS;
640
+ }
641
+
642
+ // Paste as Text
643
+ else if (popupName == "pastetext") {
644
+ $popup.html('Paste your content here and click submit.<br /><textarea cols=40 rows=3></textarea><br /><input type=button value=Submit>');
645
+ popupTypeClass = PROMPT_CLASS;
646
+ }
647
+
648
+ // Add the popup type class name
649
+ if (!popupTypeClass && !popupContent)
650
+ popupTypeClass = LIST_CLASS;
651
+ $popup.addClass(popupTypeClass);
652
+
653
+ // Add the unselectable attribute to all items
654
+ if (ie) {
655
+ $popup.attr(UNSELECTABLE, "on")
656
+ .find("div,font,p,h1,h2,h3,h4,h5,h6")
657
+ .attr(UNSELECTABLE, "on");
658
+ }
659
+
660
+ // Add the hover effect to all items
661
+ if ($popup.hasClass(LIST_CLASS) || popupHover === true)
662
+ $popup.children().hover(hoverEnter, hoverLeave);
663
+
664
+ // Add the popup to the array and return it
665
+ popups[popupName] = $popup[0];
666
+ return $popup[0];
667
+
668
+ }
669
+
670
+ // disable - enables or disables the editor
671
+ function disable(editor, disabled) {
672
+
673
+ // Update the textarea and save the state
674
+ if (disabled) {
675
+ editor.$area.attr(DISABLED, DISABLED);
676
+ editor.disabled = true;
677
+ }
678
+ else {
679
+ editor.$area.removeAttr(DISABLED);
680
+ delete editor.disabled;
681
+ }
682
+
683
+ // Switch the iframe into design mode.
684
+ // ie6 does not support designMode.
685
+ // ie7 & ie8 do not properly support designMode="off".
686
+ try {
687
+ if (ie) editor.doc.body.contentEditable = !disabled;
688
+ else editor.doc.designMode = !disabled ? "on" : "off";
689
+ }
690
+ // Firefox 1.5 throws an exception that can be ignored
691
+ // when toggling designMode from off to on.
692
+ catch (err) {}
693
+
694
+ // Enable or disable the toolbar buttons
695
+ refreshButtons(editor);
696
+
697
+ }
698
+
699
+ // execCommand - executes a designMode command
700
+ function execCommand(editor, command, value, useCSS, button) {
701
+
702
+ // Restore the current ie selection
703
+ restoreRange(editor);
704
+
705
+ // Set the styling method
706
+ if (!ie) {
707
+ if (useCSS === undefined || useCSS === null)
708
+ useCSS = editor.options.useCSS;
709
+ editor.doc.execCommand("styleWithCSS", 0, useCSS.toString());
710
+ }
711
+
712
+ // Execute the command and check for error
713
+ var success = true, description;
714
+ if (ie && command.toLowerCase() == "inserthtml")
715
+ getRange(editor).pasteHTML(value);
716
+ else {
717
+ try { success = editor.doc.execCommand(command, 0, value || null); }
718
+ catch (err) { description = err.description; success = false; }
719
+ if (!success) {
720
+ if ("cutcopypaste".indexOf(command) > -1)
721
+ showMessage(editor, "For security reasons, your browser does not support the " +
722
+ command + " command. Try using the keyboard shortcut or context menu instead.",
723
+ button);
724
+ else
725
+ showMessage(editor,
726
+ (description ? description : "Error executing the " + command + " command."),
727
+ button);
728
+ }
729
+ }
730
+
731
+ // Enable the buttons
732
+ refreshButtons(editor);
733
+ return success;
734
+
735
+ }
736
+
737
+ // focus - sets focus to either the textarea or iframe
738
+ function focus(editor) {
739
+ setTimeout(function() {
740
+ if (sourceMode(editor)) editor.$area.focus();
741
+ else editor.$frame[0].contentWindow.focus();
742
+ refreshButtons(editor);
743
+ }, 0);
744
+ }
745
+
746
+ // getRange - gets the current text range object
747
+ function getRange(editor) {
748
+ if (ie) return getSelection(editor).createRange();
749
+ return getSelection(editor).getRangeAt(0);
750
+ }
751
+
752
+ // getSelection - gets the current text range object
753
+ function getSelection(editor) {
754
+ if (ie) return editor.doc.selection;
755
+ return editor.$frame[0].contentWindow.getSelection();
756
+ }
757
+
758
+ // Returns the hex value for the passed in string.
759
+ // hex("rgb(255, 0, 0)"); // #FF0000
760
+ // hex("#FF0000"); // #FF0000
761
+ // hex("#F00"); // #FF0000
762
+ function hex(s) {
763
+ var m = /rgba?\((\d+), (\d+), (\d+)/.exec(s),
764
+ c = s.split("");
765
+ if (m) {
766
+ s = ( m[1] << 16 | m[2] << 8 | m[3] ).toString(16);
767
+ while (s.length < 6)
768
+ s = "0" + s;
769
+ }
770
+ return "#" + (s.length == 6 ? s : c[1] + c[1] + c[2] + c[2] + c[3] + c[3]);
771
+ }
772
+
773
+ // hidePopups - hides all popups
774
+ function hidePopups() {
775
+ $.each(popups, function(idx, popup) {
776
+ $(popup)
777
+ .hide()
778
+ .unbind(CLICK)
779
+ .removeData(BUTTON);
780
+ });
781
+ }
782
+
783
+ // imagesPath - returns the path to the images folder
784
+ function imagesPath() {
785
+ var cssFile = "jquery.cleditor.css",
786
+ href = $("link[href$='" + cssFile +"']").attr("href");
787
+ return href.substr(0, href.length - cssFile.length) + "images/";
788
+ }
789
+
790
+ // imageUrl - Returns the css url string for a filemane
791
+ function imageUrl(filename) {
792
+ return "url(" + imagesPath() + filename + ")";
793
+ }
794
+
795
+ // refresh - creates the iframe and resizes the controls
796
+ function refresh(editor) {
797
+
798
+ var $main = editor.$main,
799
+ options = editor.options;
800
+
801
+ // Remove the old iframe
802
+ if (editor.$frame)
803
+ editor.$frame.remove();
804
+
805
+ // Create a new iframe
806
+ var $frame = editor.$frame = $('<iframe frameborder="0" src="javascript:true;">')
807
+ .hide()
808
+ .appendTo($main);
809
+
810
+ // Load the iframe document content
811
+ var contentWindow = $frame[0].contentWindow,
812
+ doc = editor.doc = contentWindow.document,
813
+ $doc = $(doc);
814
+
815
+ doc.open();
816
+ doc.write(
817
+ options.docType +
818
+ '<html>' +
819
+ ((options.docCSSFile === '') ? '' : '<head><link rel="stylesheet" type="text/css" href="' + options.docCSSFile + '" /></head>') +
820
+ '<body style="' + options.bodyStyle + '"></body></html>'
821
+ );
822
+ doc.close();
823
+
824
+ // Work around for bug in IE which causes the editor to lose
825
+ // focus when clicking below the end of the document.
826
+ if (ie)
827
+ $doc.click(function() {focus(editor);});
828
+
829
+ // Load the content
830
+ updateFrame(editor);
831
+
832
+ // Bind the ie specific iframe event handlers
833
+ if (ie) {
834
+
835
+ // Save the current user selection. This code is needed since IE will
836
+ // reset the selection just after the beforedeactivate event and just
837
+ // before the beforeactivate event.
838
+ $doc.bind("beforedeactivate beforeactivate selectionchange keypress", function(e) {
839
+
840
+ // Flag the editor as inactive
841
+ if (e.type == "beforedeactivate")
842
+ editor.inactive = true;
843
+
844
+ // Get rid of the bogus selection and flag the editor as active
845
+ else if (e.type == "beforeactivate") {
846
+ if (!editor.inactive && editor.range && editor.range.length > 1)
847
+ editor.range.shift();
848
+ delete editor.inactive;
849
+ }
850
+
851
+ // Save the selection when the editor is active
852
+ else if (!editor.inactive) {
853
+ if (!editor.range)
854
+ editor.range = [];
855
+ editor.range.unshift(getRange(editor));
856
+
857
+ // We only need the last 2 selections
858
+ while (editor.range.length > 2)
859
+ editor.range.pop();
860
+ }
861
+
862
+ });
863
+
864
+ // Restore the text range when the iframe gains focus
865
+ $frame.focus(function() {
866
+ restoreRange(editor);
867
+ });
868
+
869
+ }
870
+
871
+ // Update the textarea when the iframe loses focus
872
+ ($.browser.mozilla ? $doc : $(contentWindow)).blur(function() {
873
+ updateTextArea(editor, true);
874
+ });
875
+
876
+ // Enable the toolbar buttons as the user types or clicks
877
+ $doc.click(hidePopups)
878
+ .bind("keyup mouseup", function() {
879
+ refreshButtons(editor);
880
+ });
881
+
882
+ // Show the textarea for iPhone/iTouch/iPad or
883
+ // the iframe when design mode is supported.
884
+ if (iOS) editor.$area.show();
885
+ else $frame.show();
886
+
887
+ // Wait for the layout to finish - shortcut for $(document).ready()
888
+ $(function() {
889
+
890
+ var $toolbar = editor.$toolbar,
891
+ $group = $toolbar.children("div:last"),
892
+ wid = $main.width();
893
+
894
+ // Resize the toolbar
895
+ var hgt = $group.offset().top + $group.outerHeight() - $toolbar.offset().top + 1;
896
+ $toolbar.height(hgt);
897
+
898
+ // Resize the iframe
899
+ hgt = (/%/.test("" + options.height) ? $main.height() : parseInt(options.height)) - hgt;
900
+ $frame.width(wid).height(hgt);
901
+
902
+ // Resize the textarea. IE6 textareas have a 1px top
903
+ // & bottom margin that cannot be removed using css.
904
+ editor.$area.width(wid).height(ie6 ? hgt - 2 : hgt);
905
+
906
+ // Switch the iframe into design mode if enabled
907
+ disable(editor, editor.disabled);
908
+
909
+ // Enable or disable the toolbar buttons
910
+ refreshButtons(editor);
911
+
912
+ });
913
+
914
+ }
915
+
916
+ // refreshButtons - enables or disables buttons based on availability
917
+ function refreshButtons(editor) {
918
+
919
+ // Webkit requires focus before queryCommandEnabled will return anything but false
920
+ if (!iOS && $.browser.webkit && !editor.focused) {
921
+ editor.$frame[0].contentWindow.focus();
922
+ window.focus();
923
+ editor.focused = true;
924
+ }
925
+
926
+ // Get the object used for checking queryCommandEnabled
927
+ var queryObj = editor.doc;
928
+ if (ie) queryObj = getRange(editor);
929
+
930
+ // Loop through each button
931
+ var inSourceMode = sourceMode(editor);
932
+ $.each(editor.$toolbar.find("." + BUTTON_CLASS), function(idx, elem) {
933
+
934
+ var $elem = $(elem),
935
+ button = $.cleditor.buttons[$.data(elem, BUTTON_NAME)],
936
+ command = button.command,
937
+ enabled = true;
938
+
939
+ // Determine the state
940
+ if (editor.disabled)
941
+ enabled = false;
942
+ else if (button.getEnabled) {
943
+ var data = {
944
+ editor: editor,
945
+ button: elem,
946
+ buttonName: button.name,
947
+ popup: popups[button.popupName],
948
+ popupName: button.popupName,
949
+ command: button.command,
950
+ useCSS: editor.options.useCSS
951
+ };
952
+ enabled = button.getEnabled(data);
953
+ if (enabled === undefined)
954
+ enabled = true;
955
+ }
956
+ else if (((inSourceMode || iOS) && button.name != "source") ||
957
+ (ie && (command == "undo" || command == "redo")))
958
+ enabled = false;
959
+ else if (command && command != "print") {
960
+ if (ie && command == "hilitecolor")
961
+ command = "backcolor";
962
+ // IE does not support inserthtml, so it's always enabled
963
+ if (!ie || command != "inserthtml") {
964
+ try {enabled = queryObj.queryCommandEnabled(command);}
965
+ catch (err) {enabled = false;}
966
+ }
967
+ }
968
+
969
+ // Enable or disable the button
970
+ if (enabled) {
971
+ $elem.removeClass(DISABLED_CLASS);
972
+ $elem.removeAttr(DISABLED);
973
+ }
974
+ else {
975
+ $elem.addClass(DISABLED_CLASS);
976
+ $elem.attr(DISABLED, DISABLED);
977
+ }
978
+
979
+ });
980
+ }
981
+
982
+ // restoreRange - restores the current ie selection
983
+ function restoreRange(editor) {
984
+ if (ie && editor.range)
985
+ editor.range[0].select();
986
+ }
987
+
988
+ // select - selects all the text in either the textarea or iframe
989
+ function select(editor) {
990
+ setTimeout(function() {
991
+ if (sourceMode(editor)) editor.$area.select();
992
+ else execCommand(editor, "selectall");
993
+ }, 0);
994
+ }
995
+
996
+ // selectedHTML - returns the current HTML selection or and empty string
997
+ function selectedHTML(editor) {
998
+ restoreRange(editor);
999
+ var range = getRange(editor);
1000
+ if (ie)
1001
+ return range.htmlText;
1002
+ var layer = $("<layer>")[0];
1003
+ layer.appendChild(range.cloneContents());
1004
+ var html = layer.innerHTML;
1005
+ layer = null;
1006
+ return html;
1007
+ }
1008
+
1009
+ // selectedText - returns the current text selection or and empty string
1010
+ function selectedText(editor) {
1011
+ restoreRange(editor);
1012
+ if (ie) return getRange(editor).text;
1013
+ return getSelection(editor).toString();
1014
+ }
1015
+
1016
+ // showMessage - alert replacement
1017
+ function showMessage(editor, message, button) {
1018
+ var popup = createPopup("msg", editor.options, MSG_CLASS);
1019
+ popup.innerHTML = message;
1020
+ showPopup(editor, popup, button);
1021
+ }
1022
+
1023
+ // showPopup - shows a popup
1024
+ function showPopup(editor, popup, button) {
1025
+
1026
+ var offset, left, top, $popup = $(popup);
1027
+
1028
+ // Determine the popup location
1029
+ if (button) {
1030
+ var $button = $(button);
1031
+ offset = $button.offset();
1032
+ left = --offset.left;
1033
+ top = offset.top + $button.height();
1034
+ }
1035
+ else {
1036
+ var $toolbar = editor.$toolbar;
1037
+ offset = $toolbar.offset();
1038
+ left = Math.floor(($toolbar.width() - $popup.width()) / 2) + offset.left;
1039
+ top = offset.top + $toolbar.height() - 2;
1040
+ }
1041
+
1042
+ // Position and show the popup
1043
+ hidePopups();
1044
+ $popup.css({left: left, top: top})
1045
+ .show();
1046
+
1047
+ // Assign the popup button and click event handler
1048
+ if (button) {
1049
+ $.data(popup, BUTTON, button);
1050
+ $popup.bind(CLICK, {popup: popup}, $.proxy(popupClick, editor));
1051
+ }
1052
+
1053
+ // Focus the first input element if any
1054
+ setTimeout(function() {
1055
+ $popup.find(":text,textarea").eq(0).focus().select();
1056
+ }, 100);
1057
+
1058
+ }
1059
+
1060
+ // sourceMode - returns true if the textarea is showing
1061
+ function sourceMode(editor) {
1062
+ return editor.$area.is(":visible");
1063
+ }
1064
+
1065
+ // updateFrame - updates the iframe with the textarea contents
1066
+ function updateFrame(editor, checkForChange) {
1067
+
1068
+ var code = editor.$area.val(),
1069
+ options = editor.options,
1070
+ updateFrameCallback = options.updateFrame,
1071
+ $body = $(editor.doc.body);
1072
+
1073
+ // Check for textarea change to avoid unnecessary firing
1074
+ // of potentially heavy updateFrame callbacks.
1075
+ if (updateFrameCallback) {
1076
+ var sum = checksum(code);
1077
+ if (checkForChange && editor.areaChecksum == sum)
1078
+ return;
1079
+ editor.areaChecksum = sum;
1080
+ }
1081
+
1082
+ // Convert the textarea source code into iframe html
1083
+ var html = updateFrameCallback ? updateFrameCallback(code) : code;
1084
+
1085
+ // Prevent script injection attacks by html encoding script tags
1086
+ html = html.replace(/<(?=\/?script)/ig, "&lt;");
1087
+
1088
+ // Update the iframe checksum
1089
+ if (options.updateTextArea)
1090
+ editor.frameChecksum = checksum(html);
1091
+
1092
+ // Update the iframe and trigger the change event
1093
+ if (html != $body.html()) {
1094
+ $body.html(html);
1095
+ $(editor).triggerHandler(CHANGE);
1096
+ }
1097
+
1098
+ }
1099
+
1100
+ // updateTextArea - updates the textarea with the iframe contents
1101
+ function updateTextArea(editor, checkForChange) {
1102
+
1103
+ var html = $(editor.doc.body).html(),
1104
+ options = editor.options,
1105
+ updateTextAreaCallback = options.updateTextArea,
1106
+ $area = editor.$area;
1107
+
1108
+ // Check for iframe change to avoid unnecessary firing
1109
+ // of potentially heavy updateTextArea callbacks.
1110
+ if (updateTextAreaCallback) {
1111
+ var sum = checksum(html);
1112
+ if (checkForChange && editor.frameChecksum == sum)
1113
+ return;
1114
+ editor.frameChecksum = sum;
1115
+ }
1116
+
1117
+ // Convert the iframe html into textarea source code
1118
+ var code = updateTextAreaCallback ? updateTextAreaCallback(html) : html;
1119
+
1120
+ // Update the textarea checksum
1121
+ if (options.updateFrame)
1122
+ editor.areaChecksum = checksum(code);
1123
+
1124
+ // Update the textarea and trigger the change event
1125
+ if (code != $area.val()) {
1126
+ $area.val(code);
1127
+ $(editor).triggerHandler(CHANGE);
1128
+ }
1129
+
1130
+ }
1131
+
1132
+ })(jQuery);
@@ -0,0 +1,31 @@
1
+ /*
2
+ CLEditor WYSIWYG HTML Editor v1.3.0
3
+ http://premiumsoftware.net/cleditor
4
+ requires jQuery v1.4.2 or later
5
+
6
+ Copyright 2010, Chris Landowski, Premium Software, LLC
7
+ Dual licensed under the MIT or GPL Version 2 licenses.
8
+ */
9
+ (function(e){function aa(a){var b=this,c=a.target,d=e.data(c,x),h=s[d],f=h.popupName,i=p[f];if(!(b.disabled||e(c).attr(n)==n)){var g={editor:b,button:c,buttonName:d,popup:i,popupName:f,command:h.command,useCSS:b.options.useCSS};if(h.buttonClick&&h.buttonClick(a,g)===false)return false;if(d=="source"){if(t(b)){delete b.range;b.$area.hide();b.$frame.show();c.title=h.title}else{b.$frame.hide();b.$area.show();c.title="Show Rich Text"}setTimeout(function(){u(b)},100)}else if(!t(b))if(f){var j=e(i);if(f==
10
+ "url"){if(d=="link"&&M(b)===""){z(b,"A selection is required when inserting a link.",c);return false}j.children(":button").unbind(q).bind(q,function(){var k=j.find(":text"),o=e.trim(k.val());o!==""&&v(b,g.command,o,null,g.button);k.val("http://");r();w(b)})}else f=="pastetext"&&j.children(":button").unbind(q).bind(q,function(){var k=j.find("textarea"),o=k.val().replace(/\n/g,"<br />");o!==""&&v(b,g.command,o,null,g.button);k.val("");r();w(b)});if(c!==e.data(i,A)){N(b,i,c);return false}return}else if(d==
11
+ "print")b.$frame[0].contentWindow.print();else if(!v(b,g.command,g.value,g.useCSS,c))return false;w(b)}}function O(a){a=e(a.target).closest("div");a.css(H,a.data(x)?"#FFF":"#FFC")}function P(a){e(a.target).closest("div").css(H,"transparent")}function ba(a){var b=a.data.popup,c=a.target;if(!(b===p.msg||e(b).hasClass(B))){var d=e.data(b,A),h=e.data(d,x),f=s[h],i=f.command,g,j=this.options.useCSS;if(h=="font")g=c.style.fontFamily.replace(/"/g,"");else if(h=="size"){if(c.tagName=="DIV")c=c.children[0];
12
+ g=c.innerHTML}else if(h=="style")g="<"+c.tagName+">";else if(h=="color")g=Q(c.style.backgroundColor);else if(h=="highlight"){g=Q(c.style.backgroundColor);if(l)i="backcolor";else j=true}b={editor:this,button:d,buttonName:h,popup:b,popupName:f.popupName,command:i,value:g,useCSS:j};if(!(f.popupClick&&f.popupClick(a,b)===false)){if(b.command&&!v(this,b.command,b.value,b.useCSS,d))return false;r();w(this)}}}function C(a){for(var b=1,c=0,d=0;d<a.length;++d){b=(b+a.charCodeAt(d))%65521;c=(c+b)%65521}return c<<
13
+ 16|b}function R(a,b,c,d,h){if(p[a])return p[a];var f=e(m).hide().addClass(ca).appendTo("body");if(d)f.html(d);else if(a=="color"){b=b.colors.split(" ");b.length<10&&f.width("auto");e.each(b,function(i,g){e(m).appendTo(f).css(H,"#"+g)});c=da}else if(a=="font")e.each(b.fonts.split(","),function(i,g){e(m).appendTo(f).css("fontFamily",g).html(g)});else if(a=="size")e.each(b.sizes.split(","),function(i,g){e(m).appendTo(f).html("<font size="+g+">"+g+"</font>")});else if(a=="style")e.each(b.styles,function(i,
14
+ g){e(m).appendTo(f).html(g[1]+g[0]+g[1].replace("<","</"))});else if(a=="url"){f.html('Enter URL:<br><input type=text value="http://" size=35><br><input type=button value="Submit">');c=B}else if(a=="pastetext"){f.html("Paste your content here and click submit.<br /><textarea cols=40 rows=3></textarea><br /><input type=button value=Submit>");c=B}if(!c&&!d)c=S;f.addClass(c);l&&f.attr(I,"on").find("div,font,p,h1,h2,h3,h4,h5,h6").attr(I,"on");if(f.hasClass(S)||h===true)f.children().hover(O,P);p[a]=f[0];
15
+ return f[0]}function T(a,b){if(b){a.$area.attr(n,n);a.disabled=true}else{a.$area.removeAttr(n);delete a.disabled}try{if(l)a.doc.body.contentEditable=!b;else a.doc.designMode=!b?"on":"off"}catch(c){}u(a)}function v(a,b,c,d,h){D(a);if(!l){if(d===undefined||d===null)d=a.options.useCSS;a.doc.execCommand("styleWithCSS",0,d.toString())}d=true;var f;if(l&&b.toLowerCase()=="inserthtml")y(a).pasteHTML(c);else{try{d=a.doc.execCommand(b,0,c||null)}catch(i){f=i.description;d=false}d||("cutcopypaste".indexOf(b)>
16
+ -1?z(a,"For security reasons, your browser does not support the "+b+" command. Try using the keyboard shortcut or context menu instead.",h):z(a,f?f:"Error executing the "+b+" command.",h))}u(a);return d}function w(a){setTimeout(function(){t(a)?a.$area.focus():a.$frame[0].contentWindow.focus();u(a)},0)}function y(a){if(l)return J(a).createRange();return J(a).getRangeAt(0)}function J(a){if(l)return a.doc.selection;return a.$frame[0].contentWindow.getSelection()}function Q(a){var b=/rgba?\((\d+), (\d+), (\d+)/.exec(a),
17
+ c=a.split("");if(b)for(a=(b[1]<<16|b[2]<<8|b[3]).toString(16);a.length<6;)a="0"+a;return"#"+(a.length==6?a:c[1]+c[1]+c[2]+c[2]+c[3]+c[3])}function r(){e.each(p,function(a,b){e(b).hide().unbind(q).removeData(A)})}function U(){var a=e("link[href$='jquery.cleditor.css']").attr("href");return a.substr(0,a.length-19)+"images/"}function K(a){var b=a.$main,c=a.options;a.$frame&&a.$frame.remove();var d=a.$frame=e('<iframe frameborder="0" src="javascript:true;">').hide().appendTo(b),h=d[0].contentWindow,f=
18
+ a.doc=h.document,i=e(f);f.open();f.write(c.docType+"<html>"+(c.docCSSFile===""?"":'<head><link rel="stylesheet" type="text/css" href="'+c.docCSSFile+'" /></head>')+'<body style="'+c.bodyStyle+'"></body></html>');f.close();l&&i.click(function(){w(a)});E(a);if(l){i.bind("beforedeactivate beforeactivate selectionchange keypress",function(g){if(g.type=="beforedeactivate")a.inactive=true;else if(g.type=="beforeactivate"){!a.inactive&&a.range&&a.range.length>1&&a.range.shift();delete a.inactive}else if(!a.inactive){if(!a.range)a.range=
19
+ [];for(a.range.unshift(y(a));a.range.length>2;)a.range.pop()}});d.focus(function(){D(a)})}(e.browser.mozilla?i:e(h)).blur(function(){V(a,true)});i.click(r).bind("keyup mouseup",function(){u(a)});L?a.$area.show():d.show();e(function(){var g=a.$toolbar,j=g.children("div:last"),k=b.width();j=j.offset().top+j.outerHeight()-g.offset().top+1;g.height(j);j=(/%/.test(""+c.height)?b.height():parseInt(c.height))-j;d.width(k).height(j);a.$area.width(k).height(ea?j-2:j);T(a,a.disabled);u(a)})}function u(a){if(!L&&
20
+ e.browser.webkit&&!a.focused){a.$frame[0].contentWindow.focus();window.focus();a.focused=true}var b=a.doc;if(l)b=y(a);var c=t(a);e.each(a.$toolbar.find("."+W),function(d,h){var f=e(h),i=e.cleditor.buttons[e.data(h,x)],g=i.command,j=true;if(a.disabled)j=false;else if(i.getEnabled){j=i.getEnabled({editor:a,button:h,buttonName:i.name,popup:p[i.popupName],popupName:i.popupName,command:i.command,useCSS:a.options.useCSS});if(j===undefined)j=true}else if((c||L)&&i.name!="source"||l&&(g=="undo"||g=="redo"))j=
21
+ false;else if(g&&g!="print"){if(l&&g=="hilitecolor")g="backcolor";if(!l||g!="inserthtml")try{j=b.queryCommandEnabled(g)}catch(k){j=false}}if(j){f.removeClass(X);f.removeAttr(n)}else{f.addClass(X);f.attr(n,n)}})}function D(a){l&&a.range&&a.range[0].select()}function M(a){D(a);if(l)return y(a).text;return J(a).toString()}function z(a,b,c){var d=R("msg",a.options,fa);d.innerHTML=b;N(a,d,c)}function N(a,b,c){var d,h,f=e(b);if(c){var i=e(c);d=i.offset();h=--d.left;d=d.top+i.height()}else{i=a.$toolbar;
22
+ d=i.offset();h=Math.floor((i.width()-f.width())/2)+d.left;d=d.top+i.height()-2}r();f.css({left:h,top:d}).show();if(c){e.data(b,A,c);f.bind(q,{popup:b},e.proxy(ba,a))}setTimeout(function(){f.find(":text,textarea").eq(0).focus().select()},100)}function t(a){return a.$area.is(":visible")}function E(a,b){var c=a.$area.val(),d=a.options,h=d.updateFrame,f=e(a.doc.body);if(h){var i=C(c);if(b&&a.areaChecksum==i)return;a.areaChecksum=i}c=h?h(c):c;c=c.replace(/<(?=\/?script)/ig,"&lt;");if(d.updateTextArea)a.frameChecksum=
23
+ C(c);if(c!=f.html()){f.html(c);e(a).triggerHandler(F)}}function V(a,b){var c=e(a.doc.body).html(),d=a.options,h=d.updateTextArea,f=a.$area;if(h){var i=C(c);if(b&&a.frameChecksum==i)return;a.frameChecksum=i}c=h?h(c):c;if(d.updateFrame)a.areaChecksum=C(c);if(c!=f.val()){f.val(c);e(a).triggerHandler(F)}}e.cleditor={defaultOptions:{width:500,height:250,controls:"bold italic underline strikethrough subscript superscript | font size style | color highlight removeformat | bullets numbering | outdent indent | alignleft center alignright justify | undo redo | rule image link unlink | cut copy paste pastetext | print source",
24
+ colors:"FFF FCC FC9 FF9 FFC 9F9 9FF CFF CCF FCF CCC F66 F96 FF6 FF3 6F9 3FF 6FF 99F F9F BBB F00 F90 FC6 FF0 3F3 6CC 3CF 66C C6C 999 C00 F60 FC3 FC0 3C0 0CC 36F 63F C3C 666 900 C60 C93 990 090 399 33F 60C 939 333 600 930 963 660 060 366 009 339 636 000 300 630 633 330 030 033 006 309 303",fonts:"Arial,Arial Black,Comic Sans MS,Courier New,Narrow,Garamond,Georgia,Impact,Sans Serif,Serif,Tahoma,Trebuchet MS,Verdana",sizes:"1,2,3,4,5,6,7",styles:[["Paragraph","<p>"],["Header 1","<h1>"],["Header 2","<h2>"],
25
+ ["Header 3","<h3>"],["Header 4","<h4>"],["Header 5","<h5>"],["Header 6","<h6>"]],useCSS:false,docType:'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',docCSSFile:"",bodyStyle:"margin:4px; font:10pt Arial,Verdana; cursor:text"},buttons:{init:"bold,,|italic,,|underline,,|strikethrough,,|subscript,,|superscript,,|font,,fontname,|size,Font Size,fontsize,|style,,formatblock,|color,Font Color,forecolor,|highlight,Text Highlight Color,hilitecolor,color|removeformat,Remove Formatting,|bullets,,insertunorderedlist|numbering,,insertorderedlist|outdent,,|indent,,|alignleft,Align Text Left,justifyleft|center,,justifycenter|alignright,Align Text Right,justifyright|justify,,justifyfull|undo,,|redo,,|rule,Insert Horizontal Rule,inserthorizontalrule|image,Insert Image,insertimage,url|link,Insert Hyperlink,createlink,url|unlink,Remove Hyperlink,|cut,,|copy,,|paste,,|pastetext,Paste as Text,inserthtml,|print,,|source,Show Source"},
26
+ imagesPath:function(){return U()}};e.fn.cleditor=function(a){var b=e([]);this.each(function(c,d){if(d.tagName=="TEXTAREA"){var h=e.data(d,Y);h||(h=new cleditor(d,a));b=b.add(h)}});return b};var H="backgroundColor",A="button",x="buttonName",F="change",Y="cleditor",q="click",n="disabled",m="<div>",I="unselectable",W="cleditorButton",X="cleditorDisabled",ca="cleditorPopup",S="cleditorList",da="cleditorColor",B="cleditorPrompt",fa="cleditorMsg",l=e.browser.msie,ea=/msie\s6/i.test(navigator.userAgent),
27
+ L=/iphone|ipad|ipod/i.test(navigator.userAgent),p={},Z,s=e.cleditor.buttons;e.each(s.init.split("|"),function(a,b){var c=b.split(","),d=c[0];s[d]={stripIndex:a,name:d,title:c[1]===""?d.charAt(0).toUpperCase()+d.substr(1):c[1],command:c[2]===""?d:c[2],popupName:c[3]===""?d:c[3]}});delete s.init;cleditor=function(a,b){var c=this;c.options=b=e.extend({},e.cleditor.defaultOptions,b);var d=c.$area=e(a).hide().data(Y,c).blur(function(){E(c,true)}),h=c.$main=e(m).addClass("cleditorMain").width(b.width).height(b.height),
28
+ f=c.$toolbar=e(m).addClass("cleditorToolbar").appendTo(h),i=e(m).addClass("cleditorGroup").appendTo(f);e.each(b.controls.split(" "),function(g,j){if(j==="")return true;if(j=="|"){e(m).addClass("cleditorDivider").appendTo(i);i=e(m).addClass("cleditorGroup").appendTo(f)}else{var k=s[j],o=e(m).data(x,k.name).addClass(W).attr("title",k.title).bind(q,e.proxy(aa,c)).appendTo(i).hover(O,P),G={};if(k.css)G=k.css;else if(k.image)G.backgroundImage="url("+U()+k.image+")";if(k.stripIndex)G.backgroundPosition=
29
+ k.stripIndex*-24;o.css(G);l&&o.attr(I,"on");k.popupName&&R(k.popupName,b,k.popupClass,k.popupContent,k.popupHover)}});h.insertBefore(d).append(d);if(!Z){e(document).click(function(g){g=e(g.target);g.add(g.parents()).is("."+B)||r()});Z=true}/auto|%/.test(""+b.width+b.height)&&e(window).resize(function(){K(c)});K(c)};var $=cleditor.prototype;e.each([["clear",function(a){a.$area.val("");E(a)}],["disable",T],["execCommand",v],["focus",w],["hidePopups",r],["sourceMode",t,true],["refresh",K],["select",
30
+ function(a){setTimeout(function(){t(a)?a.$area.select():v(a,"selectall")},0)}],["selectedHTML",function(a){D(a);a=y(a);if(l)return a.htmlText;var b=e("<layer>")[0];b.appendChild(a.cloneContents());return b.innerHTML},true],["selectedText",M,true],["showMessage",z],["updateFrame",E],["updateTextArea",V]],function(a,b){$[b[0]]=function(){for(var c=[this],d=0;d<arguments.length;d++)c.push(arguments[d]);c=b[1].apply(this,c);if(b[2])return c;return this}});$.change=function(a){var b=e(this);return a?b.bind(F,
31
+ a):b.trigger(F)}})(jQuery);
@@ -0,0 +1,3 @@
1
+ /*
2
+ *= require jquery.cleditor
3
+ */
@@ -0,0 +1,23 @@
1
+ .cleditorMain {border:1px solid #999; padding:0 1px 1px; background-color:white}
2
+ .cleditorMain iframe {border:none; margin:0; padding:0}
3
+ .cleditorMain textarea {border:none; margin:0; padding:0; overflow-y:scroll; font:10pt Arial,Verdana; resize:none; outline:none /* webkit grip focus */}
4
+ .cleditorToolbar {width:100%;background: url('toolbar.gif') repeat}
5
+ .cleditorGroup {float:left; height:26px}
6
+ .cleditorButton {float:left; width:24px; height:24px; margin:1px 0 1px 0; background: url('buttons.gif')}
7
+ .cleditorDisabled {opacity:0.3; filter:alpha(opacity=30)}
8
+ .cleditorDivider {float:left; width:1px; height:23px; margin:1px 0 1px 0; background:#CCC}
9
+ .cleditorPopup {border:solid 1px #999; background-color:white; position:absolute; font:10pt Arial,Verdana; cursor:default; z-index:10000}
10
+ .cleditorList div {padding:2px 4px 2px 4px}
11
+ .cleditorList p,
12
+ .cleditorList h1,
13
+ .cleditorList h2,
14
+ .cleditorList h3,
15
+ .cleditorList h4,
16
+ .cleditorList h5,
17
+ .cleditorList h6,
18
+ .cleditorList font {padding:0; margin:0; background-color:Transparent}
19
+ .cleditorColor {width:150px; padding:1px 0 0 1px}
20
+ .cleditorColor div {float:left; width:14px; height:14px; margin:0 1px 1px 0}
21
+ .cleditorPrompt {background-color:#F6F7F9; padding:4px; font-size:8.5pt}
22
+ .cleditorPrompt textarea {font:8.5pt Arial,Verdana;}
23
+ .cleditorMsg {background-color:#FDFCEE; width:150px; padding:4px; font-size:8.5pt}
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cleditor_rails
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Sean Behan
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-07-12 00:00:00 -04:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: jQuery CLEditor for Rails 3.1 Asset Pipeline
23
+ email:
24
+ - bseanvt@gmail.com
25
+ executables: []
26
+
27
+ extensions: []
28
+
29
+ extra_rdoc_files: []
30
+
31
+ files:
32
+ - .gitignore
33
+ - Gemfile
34
+ - Rakefile
35
+ - cleditor_rails.gemspec
36
+ - lib/cleditor_rails.rb
37
+ - lib/cleditor_rails/engine.rb
38
+ - lib/cleditor_rails/version.rb
39
+ - vendor/assets/.DS_Store
40
+ - vendor/assets/images/buttons.gif
41
+ - vendor/assets/images/toolbar.gif
42
+ - vendor/assets/javascripts/cleditor.js
43
+ - vendor/assets/javascripts/jquery.cleditor.js
44
+ - vendor/assets/javascripts/jquery.cleditor.min.js
45
+ - vendor/assets/stylesheets/cleditor.css
46
+ - vendor/assets/stylesheets/jquery.cleditor.css
47
+ has_rdoc: true
48
+ homepage: https://github.com/bseanvt/selectbox_rails
49
+ licenses: []
50
+
51
+ post_install_message:
52
+ rdoc_options: []
53
+
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 3
62
+ segments:
63
+ - 0
64
+ version: "0"
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ hash: 3
71
+ segments:
72
+ - 0
73
+ version: "0"
74
+ requirements: []
75
+
76
+ rubyforge_project: cleditor_rails
77
+ rubygems_version: 1.3.7
78
+ signing_key:
79
+ specification_version: 3
80
+ summary: jQuery CLEditor for Rails 3.1 Asset Pipeline
81
+ test_files: []
82
+