diff --git a/.bashrc b/.bashrc
new file mode 100644
index 0000000..607ec62
--- /dev/null
+++ b/.bashrc
@@ -0,0 +1 @@
+[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm"
diff --git a/Gemfile b/Gemfile
index 0960f7d..fde5586 100644
--- a/Gemfile
+++ b/Gemfile
@@ -8,8 +8,7 @@ gem 'bcrypt-ruby', '~> 3.0.0'
gem 'mysql2'
gem 'sass-rails'
- gem 'compass-rails'
- gem 'zurb-foundation', ">= 3.2"
+
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
@@ -30,18 +29,15 @@ gem 'turbolinks'
gem 'jbuilder', '~> 1.0.1'
gem "therubyracer"
-gem "less-rails"
-gem "twitter-bootstrap-rails"
+#gem "less-rails"
+#gem "twitter-bootstrap-rails"
gem 'haml-rails'
gem 'nokogiri'
gem 'acts_as_tree'
-gem 'formtastic', :git => 'git://github.com/justinfrench/formtastic.git'
-gem 'kaminari-bootstrap'
-
gem "htmlentities"
@@ -80,7 +76,9 @@ gem "geocoder"
gem 'pygments.rb'
gem 'redcarpet'
gem "non-stupid-digest-assets"
-
+gem "twitter-bootstrap-rails"
+gem 'formtastic', "2.3.0"
+gem 'formtastic-bootstrap'
# Use debugger
# gem 'debugger', group: [:development, :test]
diff --git a/Gemfile.lock b/Gemfile.lock
index a398b8e..e3786a6 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,10 +1,3 @@
-GIT
- remote: git://github.com/justinfrench/formtastic.git
- revision: f630fb0bee233c75301cc0a362cfbe58ae7b5001
- specs:
- formtastic (2.3.0.rc2)
- actionpack (>= 3.0)
-
GEM
remote: https://rubygems.org/
specs:
@@ -32,44 +25,46 @@ GEM
multi_json (~> 1.3)
thread_safe (~> 0.1)
tzinfo (~> 0.3.37)
- acts_as_commentable (4.0.1)
- acts_as_tree (1.5.1)
+ acts_as_commentable (4.0.2)
+ acts_as_tree (2.1.0)
activerecord (>= 3.0.0)
arel (4.0.2)
- bcrypt (3.1.7)
+ bcrypt (3.1.9)
bcrypt-ruby (3.0.1)
builder (3.1.4)
cancan (1.6.10)
+ capistrano (2.15.5)
+ highline
+ net-scp (>= 1.0.0)
+ net-sftp (>= 2.0.0)
+ net-ssh (>= 2.0.14)
+ net-ssh-gateway (>= 1.1.0)
carrierwave (0.9.0)
activemodel (>= 3.2.0)
activesupport (>= 3.2.0)
json (>= 1.7)
- chunky_png (1.3.0)
coffee-rails (4.0.1)
coffee-script (>= 2.2.0)
railties (>= 4.0.0, < 5.0)
- coffee-script (2.2.0)
+ coffee-script (2.3.0)
coffee-script-source
execjs
- coffee-script-source (1.7.0)
- commonjs (0.2.7)
- compass (0.12.5)
- chunky_png (~> 1.2)
- fssm (>= 0.2.7)
- sass (~> 3.2.19)
- compass-rails (1.1.6)
- compass (>= 0.12.2)
- devise (3.2.4)
+ coffee-script-source (1.8.0)
+ devise (3.4.1)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 3.2.6, < 5)
+ responders
thread_safe (~> 0.1)
warden (~> 1.2.3)
erubis (2.7.0)
- execjs (2.0.2)
- fssm (0.2.10)
- geocoder (1.1.9)
- haml (4.0.5)
+ execjs (2.2.2)
+ formtastic (2.3.0)
+ actionpack (>= 3.0)
+ formtastic-bootstrap (3.0.0)
+ formtastic (>= 2.2)
+ geocoder (1.2.6)
+ haml (4.0.6)
tilt
haml-rails (0.5.1)
actionpack (~> 4.0.0)
@@ -78,44 +73,46 @@ GEM
railties (~> 4.0.0)
highline (1.6.21)
hike (1.2.3)
- htmlentities (4.3.1)
- i18n (0.6.9)
+ htmlentities (4.3.2)
+ i18n (0.6.11)
jbuilder (1.0.2)
activesupport (>= 3.0.0)
- jquery-rails (3.1.0)
+ jquery-rails (3.1.2)
railties (>= 3.0, < 5.0)
thor (>= 0.14, < 2.0)
- jquery-ui-rails (4.2.0)
+ jquery-ui-rails (5.0.3)
railties (>= 3.2.16)
json (1.8.1)
- kaminari (0.15.1)
+ kaminari (0.16.1)
actionpack (>= 3.0.0)
activesupport (>= 3.0.0)
kaminari-bootstrap (3.0.1)
kaminari (>= 0.13.0)
rails
- kgio (2.8.0)
- less (2.5.0)
- commonjs (~> 0.2.7)
- less-rails (2.5.0)
- actionpack (>= 3.1)
- less (~> 2.5.0)
- libv8 (3.16.14.3)
+ kgio (2.9.2)
+ libv8 (3.16.14.7)
mail (2.5.4)
mime-types (~> 1.16)
treetop (~> 1.4.8)
mime-types (1.25.1)
- mini_portile (0.5.3)
+ mini_portile (0.6.1)
minitest (4.7.5)
- multi_json (1.9.2)
- mysql2 (0.3.15)
- nokogiri (1.6.1)
- mini_portile (~> 0.5.0)
+ multi_json (1.10.1)
+ mysql2 (0.3.17)
+ net-scp (1.2.1)
+ net-ssh (>= 2.6.5)
+ net-sftp (2.1.2)
+ net-ssh (>= 2.6.5)
+ net-ssh (2.9.1)
+ net-ssh-gateway (1.2.0)
+ net-ssh (>= 2.6.5)
+ nokogiri (1.6.5)
+ mini_portile (~> 0.6.0)
non-stupid-digest-assets (1.0.4)
orm_adapter (0.5.0)
- polyglot (0.3.4)
- posix-spawn (0.3.8)
- pygments.rb (0.5.4)
+ polyglot (0.3.5)
+ posix-spawn (0.3.9)
+ pygments.rb (0.6.0)
posix-spawn (~> 0.3.6)
yajl-ruby (~> 1.1.0)
rack (1.5.2)
@@ -134,24 +131,27 @@ GEM
activesupport (= 4.0.0)
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
- raindrops (0.11.0)
- rake (10.1.0)
- rdoc (4.1.1)
+ raindrops (0.13.0)
+ rake (10.4.2)
+ rdoc (4.1.2)
json (~> 1.4)
- redcarpet (3.1.1)
+ redcarpet (3.2.1)
ref (1.0.5)
- rmagick (2.13.2)
- rvm-capistrano (1.5.1)
+ responders (1.1.2)
+ railties (>= 3.2, < 4.2)
+ rmagick (2.13.4)
+ rvm-capistrano (1.5.5)
capistrano (~> 2.15.4)
sass (3.2.19)
- sass-rails (4.0.1)
+ sass-rails (4.0.5)
railties (>= 4.0.0, < 5.0)
- sass (>= 3.1.10)
- sprockets-rails (~> 2.0.0)
- sdoc (0.4.0)
- json (~> 1.8)
- rdoc (~> 4.0, < 5.0)
- sprockets (2.12.0)
+ sass (~> 3.2.2)
+ sprockets (~> 2.8, < 3.0)
+ sprockets-rails (~> 2.0)
+ sdoc (0.4.1)
+ json (~> 1.7, >= 1.7.7)
+ rdoc (~> 4.0)
+ sprockets (2.12.3)
hike (~> 1.2)
multi_json (~> 1.0)
rack (~> 1.0)
@@ -164,20 +164,20 @@ GEM
libv8 (~> 3.16.14.0)
ref
thor (0.19.1)
- thread_safe (0.3.3)
+ thread_safe (0.3.4)
tilt (1.4.1)
treetop (1.4.15)
polyglot
polyglot (>= 0.3.1)
- turbolinks (2.2.2)
+ turbolinks (2.5.2)
coffee-rails
twitter-bootstrap-rails (2.2.8)
actionpack (>= 3.1)
execjs
rails (>= 3.1)
railties (>= 3.1)
- tzinfo (0.3.39)
- uglifier (2.5.0)
+ tzinfo (0.3.42)
+ uglifier (2.5.3)
execjs (>= 0.3.0)
json (>= 1.8.0)
unicorn (4.6.3)
@@ -187,8 +187,6 @@ GEM
warden (1.2.3)
rack (>= 1.0)
yajl-ruby (1.1.0)
- zurb-foundation (4.3.2)
- sass (>= 3.2.0)
PLATFORMS
ruby
@@ -201,9 +199,9 @@ DEPENDENCIES
capistrano
carrierwave (= 0.9.0)
coffee-rails (~> 4.0.0)
- compass-rails
devise
- formtastic!
+ formtastic (= 2.3.0)
+ formtastic-bootstrap
geocoder
haml-rails
htmlentities
@@ -212,7 +210,6 @@ DEPENDENCIES
jquery-ui-rails
kaminari
kaminari-bootstrap
- less-rails
mysql2
nokogiri
non-stupid-digest-assets
@@ -228,4 +225,3 @@ DEPENDENCIES
twitter-bootstrap-rails
uglifier (>= 1.3.0)
unicorn (= 4.6.3)
- zurb-foundation (>= 3.2)
diff --git a/app/assets/javascripts/admin.js b/app/assets/javascripts/admin.js
index de912ab..634a807 100644
--- a/app/assets/javascripts/admin.js
+++ b/app/assets/javascripts/admin.js
@@ -1,6 +1,5 @@
/*
=require jquery
-= require jquery.ui.all
= require twitter/bootstrap
diff --git a/app/assets/javascripts/connexion.coffee b/app/assets/javascripts/connexion.coffee
index 5127ddf..943ed17 100644
--- a/app/assets/javascripts/connexion.coffee
+++ b/app/assets/javascripts/connexion.coffee
@@ -1,5 +1,4 @@
#= require jquery
-#= require jquery.ui.all
#= require twitter/bootstrap
#= require ./shared/jquery.backstretch.js
diff --git a/app/assets/javascripts/forum.coffee b/app/assets/javascripts/forum.coffee
index 069120f..86fd268 100644
--- a/app/assets/javascripts/forum.coffee
+++ b/app/assets/javascripts/forum.coffee
@@ -16,7 +16,7 @@
$(document).on "scroll", () ->
if( $(this).scrollTop() <= 40 )
- top = 40 - $(this).scrollTop()
+ top = 50 - $(this).scrollTop()
else
top = 0
@@ -28,7 +28,7 @@ $(document).on "scroll", () ->
$(".images .user_image").click ->
src = undefined
src = $(this).data("src-large")
- $("#message_form .content").redactor().insertHtml "
"
+ $("#message_form .content").redactor('insert.html', "
");
false
return
diff --git a/app/assets/javascripts/redactor.js b/app/assets/javascripts/redactor.js
index ec3659a..41fae96 100755
--- a/app/assets/javascripts/redactor.js
+++ b/app/assets/javascripts/redactor.js
@@ -1,4269 +1,8084 @@
/*
- Redactor v8.2.2
- Updated: January 17, 2013
+ Redactor v10.0.5
+ Updated: November 18, 2014
- http://redactorjs.com/
+ http://imperavi.com/redactor/
- Copyright (c) 2009-2013, Imperavi Inc.
- License: http://redactorjs.com/license/
+ Copyright (c) 2009-2014, Imperavi LLC.
+ License: http://imperavi.com/redactor/license/
Usage: $('#content').redactor();
*/
-var rwindow, rdocument;
-
-if (typeof RELANG === 'undefined')
+(function($)
{
- var RELANG = {};
-}
+ 'use strict';
-var RLANG = {
- html: 'HTML',
- video: 'Insert Video',
- image: 'Insert Image',
- table: 'Table',
- link: 'Link',
- link_insert: 'Insert link',
- unlink: 'Unlink',
- formatting: 'Formatting',
- paragraph: 'Paragraph',
- quote: 'Quote',
- code: 'Code',
- header1: 'Header 1',
- header2: 'Header 2',
- header3: 'Header 3',
- header4: 'Header 4',
- bold: 'Bold',
- italic: 'Italic',
- fontcolor: 'Font Color',
- backcolor: 'Back Color',
- unorderedlist: 'Unordered List',
- orderedlist: 'Ordered List',
- outdent: 'Outdent',
- indent: 'Indent',
- cancel: 'Cancel',
- insert: 'Insert',
- save: 'Save',
- _delete: 'Delete',
- insert_table: 'Insert Table',
- insert_row_above: 'Add Row Above',
- insert_row_below: 'Add Row Below',
- insert_column_left: 'Add Column Left',
- insert_column_right: 'Add Column Right',
- delete_column: 'Delete Column',
- delete_row: 'Delete Row',
- delete_table: 'Delete Table',
- rows: 'Rows',
- columns: 'Columns',
- add_head: 'Add Head',
- delete_head: 'Delete Head',
- title: 'Title',
- image_position: 'Position',
- none: 'None',
- left: 'Left',
- right: 'Right',
- image_web_link: 'Image Web Link',
- text: 'Text',
- mailto: 'Email',
- web: 'URL',
- video_html_code: 'Video Embed Code',
- file: 'Insert File',
- upload: 'Upload',
- download: 'Download',
- choose: 'Choose',
- or_choose: 'Or choose',
- drop_file_here: 'Drop file here',
- align_left: 'Align text to the left',
- align_center: 'Center text',
- align_right: 'Align text to the right',
- align_justify: 'Justify text',
- horizontalrule: 'Insert Horizontal Rule',
- deleted: 'Deleted',
- anchor: 'Anchor',
- link_new_tab: 'Open link in new tab',
- underline: 'Underline',
- alignment: 'Alignment'
-};
+ if (!Function.prototype.bind)
+ {
+ Function.prototype.bind = function(scope)
+ {
+ var fn = this;
+ return function()
+ {
+ return fn.apply(scope);
+ };
+ };
+ }
-(function($){
+ var uuid = 0;
+
+ var reUrlYoutube = /https?:\/\/(?:[0-9A-Z-]+\.)?(?:youtu\.be\/|youtube\.com\S*[^\w\-\s])([\w\-]{11})(?=[^\w\-]|$)(?![?=&+%\w.\-]*(?:['"][^<>]*>|<\/a>))[?=&+%\w.-]*/ig;
+ var reUrlVimeo = /https?:\/\/(www\.)?vimeo.com\/(\d+)($|\/)/;
// Plugin
- jQuery.fn.redactor = function(option)
+ $.fn.redactor = function(options)
{
- return this.each(function()
- {
- var $obj = $(this);
+ var val = [];
+ var args = Array.prototype.slice.call(arguments, 1);
- var data = $obj.data('redactor');
- if (!data)
+ if (typeof options === 'string')
+ {
+ this.each(function()
{
- $obj.data('redactor', (data = new Redactor(this, option)));
- }
- });
- };
+ var instance = $.data(this, 'redactor');
+ var func;
+ if (options.search(/\./) != '-1')
+ {
+ func = options.split('.');
+ if (typeof instance[func[0]] != 'undefined')
+ {
+ func = instance[func[0]][func[1]];
+ }
+ }
+ else
+ {
+ func = instance[options];
+ }
- // Initialization
- var Redactor = function(element, options)
- {
- // Element
- this.$el = $(element);
-
- // Lang
- if (typeof options !== 'undefined' && typeof options.lang !== 'undefined' && options.lang !== 'en' && typeof RELANG[options.lang] !== 'undefined')
+ if (typeof instance !== 'undefined' && $.isFunction(func))
+ {
+ var methodVal = func.apply(instance, args);
+ if (methodVal !== undefined && methodVal !== instance)
+ {
+ val.push(methodVal);
+ }
+ }
+ else
+ {
+ $.error('No such method "' + options + '" for Redactor');
+ }
+ });
+ }
+ else
{
- RLANG = RELANG[options.lang];
+ this.each(function()
+ {
+ $.data(this, 'redactor', {});
+ $.data(this, 'redactor', Redactor(this, options));
+ });
}
- // Options
- this.opts = $.extend({
+ if (val.length === 0) return this;
+ else if (val.length === 1) return val[0];
+ else return val;
- iframe: false,
- css: false, // url
+ };
- lang: 'en',
- direction: 'ltr', // ltr or rtl
+ // Initialization
+ function Redactor(el, options)
+ {
+ return new Redactor.prototype.init(el, options);
+ }
- callback: false, // function
- keyupCallback: false, // function
- keydownCallback: false, // function
- execCommandCallback: false, // function
+ // Functionality
+ $.Redactor = Redactor;
+ $.Redactor.VERSION = '10.0.5';
+ $.Redactor.modules = ['alignment', 'autosave', 'block', 'buffer', 'build', 'button',
+ 'caret', 'clean', 'code', 'core', 'dropdown', 'file', 'focus',
+ 'image', 'indent', 'inline', 'insert', 'keydown', 'keyup',
+ 'lang', 'line', 'link', 'list', 'modal', 'observe', 'paragraphize',
+ 'paste', 'placeholder', 'progress', 'selection', 'shortcuts',
+ 'tabifier', 'tidy', 'toolbar', 'upload', 'utils'];
- plugins: false,
- cleanup: true,
+ $.Redactor.opts = {
- focus: false,
- tabindex: false,
- autoresize: true,
- minHeight: false,
- fixed: false,
- fixedTop: 0, // pixels
- fixedBox: false,
- source: true,
- shortcuts: true,
+ // settings
+ lang: 'en',
+ direction: 'ltr', // ltr or rtl
- mobile: true,
- air: false, // true or toolbar
- wym: false,
+ plugins: false, // array
- convertLinks: true,
- convertDivs: true,
- protocol: 'http://', // for links http or https or ftp or false
+ focus: false,
+ focusEnd: false,
- autosave: false, // false or url
- autosaveCallback: false, // function
- interval: 60, // seconds
+ placeholder: false,
- imageGetJson: false, // url (ex. /folder/images.json ) or false
+ visual: true,
+ tabindex: false,
- imageUpload: false, // url
- imageUploadCallback: false, // function
- imageUploadErrorCallback: false, // function
+ minHeight: false,
+ maxHeight: false,
- fileUpload: false, // url
- fileUploadCallback: false, // function
- fileUploadErrorCallback: false, // function
+ linebreaks: false,
+ replaceDivs: true,
+ paragraphize: true,
+ cleanStyleOnEnter: false,
+ enterKey: true,
- uploadCrossDomain: false,
- uploadFields: false,
+ cleanOnPaste: true,
+ cleanSpaces: true,
+ pastePlainText: false,
- observeImages: true,
- overlay: true, // modal overlay
+ autosave: false, // false or url
+ autosaveName: false,
+ autosaveInterval: 60, // seconds
+ autosaveOnChange: false,
- allowedTags: ["form", "input", "button", "select", "option", "datalist", "output", "textarea", "fieldset", "legend",
- "section", "header", "hgroup", "aside", "footer", "article", "details", "nav", "progress", "time", "canvas",
- "code", "span", "div", "label", "a", "br", "p", "b", "i", "del", "strike", "u",
- "img", "video", "source", "track", "audio", "iframe", "object", "embed", "param", "blockquote",
- "mark", "cite", "small", "ul", "ol", "li", "hr", "dl", "dt", "dd", "sup", "sub",
- "big", "pre", "code", "figure", "figcaption", "strong", "em", "table", "tr", "td",
- "th", "tbody", "thead", "tfoot", "h1", "h2", "h3", "h4", "h5", "h6"],
+ linkTooltip: true,
+ linkProtocol: 'http',
+ linkNofollow: false,
+ linkSize: 50,
- toolbarExternal: false, // ID selector
+ imageEditable: true,
+ imageLink: true,
+ imagePosition: true,
+ imageFloatMargin: '10px',
+ imageResizable: true,
- buttonsCustom: {},
- buttonsAdd: [],
- buttons: ['html', '|', 'formatting', '|', 'bold', 'italic', 'deleted', '|', 'unorderedlist', 'orderedlist', 'outdent', 'indent', '|',
- 'image', 'video', 'file', 'table', 'link', '|',
- 'fontcolor', 'backcolor', '|', 'alignment', '|', 'horizontalrule'], // 'underline', 'alignleft', 'aligncenter', 'alignright', 'justify'
+ imageUpload: false,
+ imageUploadParam: 'file',
- airButtons: ['formatting', '|', 'bold', 'italic', 'deleted', '|', 'unorderedlist', 'orderedlist', 'outdent', 'indent', '|', 'fontcolor', 'backcolor'],
+ uploadImageField: false,
- formattingTags: ['p', 'blockquote', 'pre', 'h1', 'h2', 'h3', 'h4'],
+ dragImageUpload: true,
- activeButtons: ['deleted', 'italic', 'bold', 'underline', 'unorderedlist', 'orderedlist'], // 'alignleft', 'aligncenter', 'alignright', 'justify'
- activeButtonsStates: {
- b: 'bold',
- strong: 'bold',
- i: 'italic',
- em: 'italic',
- del: 'deleted',
- strike: 'deleted',
- ul: 'unorderedlist',
- ol: 'orderedlist',
- u: 'underline'
- },
+ fileUpload: false,
+ fileUploadParam: 'file',
- colors: [
- '#ffffff', '#000000', '#eeece1', '#1f497d', '#4f81bd', '#c0504d', '#9bbb59', '#8064a2', '#4bacc6', '#f79646', '#ffff00',
- '#f2f2f2', '#7f7f7f', '#ddd9c3', '#c6d9f0', '#dbe5f1', '#f2dcdb', '#ebf1dd', '#e5e0ec', '#dbeef3', '#fdeada', '#fff2ca',
- '#d8d8d8', '#595959', '#c4bd97', '#8db3e2', '#b8cce4', '#e5b9b7', '#d7e3bc', '#ccc1d9', '#b7dde8', '#fbd5b5', '#ffe694',
- '#bfbfbf', '#3f3f3f', '#938953', '#548dd4', '#95b3d7', '#d99694', '#c3d69b', '#b2a2c7', '#b7dde8', '#fac08f', '#f2c314',
- '#a5a5a5', '#262626', '#494429', '#17365d', '#366092', '#953734', '#76923c', '#5f497a', '#92cddc', '#e36c09', '#c09100',
- '#7f7f7f', '#0c0c0c', '#1d1b10', '#0f243e', '#244061', '#632423', '#4f6128', '#3f3151', '#31859b', '#974806', '#7f6000'],
+ dragFileUpload: true,
- // private
- emptyHtml: '
',
- buffer: false,
- visual: true,
+ s3: false,
- // modal windows container
- modal_file: String() +
- '',
+ convertLinks: true,
+ convertUrlLinks: true,
+ convertImageLinks: true,
+ convertVideoLinks: true,
- modal_image_edit: String() +
- '' +
- '' +
- '' +
- '' +
- '' +
- '' +
- '' +
- '
' +
- '',
+ preSpaces: 4, // or false
+ tabAsSpaces: false, // true or number of spaces
+ tabFocus: true,
- modal_image: String() +
- '' +
- '
' +
- '
' +
- '
' +
- '' +
- '' +
- '
' +
- '
' +
- '',
+ scrollTarget: false,
- modal_link: String() +
- '' +
- '',
+ toolbar: true,
+ toolbarFixed: true,
+ toolbarFixedTarget: document,
+ toolbarFixedTopOffset: 0, // pixels
+ toolbarExternal: false, // ID selector
+ toolbarOverflow: false,
- modal_table: String() +
- '' +
- '' +
- '' +
- '' +
- '' +
- '
' +
- '',
+ buttonSource: false,
+ buttons: ['html', 'formatting', 'bold', 'italic', 'deleted', 'unorderedlist', 'orderedlist',
+ 'outdent', 'indent', 'image', 'file', 'link', 'alignment', 'horizontalrule'], // + 'underline'
- modal_video: String() +
- '' +
- '' +
- '
'+
- '',
+ buttonsHide: [],
+ buttonsHideOnMobile: [],
- toolbar: {
- html:
- {
- title: RLANG.html,
- func: 'toggle'
- },
- formatting:
- {
- title: RLANG.formatting,
- func: 'show',
- dropdown:
- {
- p:
- {
- title: RLANG.paragraph,
- exec: 'formatblock'
- },
- blockquote:
- {
- title: RLANG.quote,
- exec: 'formatblock',
- className: 'redactor_format_blockquote'
- },
- pre:
- {
- title: RLANG.code,
- exec: 'formatblock',
- className: 'redactor_format_pre'
- },
- h1:
- {
- title: RLANG.header1,
- exec: 'formatblock',
- className: 'redactor_format_h1'
- },
- h2:
- {
- title: RLANG.header2,
- exec: 'formatblock',
- className: 'redactor_format_h2'
- },
- h3:
- {
- title: RLANG.header3,
- exec: 'formatblock',
- className: 'redactor_format_h3'
- },
- h4:
- {
- title: RLANG.header4,
- exec: 'formatblock',
- className: 'redactor_format_h4'
- }
- }
- },
- bold:
- {
- title: RLANG.bold,
- exec: 'bold'
- },
- italic:
- {
- title: RLANG.italic,
- exec: 'italic'
- },
- deleted:
- {
- title: RLANG.deleted,
- exec: 'strikethrough'
- },
- underline:
- {
- title: RLANG.underline,
- exec: 'underline'
- },
- unorderedlist:
- {
- title: '• ' + RLANG.unorderedlist,
- exec: 'insertunorderedlist'
- },
- orderedlist:
- {
- title: '1. ' + RLANG.orderedlist,
- exec: 'insertorderedlist'
- },
- outdent:
- {
- title: '< ' + RLANG.outdent,
- exec: 'outdent'
- },
- indent:
- {
- title: '> ' + RLANG.indent,
- exec: 'indent'
- },
- image:
- {
- title: RLANG.image,
- func: 'showImage'
- },
- video:
- {
- title: RLANG.video,
- func: 'showVideo'
- },
- file:
- {
- title: RLANG.file,
- func: 'showFile'
- },
- table:
- {
- title: RLANG.table,
- func: 'show',
- dropdown:
- {
- insert_table:
- {
- title: RLANG.insert_table,
- func: 'showTable'
- },
- separator_drop1:
- {
- name: 'separator'
- },
- insert_row_above:
- {
- title: RLANG.insert_row_above,
- func: 'insertRowAbove'
- },
- insert_row_below:
- {
- title: RLANG.insert_row_below,
- func: 'insertRowBelow'
- },
- insert_column_left:
- {
- title: RLANG.insert_column_left,
- func: 'insertColumnLeft'
- },
- insert_column_right:
- {
- title: RLANG.insert_column_right,
- func: 'insertColumnRight'
- },
- separator_drop2:
- {
- name: 'separator'
- },
- add_head:
- {
- title: RLANG.add_head,
- func: 'addHead'
- },
- delete_head:
- {
- title: RLANG.delete_head,
- func: 'deleteHead'
- },
- separator_drop3:
- {
- name: 'separator'
- },
- delete_column:
- {
- title: RLANG.delete_column,
- func: 'deleteColumn'
- },
- delete_row:
- {
- title: RLANG.delete_row,
- func: 'deleteRow'
- },
- delete_table:
- {
- title: RLANG.delete_table,
- func: 'deleteTable'
- }
- }
- },
- link:
- {
- title: RLANG.link,
- func: 'show',
- dropdown:
- {
- link:
- {
- title: RLANG.link_insert,
- func: 'showLink'
- },
- unlink:
- {
- title: RLANG.unlink,
- exec: 'unlink'
- }
- }
- },
- fontcolor:
- {
- title: RLANG.fontcolor,
- func: 'show'
- },
- backcolor:
- {
- title: RLANG.backcolor,
- func: 'show'
- },
- alignment:
- {
- title: RLANG.alignment,
- func: 'show',
- dropdown:
- {
- alignleft:
- {
- title: RLANG.align_left,
- exec: 'JustifyLeft'
- },
- aligncenter:
- {
- title: RLANG.align_center,
- exec: 'JustifyCenter'
- },
- alignright:
- {
- title: RLANG.align_right,
- exec: 'JustifyRight'
- },
- justify:
- {
- title: RLANG.align_justify,
- exec: 'JustifyFull'
- }
- }
- },
- alignleft:
- {
- exec: 'JustifyLeft',
- title: RLANG.align_left
- },
- aligncenter:
- {
- exec: 'JustifyCenter',
- title: RLANG.align_center
- },
- alignright:
- {
- exec: 'JustifyRight',
- title: RLANG.align_right
- },
- justify:
- {
- exec: 'JustifyFull',
- title: RLANG.align_justify
- },
- horizontalrule:
- {
- exec: 'inserthorizontalrule',
- title: RLANG.horizontalrule
- }
+ formatting: ['p', 'blockquote', 'pre', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'],
+ formattingAdd: false,
+
+ tabifier: true,
+
+ deniedTags: ['html', 'head', 'link', 'body', 'meta', 'script', 'style', 'applet'],
+ allowedTags: false, // or array
+
+ removeComments: false,
+ replaceTags: [
+ ['strike', 'del']
+ ],
+ replaceStyles: [
+ ['font-weight:\\s?bold', "strong"],
+ ['font-style:\\s?italic', "em"],
+ ['text-decoration:\\s?underline', "u"],
+ ['text-decoration:\\s?line-through', 'del']
+ ],
+ removeDataAttr: false,
+
+ removeAttr: false, // or multi array
+ allowedAttr: false, // or multi array
+
+ removeWithoutAttr: ['span'], // or false
+ removeEmpty: ['p'], // or false;
+
+ activeButtons: ['deleted', 'italic', 'bold', 'underline', 'unorderedlist', 'orderedlist',
+ 'alignleft', 'aligncenter', 'alignright', 'justify'],
+ activeButtonsStates: {
+ b: 'bold',
+ strong: 'bold',
+ i: 'italic',
+ em: 'italic',
+ del: 'deleted',
+ strike: 'deleted',
+ ul: 'unorderedlist',
+ ol: 'orderedlist',
+ u: 'underline'
+ },
+
+ shortcuts: {
+ 'ctrl+shift+m, meta+shift+m': { func: 'inline.removeFormat' },
+ 'ctrl+b, meta+b': { func: 'inline.format', params: ['bold'] },
+ 'ctrl+i, meta+i': { func: 'inline.format', params: ['italic'] },
+ 'ctrl+h, meta+h': { func: 'inline.format', params: ['superscript'] },
+ 'ctrl+l, meta+l': { func: 'inline.format', params: ['subscript'] },
+ 'ctrl+k, meta+k': { func: 'link.show' },
+ 'ctrl+shift+7': { func: 'list.toggle', params: ['orderedlist'] },
+ 'ctrl+shift+8': { func: 'list.toggle', params: ['unorderedlist'] }
+ },
+ shortcutsAdd: false,
+
+ // private
+ buffer: [],
+ rebuffer: [],
+ emptyHtml: '
',
+ invisibleSpace: '',
+ imageTypes: ['image/png', 'image/jpeg', 'image/gif'],
+ indentValue: 20,
+ verifiedTags: ['a', 'img', 'b', 'strong', 'sub', 'sup', 'i', 'em', 'u', 'small', 'strike', 'del', 'cite', 'ul', 'ol', 'li'], // and for span tag special rule
+ inlineTags: ['strong', 'b', 'u', 'em', 'i', 'code', 'del', 'ins', 'samp', 'kbd', 'sup', 'sub', 'mark', 'var', 'cite', 'small'],
+ alignmentTags: ['P', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'DL', 'DT', 'DD', 'DIV', 'TD', 'BLOCKQUOTE', 'OUTPUT', 'FIGCAPTION', 'ADDRESS', 'SECTION', 'HEADER', 'FOOTER', 'ASIDE', 'ARTICLE'],
+ blockLevelElements: ['PRE', 'UL', 'OL', 'LI'],
+
+
+ // lang
+ langs: {
+ en: {
+ html: 'HTML',
+ video: 'Insert Video',
+ image: 'Insert Image',
+ table: 'Table',
+ link: 'Link',
+ link_insert: 'Insert link',
+ link_edit: 'Edit link',
+ unlink: 'Unlink',
+ formatting: 'Formatting',
+ paragraph: 'Normal text',
+ quote: 'Quote',
+ code: 'Code',
+ header1: 'Header 1',
+ header2: 'Header 2',
+ header3: 'Header 3',
+ header4: 'Header 4',
+ header5: 'Header 5',
+ bold: 'Bold',
+ italic: 'Italic',
+ fontcolor: 'Font Color',
+ backcolor: 'Back Color',
+ unorderedlist: 'Unordered List',
+ orderedlist: 'Ordered List',
+ outdent: 'Outdent',
+ indent: 'Indent',
+ cancel: 'Cancel',
+ insert: 'Insert',
+ save: 'Save',
+ _delete: 'Delete',
+ insert_table: 'Insert Table',
+ insert_row_above: 'Add Row Above',
+ insert_row_below: 'Add Row Below',
+ insert_column_left: 'Add Column Left',
+ insert_column_right: 'Add Column Right',
+ delete_column: 'Delete Column',
+ delete_row: 'Delete Row',
+ delete_table: 'Delete Table',
+ rows: 'Rows',
+ columns: 'Columns',
+ add_head: 'Add Head',
+ delete_head: 'Delete Head',
+ title: 'Title',
+ image_position: 'Position',
+ none: 'None',
+ left: 'Left',
+ right: 'Right',
+ center: 'Center',
+ image_web_link: 'Image Web Link',
+ text: 'Text',
+ mailto: 'Email',
+ web: 'URL',
+ video_html_code: 'Video Embed Code or Youtube/Vimeo Link',
+ file: 'Insert File',
+ upload: 'Upload',
+ download: 'Download',
+ choose: 'Choose',
+ or_choose: 'Or choose',
+ drop_file_here: 'Drop file here',
+ align_left: 'Align text to the left',
+ align_center: 'Center text',
+ align_right: 'Align text to the right',
+ align_justify: 'Justify text',
+ horizontalrule: 'Insert Horizontal Rule',
+ deleted: 'Deleted',
+ anchor: 'Anchor',
+ link_new_tab: 'Open link in new tab',
+ underline: 'Underline',
+ alignment: 'Alignment',
+ filename: 'Name (optional)',
+ edit: 'Edit'
}
-
-
- }, options, this.$el.data());
-
- this.dropdowns = [];
-
- // Init
- this.init();
+ }
};
// Functionality
- Redactor.prototype = {
+ Redactor.fn = $.Redactor.prototype = {
+ keyCode: {
+ BACKSPACE: 8,
+ DELETE: 46,
+ DOWN: 40,
+ ENTER: 13,
+ SPACE: 32,
+ ESC: 27,
+ TAB: 9,
+ CTRL: 17,
+ META: 91,
+ SHIFT: 16,
+ ALT: 18,
+ LEFT: 37,
+ LEFT_WIN: 91
+ },
// Initialization
- init: function()
+ init: function(el, options)
{
- // get dimensions
- this.height = this.$el.css('height');
- this.width = this.$el.css('width');
+ this.$element = $(el);
+ this.uuid = uuid++;
- rdocument = this.document = document;
- rwindow = this.window = window;
+ // if paste event detected = true
+ this.rtePaste = false;
+ this.$pasteBox = false;
- // mobile
- if (this.opts.mobile === false && this.isMobile())
+ this.loadOptions(options);
+ this.loadModules();
+
+ // formatting storage
+ this.formatting = {};
+
+ // block level tags
+ $.merge(this.opts.blockLevelElements, this.opts.alignmentTags);
+ this.reIsBlock = new RegExp('^(' + this.opts.blockLevelElements.join('|' ) + ')$', 'i');
+
+ // setup allowed and denied tags
+ this.tidy.setupAllowed();
+
+ // load lang
+ this.lang.load();
+
+ // extend shortcuts
+ $.extend(this.opts.shortcuts, this.opts.shortcutsAdd);
+
+ // start callback
+ this.core.setCallback('start');
+
+ // build
+ this.start = true;
+ this.build.run();
+ },
+
+ loadOptions: function(options)
+ {
+ this.opts = $.extend(
+ {},
+ $.extend(true, {}, $.Redactor.opts),
+ this.$element.data(),
+ options
+ );
+ },
+ getModuleMethods: function(object)
+ {
+ return Object.getOwnPropertyNames(object).filter(function(property)
{
- this.build(true);
- return false;
+ return typeof object[property] == 'function';
+ });
+ },
+ loadModules: function()
+ {
+ var len = $.Redactor.modules.length;
+ for (var i = 0; i < len; i++)
+ {
+ this.bindModuleMethods($.Redactor.modules[i]);
}
+ },
+ bindModuleMethods: function(module)
+ {
+ if (typeof this[module] == 'undefined') return;
- // iframe
- if (this.opts.iframe)
- {
- this.opts.autoresize = false;
- }
+ // init module
+ this[module] = this[module]();
- // extend buttons
- if (this.opts.air)
+ var methods = this.getModuleMethods(this[module]);
+ var len = methods.length;
+
+ // bind methods
+ for (var z = 0; z < len; z++)
{
- this.opts.buttons = this.opts.airButtons;
+ this[module][methods[z]] = this[module][methods[z]].bind(this);
}
- else if (this.opts.toolbar !== false)
- {
- if (this.opts.source === false)
+ },
+
+ alignment: function()
+ {
+ return {
+ left: function()
{
- var index = this.opts.buttons.indexOf('html');
- var next = this.opts.buttons[index+1];
- this.opts.buttons.splice(index, 1);
- if (typeof next !== 'undefined' && next === '|')
+ this.alignment.set('');
+ },
+ right: function()
+ {
+ this.alignment.set('right');
+ },
+ center: function()
+ {
+ this.alignment.set('center');
+ },
+ justify: function()
+ {
+ this.alignment.set('justify');
+ },
+ set: function(type)
+ {
+ if (!this.utils.browser('msie')) this.$editor.focus();
+
+ this.buffer.set();
+ this.selection.save();
+
+ this.alignment.blocks = this.selection.getBlocks();
+ if (this.opts.linebreaks && this.alignment.blocks[0] === false)
{
- this.opts.buttons.splice(index, 1);
+ this.alignment.setText(type);
+ }
+ else
+ {
+ this.alignment.setBlocks(type);
+ }
+
+ this.selection.restore();
+ this.code.sync();
+ },
+ setText: function(type)
+ {
+ var wrapper = this.selection.wrap('div');
+ $(wrapper).attr('data-tagblock', 'redactor');
+ $(wrapper).css('text-align', type);
+ },
+ setBlocks: function(type)
+ {
+ $.each(this.alignment.blocks, $.proxy(function(i, el)
+ {
+ var $el = this.utils.getAlignmentElement(el);
+
+ if (!$el) return;
+
+ if (type === '' && typeof($el.data('tagblock')) !== 'undefined')
+ {
+ $el.replaceWith($el.html());
+ }
+ else
+ {
+ $el.css('text-align', type);
+ this.utils.removeEmptyAttr($el, 'style');
+ }
+
+
+ }, this));
+ }
+ };
+ },
+ autosave: function()
+ {
+ return {
+ enable: function()
+ {
+ if (!this.opts.autosave) return;
+
+ this.autosave.html = false;
+ this.autosave.name = (this.opts.autosaveName) ? this.opts.autosaveName : this.$textarea.attr('name');
+
+ if (!this.opts.autosaveOnChange)
+ {
+ this.autosaveInterval = setInterval($.proxy(this.autosave.load, this), this.opts.autosaveInterval * 1000);
+ }
+ },
+ onChange: function()
+ {
+ if (!this.opts.autosaveOnChange) return;
+
+ this.autosave.load();
+ },
+ load: function()
+ {
+ var html = this.code.get();
+ if (this.autosave.html === html) return;
+ if (this.utils.isEmpty(html)) return;
+
+ $.ajax({
+ url: this.opts.autosave,
+ type: 'post',
+ data: 'name=' + this.autosave.name + '&' + this.autosave.name + '=' + escape(encodeURIComponent(html)),
+ success: $.proxy(function(data)
+ {
+ this.autosave.success(data, html);
+
+ }, this)
+ });
+ },
+ success: function(data, html)
+ {
+ var json;
+ try
+ {
+ json = $.parseJSON(data);
+ }
+ catch(e)
+ {
+ //data has already been parsed
+ json = data;
+ }
+
+ var callbackName = (typeof json.error == 'undefined') ? 'autosave' : 'autosaveError';
+
+ this.core.setCallback(callbackName, this.autosave.name, json);
+ this.autosave.html = html;
+ },
+ disable: function()
+ {
+ clearInterval(this.autosaveInterval);
+ }
+ };
+ },
+ block: function()
+ {
+ return {
+ formatting: function(name)
+ {
+ var type, value;
+
+ if (typeof this.formatting[name].data != 'undefined') type = 'data';
+ else if (typeof this.formatting[name].attr != 'undefined') type = 'attr';
+ else if (typeof this.formatting[name].class != 'undefined') type = 'class';
+
+ if (type) value = this.formatting[name][type];
+
+ this.block.format(this.formatting[name].tag, type, value);
+
+ },
+ format: function(tag, type, value)
+ {
+ if (tag == 'quote') tag = 'blockquote';
+
+ var formatTags = ['p', 'pre', 'blockquote', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'];
+ if ($.inArray(tag, formatTags) == -1) return;
+
+ this.block.isRemoveInline = (tag == 'pre' || tag.search(/h[1-6]/i) != -1);
+
+ // focus
+ if (!this.utils.browser('msie')) this.$editor.focus();
+
+ this.block.blocks = this.selection.getBlocks();
+
+ this.block.blocksSize = this.block.blocks.length;
+ this.block.type = type;
+ this.block.value = value;
+
+ this.buffer.set();
+ this.selection.save();
+
+ this.block.set(tag);
+
+ this.selection.restore();
+ this.code.sync();
+
+ },
+ set: function(tag)
+ {
+ this.selection.get();
+ this.block.containerTag = this.range.commonAncestorContainer.tagName;
+
+ if (this.range.collapsed)
+ {
+ this.block.setCollapsed(tag);
+ }
+ else
+ {
+ this.block.setMultiple(tag);
+ }
+ },
+ setCollapsed: function(tag)
+ {
+ var block = this.block.blocks[0];
+ if (block === false) return;
+
+ if (block.tagName == 'LI')
+ {
+ if (tag != 'blockquote') return;
+
+ this.block.formatListToBlockquote();
+ return;
+ }
+
+ var isContainerTable = (this.block.containerTag == 'TD' || this.block.containerTag == 'TH');
+ if (isContainerTable && !this.opts.linebreaks)
+ {
+
+ document.execCommand('formatblock', false, '<' + tag + '>');
+
+ block = this.selection.getBlock();
+ this.block.toggle($(block));
+
+ }
+ else if (block.tagName.toLowerCase() != tag)
+ {
+ if (this.opts.linebreaks && tag == 'p')
+ {
+ $(block).prepend('
').append('
');
+ this.utils.replaceWithContents(block);
+ }
+ else
+ {
+ var $formatted = this.utils.replaceToTag(block, tag);
+
+ this.block.toggle($formatted);
+
+ if (tag != 'p' && tag != 'blockquote') $formatted.find('img').remove();
+ if (this.block.isRemoveInline) this.utils.removeInlineTags($formatted);
+ if (tag == 'p' || this.block.headTag) $formatted.find('p').contents().unwrap();
+
+ this.block.formatTableWrapping($formatted);
+ }
+ }
+ else if (tag == 'blockquote' && block.tagName.toLowerCase() == tag)
+ {
+ // blockquote off
+ if (this.opts.linebreaks)
+ {
+ $(block).prepend('
').append('
');
+ this.utils.replaceWithContents(block);
+ }
+ else
+ {
+ var $el = this.utils.replaceToTag(block, 'p');
+ this.block.toggle($el);
+ }
+ }
+ else if (block.tagName.toLowerCase() == tag)
+ {
+ this.block.toggle($(block));
+ }
+
+ },
+ setMultiple: function(tag)
+ {
+ var block = this.block.blocks[0];
+ var isContainerTable = (this.block.containerTag == 'TD' || this.block.containerTag == 'TH');
+
+ if (block !== false && this.block.blocksSize === 1)
+ {
+ if (block.tagName.toLowerCase() == tag && tag == 'blockquote')
+ {
+ // blockquote off
+ if (this.opts.linebreaks)
+ {
+ $(block).prepend('
').append('
');
+ this.utils.replaceWithContents(block);
+ }
+ else
+ {
+ var $el = this.utils.replaceToTag(block, 'p');
+ this.block.toggle($el);
+ }
+ }
+ else if (block.tagName == 'LI')
+ {
+ if (tag != 'blockquote') return;
+
+ this.block.formatListToBlockquote();
+ }
+ else if (this.block.containerTag == 'BLOCKQUOTE')
+ {
+ this.block.formatBlockquote(tag);
+ }
+ else if (this.opts.linebreaks && ((isContainerTable) || (this.range.commonAncestorContainer != block)))
+ {
+ this.block.formatWrap(tag);
+ }
+ else
+ {
+ if (this.opts.linebreaks && tag == 'p')
+ {
+ $(block).prepend('
').append('
');
+ this.utils.replaceWithContents(block);
+ }
+ else if (block.tagName === 'TD')
+ {
+ this.block.formatWrap(tag);
+ }
+ else
+ {
+ var $formatted = this.utils.replaceToTag(block, tag);
+
+ this.block.toggle($formatted);
+
+ if (this.block.isRemoveInline) this.utils.removeInlineTags($formatted);
+ if (tag == 'p' || this.block.headTag) $formatted.find('p').contents().unwrap();
+ }
+ }
+ }
+ else
+ {
+ if (this.opts.linebreaks || tag != 'p')
+ {
+ if (tag == 'blockquote')
+ {
+ var count = 0;
+ for (var i = 0; i < this.block.blocksSize; i++)
+ {
+ if (this.block.blocks[i].tagName == 'BLOCKQUOTE') count++;
+ }
+
+ // only blockquote selected
+ if (count == this.block.blocksSize)
+ {
+ $.each(this.block.blocks, $.proxy(function(i,s)
+ {
+ if (this.opts.linebreaks)
+ {
+ $(s).prepend('
').append('
');
+ this.utils.replaceWithContents(s);
+ }
+ else
+ {
+ this.utils.replaceToTag(s, 'p');
+ }
+
+ }, this));
+
+ return;
+ }
+
+ }
+
+ this.block.formatWrap(tag);
+ }
+ else
+ {
+ var classSize = 0;
+ var toggleType = false;
+ if (this.block.type == 'class')
+ {
+ toggleType = 'toggle';
+ classSize = $(this.block.blocks).filter('.' + this.block.value).size();
+
+ if (this.block.blocksSize == classSize) toggleType = 'toggle';
+ else if (this.block.blocksSize > classSize) toggleType = 'set';
+ else if (classSize === 0) toggleType = 'set';
+
+ }
+
+ var exceptTags = ['ul', 'ol', 'li', 'td', 'th', 'dl', 'dt', 'dd'];
+ $.each(this.block.blocks, $.proxy(function(i,s)
+ {
+ if ($.inArray(s.tagName.toLowerCase(), exceptTags) != -1) return;
+
+ var $formatted = this.utils.replaceToTag(s, tag);
+
+ if (toggleType)
+ {
+ if (toggleType == 'toggle') this.block.toggle($formatted);
+ else if (toggleType == 'remove') this.block.remove($formatted);
+ else if (toggleType == 'set') this.block.setForce($formatted);
+ }
+ else this.block.toggle($formatted);
+
+ if (tag != 'p' && tag != 'blockquote') $formatted.find('img').remove();
+ if (this.block.isRemoveInline) this.utils.removeInlineTags($formatted);
+ if (tag == 'p' || this.block.headTag) $formatted.find('p').contents().unwrap();
+
+
+ }, this));
+ }
+ }
+ },
+ setForce: function($el)
+ {
+ if (this.block.type == 'class')
+ {
+ $el.addClass(this.block.value);
+ return;
+ }
+ else if (this.block.type == 'attr' || this.block.type == 'data')
+ {
+ $el.attr(this.block.value.name, this.block.value.value);
+ return;
+ }
+ },
+ toggle: function($el)
+ {
+ if (this.block.type == 'class')
+ {
+ $el.toggleClass(this.block.value);
+ return;
+ }
+ else if (this.block.type == 'attr' || this.block.type == 'data')
+ {
+ if ($el.attr(this.block.value.name) == this.block.value.value)
+ {
+ $el.removeAttr(this.block.value.name);
+ }
+ else
+ {
+ $el.attr(this.block.value.name, this.block.value.value);
+ }
+
+ return;
+ }
+ else
+ {
+ $el.removeAttr('style class');
+ return;
+ }
+ },
+ remove: function($el)
+ {
+ $el.removeClass(this.block.value);
+ },
+ formatListToBlockquote: function()
+ {
+ var block = $(this.block.blocks[0]).closest('ul, ol');
+
+ $(block).find('ul, ol').contents().unwrap();
+ $(block).find('li').append($('
')).contents().unwrap();
+
+ var $el = this.utils.replaceToTag(block, 'blockquote');
+ this.block.toggle($el);
+ },
+ formatBlockquote: function(tag)
+ {
+ document.execCommand('outdent');
+ document.execCommand('formatblock', false, tag);
+
+ this.clean.clearUnverified();
+ this.$editor.find('p:empty').remove();
+
+ var formatted = this.selection.getBlock();
+
+ if (tag != 'p')
+ {
+ $(formatted).find('img').remove();
+ }
+
+ if (!this.opts.linebreaks)
+ {
+ this.block.toggle($(formatted));
+ }
+
+ this.$editor.find('ul, ol, tr, blockquote, p').each($.proxy(this.utils.removeEmpty, this));
+
+ if (this.opts.linebreaks && tag == 'p')
+ {
+ this.utils.replaceWithContents(formatted);
+ }
+
+ },
+ formatWrap: function(tag)
+ {
+ if (this.block.containerTag == 'UL' || this.block.containerTag == 'OL')
+ {
+ if (tag == 'blockquote')
+ {
+ this.block.formatListToBlockquote();
+ }
+ else
+ {
+ return;
+ }
+ }
+
+ var formatted = this.selection.wrap(tag);
+ if (formatted === false) return;
+
+ var $formatted = $(formatted);
+
+ this.block.formatTableWrapping($formatted);
+
+ var $elements = $formatted.find(this.opts.blockLevelElements.join(',') + ', td, table, thead, tbody, tfoot, th, tr');
+
+ if ((this.opts.linebreaks && tag == 'p') || tag == 'pre' || tag == 'blockquote')
+ {
+ $elements.append('
');
+ }
+
+ $elements.contents().unwrap();
+
+ if (tag != 'p' && tag != 'blockquote') $formatted.find('img').remove();
+
+ $.each(this.block.blocks, $.proxy(this.utils.removeEmpty, this));
+
+ $formatted.append(this.selection.getMarker(2));
+
+ if (!this.opts.linebreaks)
+ {
+ this.block.toggle($formatted);
+ }
+
+ this.$editor.find('ul, ol, tr, blockquote, p').each($.proxy(this.utils.removeEmpty, this));
+ $formatted.find('blockquote:empty').remove();
+
+ if (this.block.isRemoveInline)
+ {
+ this.utils.removeInlineTags($formatted);
+ }
+
+ if (this.opts.linebreaks && tag == 'p')
+ {
+ this.utils.replaceWithContents($formatted);
+ }
+
+ },
+ formatTableWrapping: function($formatted)
+ {
+ if ($formatted.closest('table').size() === 0) return;
+
+ if ($formatted.closest('tr').size() === 0) $formatted.wrap('');
+ if ($formatted.closest('td').size() === 0 && $formatted.closest('th').size() === 0)
+ {
+ $formatted.wrap('');
+ }
+ },
+ removeData: function(name, value)
+ {
+ var blocks = this.selection.getBlocks();
+ $(blocks).removeAttr('data-' + name);
+
+ this.code.sync();
+ },
+ setData: function(name, value)
+ {
+ var blocks = this.selection.getBlocks();
+ $(blocks).attr('data-' + name, value);
+
+ this.code.sync();
+ },
+ toggleData: function(name, value)
+ {
+ var blocks = this.selection.getBlocks();
+ $.each(blocks, function()
+ {
+ if ($(this).attr('data-' + name))
+ {
+ $(this).removeAttr('data-' + name);
+ }
+ else
+ {
+ $(this).attr('data-' + name, value);
+ }
+ });
+ },
+ removeAttr: function(attr, value)
+ {
+ var blocks = this.selection.getBlocks();
+ $(blocks).removeAttr(attr);
+
+ this.code.sync();
+ },
+ setAttr: function(attr, value)
+ {
+ var blocks = this.selection.getBlocks();
+ $(blocks).attr(attr, value);
+
+ this.code.sync();
+ },
+ toggleAttr: function(attr, value)
+ {
+ var blocks = this.selection.getBlocks();
+ $.each(blocks, function()
+ {
+ if ($(this).attr(name))
+ {
+ $(this).removeAttr(name);
+ }
+ else
+ {
+ $(this).attr(name, value);
+ }
+ });
+ },
+ removeClass: function(className)
+ {
+ var blocks = this.selection.getBlocks();
+ $(blocks).removeClass(className);
+
+ this.utils.removeEmptyAttr(blocks, 'class');
+
+ this.code.sync();
+ },
+ setClass: function(className)
+ {
+ var blocks = this.selection.getBlocks();
+ $(blocks).addClass(className);
+
+ this.code.sync();
+ },
+ toggleClass: function(className)
+ {
+ var blocks = this.selection.getBlocks();
+ $(blocks).toggleClass(className);
+
+ this.code.sync();
+ }
+ };
+ },
+ buffer: function()
+ {
+ return {
+ set: function(type)
+ {
+ if (typeof type == 'undefined' || type == 'undo')
+ {
+ this.buffer.setUndo();
+ }
+ else
+ {
+ this.buffer.setRedo();
+ }
+ },
+ setUndo: function()
+ {
+ this.selection.save();
+ this.opts.buffer.push(this.$editor.html());
+ this.selection.restore();
+ },
+ setRedo: function()
+ {
+ this.selection.save();
+ this.opts.rebuffer.push(this.$editor.html());
+ this.selection.restore();
+ },
+ getUndo: function()
+ {
+ this.$editor.html(this.opts.buffer.pop());
+ },
+ getRedo: function()
+ {
+ this.$editor.html(this.opts.rebuffer.pop());
+ },
+ add: function()
+ {
+ this.opts.buffer.push(this.$editor.html());
+ },
+ undo: function()
+ {
+ if (this.opts.buffer.length === 0) return;
+
+ this.buffer.set('redo');
+ this.buffer.getUndo();
+
+ this.selection.restore();
+
+ setTimeout($.proxy(this.observe.load, this), 50);
+ },
+ redo: function()
+ {
+ if (this.opts.rebuffer.length === 0) return;
+
+ this.buffer.set('undo');
+ this.buffer.getRedo();
+
+ this.selection.restore();
+
+ setTimeout($.proxy(this.observe.load, this), 50);
+ }
+ };
+ },
+ build: function()
+ {
+ return {
+ run: function()
+ {
+
+ this.build.createContainerBox();
+ this.build.loadContent();
+ this.build.loadEditor();
+ this.build.enableEditor();
+ this.build.setCodeAndCall();
+
+ },
+ isTextarea: function()
+ {
+ return (this.$element[0].tagName === 'TEXTAREA');
+ },
+ createContainerBox: function()
+ {
+ this.$box = $('');
+ },
+ createTextarea: function()
+ {
+ this.$textarea = $('').attr('name', this.build.getTextareaName());
+ },
+ getTextareaName: function()
+ {
+ var name = this.$element.attr('id');
+ if (typeof(name) == 'undefined')
+ {
+ name = 'content-' + this.uuid;
+ }
+
+ return name;
+ },
+ loadContent: function()
+ {
+ var func = (this.build.isTextarea()) ? 'val' : 'html';
+ this.content = $.trim(this.$element[func]());
+ },
+ enableEditor: function()
+ {
+ this.$editor.attr({ 'contenteditable': true, 'dir': this.opts.direction });
+ },
+ loadEditor: function()
+ {
+ var func = (this.build.isTextarea()) ? 'fromTextarea' : 'fromElement';
+ this.build[func]();
+ },
+ fromTextarea: function()
+ {
+ this.$editor = $('');
+ this.$textarea = this.$element;
+ this.$box.insertAfter(this.$element).append(this.$editor).append(this.$element);
+ this.$editor.addClass('redactor-editor');
+
+ this.$element.hide();
+ },
+ fromElement: function()
+ {
+ this.$editor = this.$element;
+ this.build.createTextarea();
+ this.$box.insertAfter(this.$editor).append(this.$editor).append(this.$textarea);
+ this.$editor.addClass('redactor-editor');
+
+ this.$textarea.hide();
+ },
+ setCodeAndCall: function()
+ {
+ // set code
+ this.code.set(this.content);
+
+ this.build.setOptions();
+ this.build.callEditor();
+
+ // code mode
+ if (!this.opts.visual)
+ {
+ setTimeout($.proxy(this.code.showCode, this), 200);
+ }
+ },
+ callEditor: function()
+ {
+ this.build.disableMozillaEditing();
+ this.build.setEvents();
+ this.build.setHelpers();
+
+ // load toolbar
+ if (this.opts.toolbar)
+ {
+ this.opts.toolbar = this.toolbar.init();
+ this.toolbar.build();
+ }
+
+ // modal templates init
+ this.modal.loadTemplates();
+
+ // plugins
+ this.build.plugins();
+
+ // observers
+ setTimeout($.proxy(this.observe.load, this), 4);
+
+ // init callback
+ this.core.setCallback('init');
+ },
+ setOptions: function()
+ {
+ // textarea direction
+ $(this.$textarea).attr('dir', this.opts.direction);
+
+ if (this.opts.linebreaks) this.$editor.addClass('redactor-linebreaks');
+
+ if (this.opts.tabindex) this.$editor.attr('tabindex', this.opts.tabindex);
+
+ if (this.opts.minHeight) this.$editor.css('minHeight', this.opts.minHeight);
+ if (this.opts.maxHeight) this.$editor.css('maxHeight', this.opts.maxHeight);
+
+ },
+ setEvents: function()
+ {
+ // drop
+ this.$editor.on('drop.redactor', $.proxy(function(e)
+ {
+ e = e.originalEvent || e;
+
+ if (window.FormData === undefined || !e.dataTransfer) return true;
+
+ var length = e.dataTransfer.files.length;
+ if (length === 0)
+ {
+ this.code.sync();
+ setTimeout($.proxy(this.clean.clearUnverified, this), 1);
+ this.core.setCallback('drop', e);
+
+ return true;
+ }
+ else
+ {
+ e.preventDefault();
+
+ if (this.opts.dragImageUpload || this.opts.dragFileUpload)
+ {
+ var files = e.dataTransfer.files;
+ this.upload.directUpload(files[0], e);
+ }
+ }
+
+ setTimeout($.proxy(this.clean.clearUnverified, this), 1);
+
+ this.core.setCallback('drop', e);
+
+ }, this));
+
+
+ // click
+ this.$editor.on('click.redactor', $.proxy(function(e)
+ {
+ var type = 'click';
+ if ((this.core.getEvent() == 'click' || this.core.getEvent() == 'arrow'))
+ {
+ type = false;
+ }
+
+ this.core.addEvent(type);
+ this.utils.disableSelectAll();
+ this.core.setCallback('click', e);
+
+ }, this));
+
+ // paste
+ this.$editor.on('paste.redactor', $.proxy(this.paste.init, this));
+
+ // keydown
+ this.$editor.on('keydown.redactor', $.proxy(this.keydown.init, this));
+
+ // keyup
+ this.$editor.on('keyup.redactor', $.proxy(this.keyup.init, this));
+
+ // textarea keydown
+ if ($.isFunction(this.opts.codeKeydownCallback))
+ {
+ this.$textarea.on('keydown.redactor-textarea', $.proxy(this.opts.codeKeydownCallback, this));
+ }
+
+ // textarea keyup
+ if ($.isFunction(this.opts.codeKeyupCallback))
+ {
+ this.$textarea.on('keyup.redactor-textarea', $.proxy(this.opts.codeKeyupCallback, this));
+ }
+
+ // focus
+ if ($.isFunction(this.opts.focusCallback))
+ {
+ this.$editor.on('focus.redactor', $.proxy(this.opts.focusCallback, this));
+ }
+
+ var clickedElement;
+ $(document).on('mousedown', function(e) {
+ clickedElement = $(e.target);
+ });
+
+ // blur
+ this.$editor.on('blur.redactor', $.proxy(function(e)
+ {
+ if (this.rtePaste) return;
+
+ var $el = $(clickedElement);
+ if (!$el.hasClass('redactor-toolbar, redactor-dropdown') && !$el.is('#redactor-modal') && $el.parents('.redactor-toolbar, .redactor-dropdown, #redactor-modal').size() === 0)
+ {
+ this.utils.disableSelectAll();
+ if ($.isFunction(this.opts.blurCallback)) this.core.setCallback('blur', e);
+ }
+ }, this));
+ },
+ setHelpers: function()
+ {
+ // autosave
+ this.autosave.enable();
+
+ // placeholder
+ this.placeholder.enable();
+
+ // focus
+ if (this.opts.focus) setTimeout($.proxy(this.focus.setStart, this), 100);
+ if (this.opts.focusEnd) setTimeout($.proxy(this.focus.setEnd, this), 100);
+
+ },
+ plugins: function()
+ {
+ if (!this.opts.plugins) return;
+ if (!RedactorPlugins) return;
+
+ $.each(this.opts.plugins, $.proxy(function(i, s)
+ {
+ if (typeof RedactorPlugins[s] === 'undefined') return;
+
+ if ($.inArray(s, $.Redactor.modules) !== -1)
+ {
+ $.error('Plugin name "' + s + '" matches the name of the Redactor\'s module.');
+ return;
+ }
+
+ if (!$.isFunction(RedactorPlugins[s])) return;
+
+ this[s] = RedactorPlugins[s]();
+
+ var methods = this.getModuleMethods(this[s]);
+ var len = methods.length;
+
+ // bind methods
+ for (var z = 0; z < len; z++)
+ {
+ this[s][methods[z]] = this[s][methods[z]].bind(this);
+ }
+
+ if ($.isFunction(this[s].init)) this[s].init();
+
+
+ }, this));
+
+
+ },
+ disableMozillaEditing: function()
+ {
+ if (!this.utils.browser('mozilla')) return;
+
+ // FF fix
+ try {
+ document.execCommand('enableObjectResizing', false, false);
+ document.execCommand('enableInlineTableEditing', false, false);
+ } catch (e) {}
+ }
+ };
+ },
+ button: function()
+ {
+ return {
+ build: function(btnName, btnObject)
+ {
+ var $button = $('').attr('tabindex', '-1');
+
+ if (btnObject.func || btnObject.command || btnObject.dropdown)
+ {
+ $button.on('touchstart click', $.proxy(function(e)
+ {
+ if ($button.hasClass('redactor-button-disabled')) return false;
+
+ var type = 'func';
+ var callback = btnObject.func;
+ if (btnObject.command)
+ {
+ type = 'command';
+ callback = btnObject.command;
+ }
+ else if (btnObject.dropdown)
+ {
+ type = 'dropdown';
+ callback = false;
+ }
+
+ this.button.onClick(e, btnName, type, callback);
+
+ }, this));
+ }
+
+ // dropdown
+ if (btnObject.dropdown)
+ {
+ var $dropdown = $('');
+ $button.data('dropdown', $dropdown);
+ this.dropdown.build(btnName, $dropdown, btnObject.dropdown);
+ }
+
+ // tooltip
+ if (this.utils.isDesktop())
+ {
+ this.button.createTooltip($button, btnName, btnObject.title);
+ }
+
+ return $button;
+ },
+ createTooltip: function($button, name, title)
+ {
+ var $tooltip = $(' ').addClass('redactor-toolbar-tooltip redactor-toolbar-tooltip-' + name).hide().html(title);
+ $tooltip.appendTo('body');
+
+ $button.on('mouseover', function()
+ {
+ if ($(this).hasClass('redactor-button-disabled')) return;
+
+ var pos = $button.offset();
+ var height = $button.innerHeight();
+ var width = $button.innerWidth();
+
+ $tooltip.show();
+ $tooltip.css({
+ top: (pos.top + height) + 'px',
+ left: (pos.left + width/2 - $tooltip.innerWidth()/2) + 'px'
+ });
+ });
+
+ $button.on('mouseout', function()
+ {
+ $tooltip.hide();
+ });
+
+ },
+ onClick: function(e, btnName, type, callback)
+ {
+ this.button.caretOffset = this.caret.getOffset();
+
+ e.preventDefault();
+
+ if (this.utils.browser('msie')) e.returnValue = false;
+
+ if (type == 'command')
+ {
+ this.inline.format(callback);
+ }
+ else if (type == 'dropdown')
+ {
+ this.dropdown.show(e, btnName);
+ }
+ else
+ {
+ var func;
+ if ($.isFunction(callback))
+ {
+ callback.call(this, btnName);
+ this.observe.buttons(e, btnName);
+ }
+ else if (callback.search(/\./) != '-1')
+ {
+ func = callback.split('.');
+ if (typeof this[func[0]] != 'undefined')
+ {
+ this[func[0]][func[1]](btnName);
+ this.observe.buttons(e, btnName);
+ }
+ }
+ else
+ {
+ this[callback](btnName);
+ this.observe.buttons(e, btnName);
+ }
+ }
+ },
+ get: function(key)
+ {
+ return this.$toolbar.find('a.re-' + key);
+ },
+ setActive: function(key)
+ {
+ this.button.get(key).addClass('redactor-act');
+ },
+ setInactive: function(key)
+ {
+ this.button.get(key).removeClass('redactor-act');
+ },
+ setInactiveAll: function(key)
+ {
+ if (typeof key == 'undefined')
+ {
+ this.$toolbar.find('a.re-icon').removeClass('redactor-act');
+ }
+ else
+ {
+ this.$toolbar.find('a.re-icon').not('.re-' + key).removeClass('redactor-act');
+ }
+ },
+ setActiveInVisual: function()
+ {
+ this.$toolbar.find('a.re-icon').not('a.re-html').removeClass('redactor-button-disabled');
+ },
+ setInactiveInCode: function()
+ {
+ this.$toolbar.find('a.re-icon').not('a.re-html').addClass('redactor-button-disabled');
+ },
+ changeIcon: function(key, classname)
+ {
+ this.button.get(key).addClass('re-' + classname);
+ },
+ removeIcon: function(key, classname)
+ {
+ this.button.get(key).removeClass('re-' + classname);
+ },
+ setAwesome: function(key, name)
+ {
+ var $button = this.button.get(key);
+ $button.removeClass('redactor-btn-image').addClass('fa-redactor-btn');
+ $button.html('');
+ },
+ addCallback: function($btn, callback)
+ {
+ var type = (callback == 'dropdown') ? 'dropdown' : 'func';
+ var key = $btn.attr('rel');
+ $btn.on('touchstart click', $.proxy(function(e)
+ {
+ if ($btn.hasClass('redactor-button-disabled')) return false;
+ this.button.onClick(e, key, type, callback);
+
+ }, this));
+ },
+ addDropdown: function($btn, dropdown)
+ {
+ var key = $btn.attr('rel');
+ this.button.addCallback($btn, 'dropdown');
+
+ var $dropdown = $('');
+ $btn.data('dropdown', $dropdown);
+
+ if (dropdown)
+ {
+ this.dropdown.build(key, $dropdown, dropdown);
+ }
+
+ return $dropdown;
+ },
+ add: function(key, title)
+ {
+ if (!this.opts.toolbar) return;
+
+ var btn = this.button.build(key, { title: title });
+ btn.addClass('redactor-btn-image');
+
+ this.$toolbar.append($(' ').append(btn));
+
+ return btn;
+ },
+ addFirst: function(key, title)
+ {
+ if (!this.opts.toolbar) return;
+
+ var btn = this.button.build(key, { title: title });
+ this.$toolbar.prepend($('').append(btn));
+
+ return btn;
+ },
+ addAfter: function(afterkey, key, title)
+ {
+ if (!this.opts.toolbar) return;
+
+ var btn = this.button.build(key, { title: title });
+ var $btn = this.button.get(afterkey);
+
+ if ($btn.size() !== 0) $btn.parent().after($('').append(btn));
+ else this.$toolbar.append($('').append(btn));
+
+ return btn;
+ },
+ addBefore: function(beforekey, key, title)
+ {
+ if (!this.opts.toolbar) return;
+
+ var btn = this.button.build(key, { title: title });
+ var $btn = this.button.get(beforekey);
+
+ if ($btn.size() !== 0) $btn.parent().before($('').append(btn));
+ else this.$toolbar.append($('').append(btn));
+
+ return btn;
+ },
+ remove: function(key)
+ {
+ this.button.get(key).remove();
+ }
+ };
+ },
+ caret: function()
+ {
+ return {
+ setStart: function(node)
+ {
+ // inline tag
+ if (!this.utils.isBlock(node))
+ {
+ var space = this.utils.createSpaceElement();
+
+ $(node).prepend(space);
+ this.caret.setEnd(space);
+ }
+ else
+ {
+ this.caret.set(node, 0, node, 0);
+ }
+ },
+ setEnd: function(node)
+ {
+ this.caret.set(node, 1, node, 1);
+ },
+ set: function(orgn, orgo, focn, foco)
+ {
+ // focus
+ if (!this.utils.browser('msie')) this.$editor.focus();
+
+ orgn = orgn[0] || orgn;
+ focn = focn[0] || focn;
+
+ if (this.utils.isBlockTag(orgn.tagName) && orgn.innerHTML === '')
+ {
+ orgn.innerHTML = this.opts.invisibleSpace;
+ }
+
+ if (orgn.tagName == 'BR' && this.opts.linebreaks === false)
+ {
+ var par = $(this.opts.emptyHtml)[0];
+ $(orgn).replaceWith(par);
+ orgn = par;
+ focn = orgn;
+ }
+
+ this.selection.get();
+
+ try {
+ this.range.setStart(orgn, orgo);
+ this.range.setEnd(focn, foco);
+ }
+ catch (e) {}
+
+ this.selection.addRange();
+ },
+ setAfter: function(node)
+ {
+ try {
+ var tag = $(node)[0].tagName;
+
+ // inline tag
+ if (tag != 'BR' && !this.utils.isBlock(node))
+ {
+ var space = this.utils.createSpaceElement();
+
+ $(node).after(space);
+ this.caret.setEnd(space);
+ }
+ else
+ {
+ if (tag != 'BR' && this.utils.browser('msie'))
+ {
+ this.caret.setStart($(node).next());
+ }
+ else
+ {
+ this.caret.setAfterOrBefore(node, 'after');
+ }
+ }
+ }
+ catch (e) {
+ var space = this.utils.createSpaceElement();
+ $(node).after(space);
+ this.caret.setEnd(space);
+ }
+ },
+ setBefore: function(node)
+ {
+ // block tag
+ if (this.utils.isBlock(node))
+ {
+ this.caret.setEnd($(node).prev());
+ }
+ else
+ {
+ this.caret.setAfterOrBefore(node, 'before');
+ }
+ },
+ setAfterOrBefore: function(node, type)
+ {
+ // focus
+ if (!this.utils.browser('msie')) this.$editor.focus();
+
+ node = node[0] || node;
+
+ this.selection.get();
+
+ if (type == 'after')
+ {
+ try {
+
+ this.range.setStartAfter(node);
+ this.range.setEndAfter(node);
+ }
+ catch (e) {}
+ }
+ else
+ {
+ try {
+ this.range.setStartBefore(node);
+ this.range.setEndBefore(node);
+ }
+ catch (e) {}
+ }
+
+
+ this.range.collapse(false);
+ this.selection.addRange();
+ },
+ getOffsetOfElement: function(node)
+ {
+ node = node[0] || node;
+
+ this.selection.get();
+
+ var cloned = this.range.cloneRange();
+ cloned.selectNodeContents(node);
+ cloned.setEnd(this.range.endContainer, this.range.endOffset);
+
+ return $.trim(cloned.toString()).length;
+ },
+ getOffset: function()
+ {
+ var offset = 0;
+ var sel = window.getSelection();
+ if (sel.rangeCount > 0)
+ {
+ var range = window.getSelection().getRangeAt(0);
+ var preCaretRange = range.cloneRange();
+ preCaretRange.selectNodeContents(this.$editor[0]);
+ preCaretRange.setEnd(range.endContainer, range.endOffset);
+ offset = preCaretRange.toString().length;
+ }
+
+ return offset;
+ },
+ setOffset: function(start, end)
+ {
+ if (typeof end == 'undefined') end = start;
+ if (!this.focus.isFocused()) this.focus.setStart();
+
+ var range = document.createRange();
+ var sel = document.getSelection();
+ var node, offset = 0;
+ var walker = document.createTreeWalker(this.$editor[0], NodeFilter.SHOW_TEXT, null, null);
+
+ while (node = walker.nextNode())
+ {
+ offset += node.nodeValue.length;
+ if (offset > start)
+ {
+ range.setStart(node, node.nodeValue.length + start - offset);
+ start = Infinity;
+ }
+
+ if (offset >= end)
+ {
+ range.setEnd(node, node.nodeValue.length + end - offset);
+ break;
+ }
+ }
+
+ sel.removeAllRanges();
+ sel.addRange(range);
+ },
+ setToPoint: function(start, end)
+ {
+ this.caret.setOffset(start, end);
+ },
+ getCoords: function()
+ {
+ return this.caret.getOffset();
+ }
+ };
+ },
+ clean: function()
+ {
+ return {
+ onSet: function(html)
+ {
+ html = this.clean.savePreCode(html);
+
+ // convert script tag
+ html = html.replace(/');
+
+ // restore form tag
+ html = this.clean.restoreFormTags(html);
+
+ var chars = {
+ '\u2122': '™',
+ '\u00a9': '©',
+ '\u2026': '…',
+ '\u2014': '—',
+ '\u2010': '‐'
+ };
+ // replace special characters
+ $.each(chars, function(i,s)
+ {
+ html = html.replace(new RegExp(i, 'g'), s);
+ });
+
+ // remove br in the of li
+ html = html.replace(new RegExp('
', 'gi'), '');
+ html = html.replace(new RegExp(' ', 'gi'), '');
+
+ // remove verified
+ html = html.replace(new RegExp(' ])>', 'gi'), ' ');
+ html = html.replace(new RegExp('<(.*?) data-verified="redactor"(.*?[^>])>', 'gi'), '<$1$2>');
+ html = html.replace(new RegExp(' ])>', 'gi'), '');
+ html = html.replace(new RegExp(' ])>', 'gi'), ' ');
+ html = html.replace(new RegExp(' ])>', 'gi'), ' ');
+ html = html.replace(new RegExp(' ])>', 'gi'), ' ');
+ html = html.replace(new RegExp('(.*?)', 'gi'), '$1');
+ html = html.replace(/ data-save-url="(.*?[^>])"/gi, '');
+
+ // remove image resize
+ html = html.replace(/])>([\w\W]*?) <\/span>/gi, '$3 ');
+ html = html.replace(/])>(.*?)<\/span>/gi, '');
+ html = html.replace(/])>(.*?)<\/span>/gi, '');
+
+ // remove font tag
+ html = html.replace(//gi, '');
+ html = html.replace(/<\/font>/gi, '');
+
+ // tidy html
+ html = this.tidy.load(html);
+
+ // link nofollow
+ if (this.opts.linkNofollow)
+ {
+ html = html.replace(/])>/gi, '');
+ html = html.replace(/])>/gi, '');
+ }
+
+ // reconvert inline
+ html = html.replace(/<(.*?) data-redactor-tag="(.*?)"(.*?[^>])>/gi, '<$1$3>');
+ html = html.replace(/<(.*?) data-redactor-class="(.*?)"(.*?[^>])>/gi, '<$1$3>');
+ html = html.replace(/<(.*?) data-redactor-style="(.*?)"(.*?[^>])>/gi, '<$1$3>');
+ html = html.replace(new RegExp('<(.*?) data-verified="redactor"(.*?[^>])>', 'gi'), '<$1$2>');
+ html = html.replace(new RegExp('<(.*?) data-verified="redactor">', 'gi'), '<$1>');
+
+ return html;
+ },
+ onPaste: function(html, setMode)
+ {
+ html = $.trim(html);
+
+ html = html.replace(/\$/g, '$');
+ html = html.replace(/”/g, '"');
+ html = html.replace(/“/g, '"');
+ html = html.replace(/‘/g, '\'');
+ html = html.replace(/’/g, '\'');
+
+ // convert dirty spaces
+ html = html.replace(/ <\/span>/gi, ' ');
+ html = html.replace(/]*>\t<\/span>/gi, '\t');
+ html = html.replace(/]*>(\s| )<\/span>/gi, ' ');
+
+ if (this.opts.pastePlainText)
+ {
+ return this.clean.getPlainText(html);
+ }
+
+ if (!this.utils.isSelectAll() && typeof setMode == 'undefined')
+ {
+ if (this.utils.isCurrentOrParent(['FIGCAPTION', 'A']))
+ {
+ return this.clean.getPlainText(html, false);
+ }
+
+ if (this.utils.isCurrentOrParent('PRE'))
+ {
+ return this.clean.getPreCode(html);
+ }
+
+ if (this.utils.isCurrentOrParent(['BLOCKQUOTE', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6']))
+ {
+ html = this.clean.getOnlyImages(html);
+
+ if (!this.utils.browser('msie'))
+ {
+ var block = this.selection.getBlock();
+ if (block && block.tagName == 'P')
+ {
+ html = html.replace(/ /gi, '![]() ');
+ }
+ }
+
+ return html;
+ }
+
+ if (this.utils.isCurrentOrParent(['TD']))
+ {
+ html = this.clean.onPasteTidy(html, 'td');
+
+ if (this.opts.linebreaks) html = this.clean.replaceParagraphsToBr(html);
+
+ html = this.clean.replaceDivsToBr(html);
+
+ return html;
+ }
+
+
+ if (this.utils.isCurrentOrParent(['LI']))
+ {
+ return this.clean.onPasteTidy(html, 'li');
+ }
+ }
+
+
+ html = this.clean.isSingleLine(html, setMode);
+
+ if (!this.clean.singleLine)
+ {
+ if (this.opts.linebreaks) html = this.clean.replaceParagraphsToBr(html);
+ if (this.opts.replaceDivs) html = this.clean.replaceDivs(html);
+
+ html = this.clean.saveFormTags(html);
+ }
+
+
+ html = this.clean.onPasteWord(html);
+ html = this.clean.onPasteExtra(html);
+
+ html = this.clean.onPasteTidy(html, 'all');
+
+
+ // paragraphize
+ if (!this.clean.singleLine && this.opts.paragraphize)
+ {
+ html = this.paragraphize.load(html);
+ }
+
+ html = this.clean.removeDirtyStyles(html);
+ html = this.clean.onPasteRemoveSpans(html);
+ html = this.clean.onPasteRemoveEmpty(html);
+
+ html = this.clean.convertInline(html);
+
+ return html;
+ },
+ onPasteWord: function(html)
+ {
+ // comments
+ html = html.replace(//gi, '');
+
+ // style
+ html = html.replace(/ |