cleditor_rails 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +14 -0
- data/Rakefile +2 -0
- data/cleditor_rails.gemspec +21 -0
- data/lib/cleditor_rails/engine.rb +6 -0
- data/lib/cleditor_rails/version.rb +3 -0
- data/lib/cleditor_rails.rb +1 -0
- data/vendor/assets/.DS_Store +0 -0
- data/vendor/assets/images/buttons.gif +0 -0
- data/vendor/assets/images/toolbar.gif +0 -0
- data/vendor/assets/javascripts/cleditor.js +1 -0
- data/vendor/assets/javascripts/jquery.cleditor.js +1132 -0
- data/vendor/assets/javascripts/jquery.cleditor.min.js +31 -0
- data/vendor/assets/stylesheets/cleditor.css +3 -0
- data/vendor/assets/stylesheets/jquery.cleditor.css +23 -0
- metadata +82 -0
data/.gitignore
ADDED
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,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 @@
|
|
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, "<");
|
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,"<");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,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
|
+
|