trumbowyg_rails 1.1.3 → 2.1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +9 -7
- data/VERSION +1 -1
- data/lib/{trumbowyg_rails.rb → trumbowyg2-rails.rb} +0 -0
- data/trumbowyg_rails.gemspec +5 -5
- data/vendor/assets/images/trumbowyg/images/icons.svg +1 -0
- data/vendor/assets/javascripts/trumbowyg/langs/ar.js +56 -0
- data/vendor/assets/javascripts/trumbowyg/langs/ca.js +33 -34
- data/vendor/assets/javascripts/trumbowyg/langs/cs.js +54 -0
- data/vendor/assets/javascripts/trumbowyg/langs/da.js +55 -0
- data/vendor/assets/javascripts/trumbowyg/langs/de.js +33 -34
- data/vendor/assets/javascripts/trumbowyg/langs/el.js +58 -0
- data/vendor/assets/javascripts/trumbowyg/langs/es.js +33 -34
- data/vendor/assets/javascripts/trumbowyg/langs/es_ar.js +34 -34
- data/vendor/assets/javascripts/trumbowyg/langs/fa.js +33 -34
- data/vendor/assets/javascripts/trumbowyg/langs/fi.js +33 -34
- data/vendor/assets/javascripts/trumbowyg/langs/fr.js +40 -34
- data/vendor/assets/javascripts/trumbowyg/langs/he.js +57 -0
- data/vendor/assets/javascripts/trumbowyg/langs/hu.js +58 -0
- data/vendor/assets/javascripts/trumbowyg/langs/id.js +33 -34
- data/vendor/assets/javascripts/trumbowyg/langs/it.js +33 -34
- data/vendor/assets/javascripts/trumbowyg/langs/ja.js +56 -0
- data/vendor/assets/javascripts/trumbowyg/langs/ko.js +33 -34
- data/vendor/assets/javascripts/trumbowyg/langs/my.js +54 -0
- data/vendor/assets/javascripts/trumbowyg/langs/nl.js +56 -0
- data/vendor/assets/javascripts/trumbowyg/langs/pl.js +33 -34
- data/vendor/assets/javascripts/trumbowyg/langs/pt.js +33 -34
- data/vendor/assets/javascripts/trumbowyg/langs/ro.js +33 -35
- data/vendor/assets/javascripts/trumbowyg/langs/rs.js +53 -0
- data/vendor/assets/javascripts/trumbowyg/langs/rs_latin.js +54 -0
- data/vendor/assets/javascripts/trumbowyg/langs/ru.js +33 -34
- data/vendor/assets/javascripts/trumbowyg/langs/sk.js +54 -0
- data/vendor/assets/javascripts/trumbowyg/langs/sv.js +55 -0
- data/vendor/assets/javascripts/trumbowyg/langs/tr.js +34 -36
- data/vendor/assets/javascripts/trumbowyg/langs/ua.js +54 -0
- data/vendor/assets/javascripts/trumbowyg/langs/vi.js +55 -0
- data/vendor/assets/javascripts/trumbowyg/langs/zh_cn.js +34 -34
- data/vendor/assets/javascripts/trumbowyg/langs/zh_tw.js +57 -0
- data/vendor/assets/javascripts/trumbowyg/plugins/base64/trumbowyg.base64.js +90 -0
- data/vendor/assets/javascripts/trumbowyg/plugins/colors/trumbowyg.colors.js +164 -0
- data/vendor/assets/javascripts/trumbowyg/plugins/noembed/trumbowyg.noembed.js +96 -0
- data/vendor/assets/javascripts/trumbowyg/plugins/pasteimage/trumbowyg.pasteimage.js +39 -0
- data/vendor/assets/javascripts/trumbowyg/plugins/preformatted/trumbowyg.preformatted.js +117 -0
- data/vendor/assets/javascripts/trumbowyg/plugins/upload/trumbowyg.upload.js +204 -0
- data/vendor/assets/javascripts/trumbowyg/trumbowyg.js +1126 -700
- data/vendor/assets/stylesheets/trumbowyg/plugins/colors/trumbowyg.colors.scss +49 -0
- data/vendor/assets/stylesheets/trumbowyg/trumbowyg.scss +351 -159
- metadata +33 -11
- data/vendor/assets/images/trumbowyg/images/icons-2x.png +0 -0
- data/vendor/assets/images/trumbowyg/images/icons.png +0 -0
- data/vendor/assets/stylesheets/trumbowyg/_sprite-2x.scss +0 -28
- data/vendor/assets/stylesheets/trumbowyg/_sprite.scss +0 -28
@@ -0,0 +1,204 @@
|
|
1
|
+
/* ===========================================================
|
2
|
+
* trumbowyg.upload.js v1.1
|
3
|
+
* Upload plugin for Trumbowyg
|
4
|
+
* http://alex-d.github.com/Trumbowyg
|
5
|
+
* ===========================================================
|
6
|
+
* Author : Alexandre Demode (Alex-D)
|
7
|
+
* Twitter : @AlexandreDemode
|
8
|
+
* Website : alex-d.fr
|
9
|
+
*/
|
10
|
+
|
11
|
+
(function ($) {
|
12
|
+
'use strict';
|
13
|
+
|
14
|
+
var defaultOptions = {
|
15
|
+
serverPath: './src/plugins/upload/trumbowyg.upload.php',
|
16
|
+
fileFieldName: 'fileToUpload',
|
17
|
+
data: [],
|
18
|
+
headers: {},
|
19
|
+
xhrFields: {},
|
20
|
+
urlPropertyName: 'file',
|
21
|
+
statusPropertyName: 'success',
|
22
|
+
success: undefined,
|
23
|
+
error: undefined
|
24
|
+
};
|
25
|
+
|
26
|
+
function getDeep(object, propertyParts) {
|
27
|
+
var mainProperty = propertyParts.shift(),
|
28
|
+
otherProperties = propertyParts;
|
29
|
+
|
30
|
+
if (object !== null) {
|
31
|
+
if (otherProperties.length === 0) {
|
32
|
+
return object[mainProperty];
|
33
|
+
}
|
34
|
+
|
35
|
+
if (typeof object === 'object') {
|
36
|
+
return getDeep(object[mainProperty], otherProperties);
|
37
|
+
}
|
38
|
+
}
|
39
|
+
return object;
|
40
|
+
}
|
41
|
+
|
42
|
+
addXhrProgressEvent();
|
43
|
+
|
44
|
+
$.extend(true, $.trumbowyg, {
|
45
|
+
langs: {
|
46
|
+
// jshint camelcase:false
|
47
|
+
en: {
|
48
|
+
upload: 'Upload',
|
49
|
+
file: 'File',
|
50
|
+
uploadError: 'Error'
|
51
|
+
},
|
52
|
+
sk: {
|
53
|
+
upload: 'Nahrať',
|
54
|
+
file: 'Súbor',
|
55
|
+
uploadError: 'Chyba'
|
56
|
+
},
|
57
|
+
fr: {
|
58
|
+
upload: 'Envoi',
|
59
|
+
file: 'Fichier',
|
60
|
+
uploadError: 'Erreur'
|
61
|
+
},
|
62
|
+
cs: {
|
63
|
+
upload: 'Nahrát obrázek',
|
64
|
+
file: 'Soubor',
|
65
|
+
uploadError: 'Chyba'
|
66
|
+
},
|
67
|
+
zh_cn: {
|
68
|
+
upload: '上传',
|
69
|
+
file: '文件',
|
70
|
+
uploadError: '错误'
|
71
|
+
}
|
72
|
+
},
|
73
|
+
// jshint camelcase:true
|
74
|
+
|
75
|
+
plugins: {
|
76
|
+
upload: {
|
77
|
+
init: function (trumbowyg) {
|
78
|
+
trumbowyg.o.plugins.upload = $.extend(true, {}, defaultOptions, trumbowyg.o.plugins.upload || {});
|
79
|
+
var btnDef = {
|
80
|
+
fn: function () {
|
81
|
+
trumbowyg.saveRange();
|
82
|
+
|
83
|
+
var file,
|
84
|
+
prefix = trumbowyg.o.prefix;
|
85
|
+
|
86
|
+
var $modal = trumbowyg.openModalInsert(
|
87
|
+
// Title
|
88
|
+
trumbowyg.lang.upload,
|
89
|
+
|
90
|
+
// Fields
|
91
|
+
{
|
92
|
+
file: {
|
93
|
+
type: 'file',
|
94
|
+
required: true
|
95
|
+
},
|
96
|
+
alt: {
|
97
|
+
label: 'description',
|
98
|
+
value: trumbowyg.getRangeText()
|
99
|
+
}
|
100
|
+
},
|
101
|
+
|
102
|
+
// Callback
|
103
|
+
function (values) {
|
104
|
+
var data = new FormData();
|
105
|
+
data.append(trumbowyg.o.plugins.upload.fileFieldName, file);
|
106
|
+
|
107
|
+
trumbowyg.o.plugins.upload.data.map(function (cur) {
|
108
|
+
data.append(cur.name, cur.value);
|
109
|
+
});
|
110
|
+
|
111
|
+
if ($('.' + prefix + 'progress', $modal).length === 0) {
|
112
|
+
$('.' + prefix + 'modal-title', $modal)
|
113
|
+
.after(
|
114
|
+
$('<div/>', {
|
115
|
+
'class': prefix + 'progress'
|
116
|
+
}).append(
|
117
|
+
$('<div/>', {
|
118
|
+
'class': prefix + 'progress-bar'
|
119
|
+
})
|
120
|
+
)
|
121
|
+
);
|
122
|
+
}
|
123
|
+
|
124
|
+
$.ajax({
|
125
|
+
url: trumbowyg.o.plugins.upload.serverPath,
|
126
|
+
headers: trumbowyg.o.plugins.upload.headers,
|
127
|
+
xhrFields: trumbowyg.o.plugins.upload.xhrFields,
|
128
|
+
type: 'POST',
|
129
|
+
data: data,
|
130
|
+
cache: false,
|
131
|
+
dataType: 'json',
|
132
|
+
processData: false,
|
133
|
+
contentType: false,
|
134
|
+
|
135
|
+
progressUpload: function (e) {
|
136
|
+
$('.' + prefix + 'progress-bar').stop().animate({
|
137
|
+
width: Math.round(e.loaded * 100 / e.total) + '%'
|
138
|
+
}, 200);
|
139
|
+
},
|
140
|
+
|
141
|
+
success: trumbowyg.o.plugins.upload.success || function (data) {
|
142
|
+
if (!!getDeep(data, trumbowyg.o.plugins.upload.statusPropertyName.split('.'))) {
|
143
|
+
var url = getDeep(data, trumbowyg.o.plugins.upload.urlPropertyName.split('.'));
|
144
|
+
trumbowyg.execCmd('insertImage', url);
|
145
|
+
$('img[src="' + url + '"]:not([alt])', trumbowyg.$box).attr('alt', values.alt);
|
146
|
+
setTimeout(function () {
|
147
|
+
trumbowyg.closeModal();
|
148
|
+
}, 250);
|
149
|
+
} else {
|
150
|
+
trumbowyg.addErrorOnModalField(
|
151
|
+
$('input[type=file]', $modal),
|
152
|
+
trumbowyg.lang[data.message]
|
153
|
+
);
|
154
|
+
}
|
155
|
+
},
|
156
|
+
error: trumbowyg.o.plugins.upload.error || function () {
|
157
|
+
trumbowyg.addErrorOnModalField(
|
158
|
+
$('input[type=file]', $modal),
|
159
|
+
trumbowyg.lang.uploadError
|
160
|
+
);
|
161
|
+
}
|
162
|
+
});
|
163
|
+
}
|
164
|
+
);
|
165
|
+
|
166
|
+
$('input[type=file]').on('change', function (e) {
|
167
|
+
try {
|
168
|
+
// If multiple files allowed, we just get the first.
|
169
|
+
file = e.target.files[0];
|
170
|
+
} catch (err) {
|
171
|
+
// In IE8, multiple files not allowed
|
172
|
+
file = e.target.value;
|
173
|
+
}
|
174
|
+
});
|
175
|
+
}
|
176
|
+
};
|
177
|
+
|
178
|
+
trumbowyg.addBtnDef('upload', btnDef);
|
179
|
+
}
|
180
|
+
}
|
181
|
+
}
|
182
|
+
});
|
183
|
+
|
184
|
+
|
185
|
+
function addXhrProgressEvent() {
|
186
|
+
if (!$.trumbowyg && !$.trumbowyg.addedXhrProgressEvent) { // Avoid adding progress event multiple times
|
187
|
+
var originalXhr = $.ajaxSettings.xhr;
|
188
|
+
$.ajaxSetup({
|
189
|
+
xhr: function () {
|
190
|
+
var req = originalXhr(),
|
191
|
+
that = this;
|
192
|
+
if (req && typeof req.upload === 'object' && that.progressUpload !== undefined) {
|
193
|
+
req.upload.addEventListener('progress', function (e) {
|
194
|
+
that.progressUpload(e);
|
195
|
+
}, false);
|
196
|
+
}
|
197
|
+
|
198
|
+
return req;
|
199
|
+
}
|
200
|
+
});
|
201
|
+
$.trumbowyg.addedXhrProgressEvent = true;
|
202
|
+
}
|
203
|
+
}
|
204
|
+
})(jQuery);
|
@@ -1,99 +1,111 @@
|
|
1
|
-
|
1
|
+
jQuery.trumbowyg = {
|
2
2
|
langs: {
|
3
3
|
en: {
|
4
|
-
viewHTML:
|
4
|
+
viewHTML: 'View HTML',
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
blockquote: "Quote",
|
9
|
-
code: "Code",
|
10
|
-
header: "Header",
|
6
|
+
undo: 'Undo',
|
7
|
+
redo: 'Redo',
|
11
8
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
9
|
+
formatting: 'Formatting',
|
10
|
+
p: 'Paragraph',
|
11
|
+
blockquote: 'Quote',
|
12
|
+
code: 'Code',
|
13
|
+
header: 'Header',
|
16
14
|
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
bold: 'Bold',
|
16
|
+
italic: 'Italic',
|
17
|
+
strikethrough: 'Stroke',
|
18
|
+
underline: 'Underline',
|
20
19
|
|
21
|
-
|
22
|
-
|
20
|
+
strong: 'Strong',
|
21
|
+
em: 'Emphasis',
|
22
|
+
del: 'Deleted',
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
link: "Link",
|
27
|
-
createLink: "Insert link",
|
28
|
-
unlink: "Remove link",
|
24
|
+
superscript: 'Superscript',
|
25
|
+
subscript: 'Subscript',
|
29
26
|
|
30
|
-
|
31
|
-
|
32
|
-
justifyRight: "Align Right",
|
33
|
-
justifyFull: "Align Justify",
|
27
|
+
unorderedList: 'Unordered list',
|
28
|
+
orderedList: 'Ordered list',
|
34
29
|
|
35
|
-
|
30
|
+
insertImage: 'Insert Image',
|
31
|
+
link: 'Link',
|
32
|
+
createLink: 'Insert link',
|
33
|
+
unlink: 'Remove link',
|
36
34
|
|
37
|
-
|
35
|
+
justifyLeft: 'Align Left',
|
36
|
+
justifyCenter: 'Align Center',
|
37
|
+
justifyRight: 'Align Right',
|
38
|
+
justifyFull: 'Align Justify',
|
38
39
|
|
39
|
-
|
40
|
+
horizontalRule: 'Insert horizontal rule',
|
41
|
+
removeformat: 'Remove format',
|
40
42
|
|
41
|
-
|
42
|
-
reset: "Cancel",
|
43
|
+
fullscreen: 'Fullscreen',
|
43
44
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
45
|
+
close: 'Close',
|
46
|
+
|
47
|
+
submit: 'Confirm',
|
48
|
+
reset: 'Cancel',
|
49
|
+
|
50
|
+
required: 'Required',
|
51
|
+
description: 'Description',
|
52
|
+
title: 'Title',
|
53
|
+
text: 'Text',
|
54
|
+
target: 'Target'
|
49
55
|
}
|
50
56
|
},
|
51
57
|
|
52
|
-
//
|
53
|
-
|
58
|
+
// Plugins
|
59
|
+
plugins: {},
|
54
60
|
|
55
|
-
|
56
|
-
|
57
|
-
semantic: ['strong', 'em', 'del'],
|
58
|
-
justify: ['justifyLeft', 'justifyCenter', 'justifyRight', 'justifyFull'],
|
59
|
-
lists: ['unorderedList', 'orderedList']
|
60
|
-
}
|
61
|
+
// SVG Path globally
|
62
|
+
svgPath: null
|
61
63
|
};
|
62
64
|
|
63
65
|
|
64
|
-
|
65
|
-
(function(window, document, $){
|
66
|
+
(function (navigator, window, document, $) {
|
66
67
|
'use strict';
|
67
68
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
69
|
+
$.fn.trumbowyg = function (options, params) {
|
70
|
+
var trumbowygDataName = 'trumbowyg';
|
71
|
+
if (options === Object(options) || !options) {
|
72
|
+
return this.each(function () {
|
73
|
+
if (!$(this).data(trumbowygDataName)) {
|
74
|
+
$(this).data(trumbowygDataName, new Trumbowyg(this, options));
|
75
|
+
}
|
75
76
|
});
|
76
|
-
}
|
77
|
+
}
|
78
|
+
if (this.length === 1) {
|
77
79
|
try {
|
78
|
-
var t = $(this).data(
|
79
|
-
switch(
|
80
|
+
var t = $(this).data(trumbowygDataName);
|
81
|
+
switch (options) {
|
82
|
+
// Exec command
|
83
|
+
case 'execCmd':
|
84
|
+
return t.execCmd(params.cmd, params.param, params.forceCss);
|
85
|
+
|
80
86
|
// Modal box
|
81
87
|
case 'openModal':
|
82
|
-
return t.openModal(
|
88
|
+
return t.openModal(params.title, params.content);
|
83
89
|
case 'closeModal':
|
84
90
|
return t.closeModal();
|
85
91
|
case 'openModalInsert':
|
86
|
-
return t.openModalInsert(
|
87
|
-
|
88
|
-
//
|
89
|
-
case '
|
90
|
-
return t.
|
91
|
-
case '
|
92
|
-
return t.
|
93
|
-
case '
|
94
|
-
return t.
|
95
|
-
case '
|
96
|
-
return t.
|
92
|
+
return t.openModalInsert(params.title, params.fields, params.callback);
|
93
|
+
|
94
|
+
// Range
|
95
|
+
case 'saveRange':
|
96
|
+
return t.saveRange();
|
97
|
+
case 'getRange':
|
98
|
+
return t.range;
|
99
|
+
case 'getRangeText':
|
100
|
+
return t.getRangeText();
|
101
|
+
case 'restoreRange':
|
102
|
+
return t.restoreRange();
|
103
|
+
|
104
|
+
// Enable/disable
|
105
|
+
case 'enable':
|
106
|
+
return t.toggleDisable(false);
|
107
|
+
case 'disable':
|
108
|
+
return t.toggleDisable(true);
|
97
109
|
|
98
110
|
// Destroy
|
99
111
|
case 'destroy':
|
@@ -103,181 +115,326 @@
|
|
103
115
|
case 'empty':
|
104
116
|
return t.empty();
|
105
117
|
|
106
|
-
// Public options
|
107
|
-
case 'lang':
|
108
|
-
return t.lang;
|
109
|
-
case 'duration':
|
110
|
-
return t.o.duration;
|
111
|
-
|
112
118
|
// HTML
|
113
119
|
case 'html':
|
114
|
-
return t.html(
|
120
|
+
return t.html(params);
|
115
121
|
}
|
116
|
-
} catch(
|
122
|
+
} catch (c) {
|
123
|
+
}
|
117
124
|
}
|
118
125
|
|
119
126
|
return false;
|
120
127
|
};
|
121
128
|
|
129
|
+
// @param: editorElem is the DOM element
|
130
|
+
var Trumbowyg = function (editorElem, options) {
|
131
|
+
var t = this,
|
132
|
+
trumbowygIconsId = 'trumbowyg-icons';
|
122
133
|
|
134
|
+
// Get the document of the element. It use to makes the plugin
|
135
|
+
// compatible on iframes.
|
136
|
+
t.doc = editorElem.ownerDocument || document;
|
123
137
|
|
124
|
-
var Trumbowyg = function(editorElem, opts){
|
125
|
-
var t = this;
|
126
138
|
// jQuery object of the editor
|
127
|
-
t.$
|
128
|
-
t.$
|
139
|
+
t.$ta = $(editorElem); // $ta : Textarea
|
140
|
+
t.$c = $(editorElem); // $c : creator
|
129
141
|
|
130
|
-
|
131
|
-
opts = $.extend(true, {}, opts, $.trumbowyg.opts);
|
142
|
+
options = options || {};
|
132
143
|
|
133
144
|
// Localization management
|
134
|
-
if(
|
145
|
+
if (options.lang != null || $.trumbowyg.langs[options.lang] != null) {
|
146
|
+
t.lang = $.extend(true, {}, $.trumbowyg.langs.en, $.trumbowyg.langs[options.lang]);
|
147
|
+
} else {
|
135
148
|
t.lang = $.trumbowyg.langs.en;
|
136
|
-
|
137
|
-
|
149
|
+
}
|
150
|
+
|
151
|
+
// SVG path
|
152
|
+
var svgPathOption = $.trumbowyg.svgPath != null ? $.trumbowyg.svgPath : options.svgPath;
|
153
|
+
t.hasSvg = svgPathOption !== false;
|
154
|
+
t.svgPath = !!t.doc.querySelector('base') ? window.location : '';
|
155
|
+
if ($('#' + trumbowygIconsId, t.doc).length === 0 && svgPathOption !== false) {
|
156
|
+
if (svgPathOption == null) {
|
157
|
+
try {
|
158
|
+
throw new Error();
|
159
|
+
} catch (e) {
|
160
|
+
var stackLines = e.stack.split('\n');
|
161
|
+
|
162
|
+
for (var i in stackLines) {
|
163
|
+
if (!stackLines[i].match(/http[s]?:\/\//)) {
|
164
|
+
continue;
|
165
|
+
}
|
166
|
+
svgPathOption = stackLines[Number(i)].match(/((http[s]?:\/\/.+\/)([^\/]+\.js)):/)[1].split('/');
|
167
|
+
svgPathOption.pop();
|
168
|
+
svgPathOption = svgPathOption.join('/') + '/ui/icons.svg';
|
169
|
+
break;
|
170
|
+
}
|
171
|
+
}
|
172
|
+
}
|
173
|
+
|
174
|
+
var div = t.doc.createElement('div');
|
175
|
+
div.id = trumbowygIconsId;
|
176
|
+
t.doc.body.insertBefore(div, t.doc.body.childNodes[0]);
|
177
|
+
$.get(svgPathOption, function (data) {
|
178
|
+
div.innerHTML = new XMLSerializer().serializeToString(data.documentElement);
|
179
|
+
});
|
180
|
+
}
|
181
|
+
|
182
|
+
|
183
|
+
/**
|
184
|
+
* When the button is associated to a empty object
|
185
|
+
* fn and title attributs are defined from the button key value
|
186
|
+
*
|
187
|
+
* For example
|
188
|
+
* foo: {}
|
189
|
+
* is equivalent to :
|
190
|
+
* foo: {
|
191
|
+
* fn: 'foo',
|
192
|
+
* title: this.lang.foo
|
193
|
+
* }
|
194
|
+
*/
|
195
|
+
var h = t.lang.header, // Header translation
|
196
|
+
isBlinkFunction = function () {
|
197
|
+
return (window.chrome || (window.Intl && Intl.v8BreakIterator)) && 'CSS' in window;
|
198
|
+
};
|
199
|
+
t.btnsDef = {
|
200
|
+
viewHTML: {
|
201
|
+
fn: 'toggle'
|
202
|
+
},
|
203
|
+
|
204
|
+
undo: {
|
205
|
+
isSupported: isBlinkFunction,
|
206
|
+
key: 'Z'
|
207
|
+
},
|
208
|
+
redo: {
|
209
|
+
isSupported: isBlinkFunction,
|
210
|
+
key: 'Y'
|
211
|
+
},
|
212
|
+
|
213
|
+
p: {
|
214
|
+
fn: 'formatBlock'
|
215
|
+
},
|
216
|
+
blockquote: {
|
217
|
+
fn: 'formatBlock'
|
218
|
+
},
|
219
|
+
h1: {
|
220
|
+
fn: 'formatBlock',
|
221
|
+
title: h + ' 1'
|
222
|
+
},
|
223
|
+
h2: {
|
224
|
+
fn: 'formatBlock',
|
225
|
+
title: h + ' 2'
|
226
|
+
},
|
227
|
+
h3: {
|
228
|
+
fn: 'formatBlock',
|
229
|
+
title: h + ' 3'
|
230
|
+
},
|
231
|
+
h4: {
|
232
|
+
fn: 'formatBlock',
|
233
|
+
title: h + ' 4'
|
234
|
+
},
|
235
|
+
subscript: {
|
236
|
+
tag: 'sub'
|
237
|
+
},
|
238
|
+
superscript: {
|
239
|
+
tag: 'sup'
|
240
|
+
},
|
241
|
+
|
242
|
+
bold: {
|
243
|
+
key: 'B'
|
244
|
+
},
|
245
|
+
italic: {
|
246
|
+
key: 'I'
|
247
|
+
},
|
248
|
+
underline: {
|
249
|
+
tag: 'u'
|
250
|
+
},
|
251
|
+
strikethrough: {
|
252
|
+
tag: 'strike'
|
253
|
+
},
|
254
|
+
|
255
|
+
strong: {
|
256
|
+
fn: 'bold',
|
257
|
+
key: 'B'
|
258
|
+
},
|
259
|
+
em: {
|
260
|
+
fn: 'italic',
|
261
|
+
key: 'I'
|
262
|
+
},
|
263
|
+
del: {
|
264
|
+
fn: 'strikethrough'
|
265
|
+
},
|
266
|
+
|
267
|
+
createLink: {
|
268
|
+
key: 'K',
|
269
|
+
tag: 'a'
|
270
|
+
},
|
271
|
+
unlink: {},
|
272
|
+
|
273
|
+
insertImage: {},
|
274
|
+
|
275
|
+
justifyLeft: {
|
276
|
+
tag: 'left',
|
277
|
+
forceCss: true
|
278
|
+
},
|
279
|
+
justifyCenter: {
|
280
|
+
tag: 'center',
|
281
|
+
forceCss: true
|
282
|
+
},
|
283
|
+
justifyRight: {
|
284
|
+
tag: 'right',
|
285
|
+
forceCss: true
|
286
|
+
},
|
287
|
+
justifyFull: {
|
288
|
+
tag: 'justify',
|
289
|
+
forceCss: true
|
290
|
+
},
|
291
|
+
|
292
|
+
unorderedList: {
|
293
|
+
fn: 'insertUnorderedList',
|
294
|
+
tag: 'ul'
|
295
|
+
},
|
296
|
+
orderedList: {
|
297
|
+
fn: 'insertOrderedList',
|
298
|
+
tag: 'ol'
|
299
|
+
},
|
300
|
+
|
301
|
+
horizontalRule: {
|
302
|
+
fn: 'insertHorizontalRule'
|
303
|
+
},
|
304
|
+
|
305
|
+
removeformat: {},
|
306
|
+
|
307
|
+
fullscreen: {
|
308
|
+
class: 'trumbowyg-not-disable'
|
309
|
+
},
|
310
|
+
close: {
|
311
|
+
fn: 'destroy',
|
312
|
+
class: 'trumbowyg-not-disable'
|
313
|
+
},
|
314
|
+
|
315
|
+
// Dropdowns
|
316
|
+
formatting: {
|
317
|
+
dropdown: ['p', 'blockquote', 'h1', 'h2', 'h3', 'h4'],
|
318
|
+
ico: 'p'
|
319
|
+
},
|
320
|
+
link: {
|
321
|
+
dropdown: ['createLink', 'unlink']
|
322
|
+
}
|
323
|
+
};
|
138
324
|
|
139
325
|
// Defaults Options
|
140
|
-
t.o = $.extend(true, {
|
326
|
+
t.o = $.extend(true, {}, {
|
141
327
|
lang: 'en',
|
142
|
-
dir: 'ltr',
|
143
|
-
duration: 200, // Duration of modal box animations
|
144
328
|
|
145
|
-
mobile: false,
|
146
|
-
tablet: true,
|
147
|
-
closable: false,
|
148
|
-
fullscreenable: true,
|
149
329
|
fixedBtnPane: false,
|
150
330
|
fixedFullWidth: false,
|
151
|
-
semantic: false,
|
152
|
-
resetCss: false,
|
153
331
|
autogrow: false,
|
154
332
|
|
155
333
|
prefix: 'trumbowyg-',
|
156
334
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
func: 'formatBlock',
|
198
|
-
title: t.lang.header + ' 2'
|
199
|
-
},
|
200
|
-
h3: {
|
201
|
-
func: 'formatBlock',
|
202
|
-
title: t.lang.header + ' 3'
|
203
|
-
},
|
204
|
-
h4: {
|
205
|
-
func: 'formatBlock',
|
206
|
-
title: t.lang.header + ' 4'
|
207
|
-
},
|
335
|
+
semantic: true,
|
336
|
+
resetCss: false,
|
337
|
+
removeformatPasted: false,
|
338
|
+
tagsToRemove: [],
|
339
|
+
|
340
|
+
btnsGrps: {
|
341
|
+
design: ['bold', 'italic', 'underline', 'strikethrough'],
|
342
|
+
semantic: ['strong', 'em', 'del'],
|
343
|
+
justify: ['justifyLeft', 'justifyCenter', 'justifyRight', 'justifyFull'],
|
344
|
+
lists: ['unorderedList', 'orderedList']
|
345
|
+
},
|
346
|
+
btns: [
|
347
|
+
['viewHTML'],
|
348
|
+
['undo', 'redo'],
|
349
|
+
['formatting'],
|
350
|
+
'btnGrp-semantic',
|
351
|
+
['superscript', 'subscript'],
|
352
|
+
['link'],
|
353
|
+
['insertImage'],
|
354
|
+
'btnGrp-justify',
|
355
|
+
'btnGrp-lists',
|
356
|
+
['horizontalRule'],
|
357
|
+
['removeformat'],
|
358
|
+
['fullscreen']
|
359
|
+
],
|
360
|
+
// For custom button definitions
|
361
|
+
btnsDef: {},
|
362
|
+
|
363
|
+
inlineElementsSelector: 'a,abbr,acronym,b,caption,cite,code,col,dfn,dir,dt,dd,em,font,hr,i,kbd,li,q,span,strikeout,strong,sub,sup,u',
|
364
|
+
|
365
|
+
pasteHandlers: [],
|
366
|
+
|
367
|
+
imgDblClickHandler: function () {
|
368
|
+
var $img = $(this),
|
369
|
+
src = $img.attr('src'),
|
370
|
+
base64 = '(Base64)';
|
371
|
+
|
372
|
+
if (src.indexOf('data:image') === 0) {
|
373
|
+
src = base64;
|
374
|
+
}
|
208
375
|
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
376
|
+
t.openModalInsert(t.lang.insertImage, {
|
377
|
+
url: {
|
378
|
+
label: 'URL',
|
379
|
+
value: src,
|
380
|
+
required: true
|
381
|
+
},
|
382
|
+
alt: {
|
383
|
+
label: t.lang.description,
|
384
|
+
value: $img.attr('alt')
|
385
|
+
}
|
386
|
+
}, function (v) {
|
387
|
+
if (v.src !== base64) {
|
388
|
+
$img.attr({
|
389
|
+
src: v.src
|
390
|
+
});
|
391
|
+
}
|
392
|
+
$img.attr({
|
393
|
+
alt: v.alt
|
394
|
+
});
|
395
|
+
return true;
|
396
|
+
});
|
397
|
+
return false;
|
398
|
+
},
|
213
399
|
|
214
|
-
|
215
|
-
|
216
|
-
},
|
217
|
-
em: {
|
218
|
-
func: 'italic'
|
219
|
-
},
|
220
|
-
del: {
|
221
|
-
func: 'strikethrough'
|
222
|
-
},
|
400
|
+
plugins: {}
|
401
|
+
}, options);
|
223
402
|
|
224
|
-
|
225
|
-
unlink: {},
|
403
|
+
t.disabled = t.o.disabled || (editorElem.nodeName === 'TEXTAREA' && editorElem.disabled);
|
226
404
|
|
227
|
-
|
405
|
+
if (options.btns) {
|
406
|
+
t.o.btns = options.btns;
|
407
|
+
} else if (!t.o.semantic) {
|
408
|
+
t.o.btns[4] = 'btnGrp-design';
|
409
|
+
}
|
228
410
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
justifyFull: {},
|
411
|
+
$.each(t.o.btnsDef, function (btnName, btnDef) {
|
412
|
+
t.addBtnDef(btnName, btnDef);
|
413
|
+
});
|
233
414
|
|
234
|
-
|
235
|
-
|
236
|
-
},
|
237
|
-
orderedList: {
|
238
|
-
func: 'insertOrderedList'
|
239
|
-
},
|
415
|
+
// Keyboard shortcuts are load in this array
|
416
|
+
t.keys = [];
|
240
417
|
|
241
|
-
|
242
|
-
|
243
|
-
|
418
|
+
// Tag to button dynamically hydrated
|
419
|
+
t.tagToButton = {};
|
420
|
+
t.tagHandlers = [];
|
244
421
|
|
245
|
-
|
246
|
-
|
247
|
-
dropdown: ['p', 'blockquote', 'h1', 'h2', 'h3', 'h4']
|
248
|
-
},
|
249
|
-
link: {
|
250
|
-
dropdown: ['createLink', 'unlink']
|
251
|
-
}
|
252
|
-
}
|
253
|
-
}, opts);
|
254
|
-
|
255
|
-
if(t.o.semantic && !opts.btns)
|
256
|
-
t.o.btns = [
|
257
|
-
'viewHTML',
|
258
|
-
'|', 'formatting',
|
259
|
-
'|', $.trumbowyg.btnsGrps.semantic,
|
260
|
-
'|', 'link',
|
261
|
-
'|', 'insertImage',
|
262
|
-
'|', $.trumbowyg.btnsGrps.justify,
|
263
|
-
'|', $.trumbowyg.btnsGrps.lists,
|
264
|
-
'|', 'horizontalRule'
|
265
|
-
];
|
266
|
-
else if(opts && opts.btns)
|
267
|
-
t.o.btns = opts.btns;
|
422
|
+
// Admit multiple paste handlers
|
423
|
+
t.pasteHandlers = [].concat(t.o.pasteHandlers);
|
268
424
|
|
269
425
|
t.init();
|
270
426
|
};
|
271
427
|
|
272
428
|
Trumbowyg.prototype = {
|
273
|
-
init: function(){
|
429
|
+
init: function () {
|
274
430
|
var t = this;
|
275
|
-
t.height = t.$
|
431
|
+
t.height = t.$ta.height();
|
276
432
|
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
433
|
+
t.initPlugins();
|
434
|
+
|
435
|
+
// Disable image resize in Firefox
|
436
|
+
t.doc.execCommand('enableObjectResizing', false, false);
|
437
|
+
t.doc.execCommand('defaultParagraphSeparator', false, 'p');
|
281
438
|
|
282
439
|
t.buildEditor();
|
283
440
|
t.buildBtnPane();
|
@@ -285,561 +442,715 @@
|
|
285
442
|
t.fixedBtnPaneEvents();
|
286
443
|
|
287
444
|
t.buildOverlay();
|
288
|
-
},
|
289
|
-
|
290
|
-
buildEditor: function(disable){
|
291
|
-
var t = this;
|
292
|
-
var pfx = t.o.prefix;
|
293
|
-
|
294
445
|
|
295
|
-
|
296
|
-
if(
|
297
|
-
|
298
|
-
t.$e.hide().after(textarea);
|
446
|
+
setTimeout(function () {
|
447
|
+
if (t.disabled) {
|
448
|
+
t.toggleDisable(true);
|
299
449
|
}
|
300
|
-
|
301
|
-
}
|
450
|
+
t.$c.trigger('tbwinit');
|
451
|
+
});
|
452
|
+
},
|
302
453
|
|
454
|
+
addBtnDef: function (btnName, btnDef) {
|
455
|
+
this.btnsDef[btnName] = btnDef;
|
456
|
+
},
|
457
|
+
|
458
|
+
buildEditor: function () {
|
459
|
+
var t = this,
|
460
|
+
prefix = t.o.prefix,
|
461
|
+
html = '';
|
303
462
|
|
304
463
|
t.$box = $('<div/>', {
|
305
|
-
class:
|
464
|
+
class: prefix + 'box ' + prefix + 'editor-visible ' + prefix + t.o.lang + ' trumbowyg'
|
306
465
|
});
|
307
466
|
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
t.$
|
314
|
-
t
|
315
|
-
|
467
|
+
// $ta = Textarea
|
468
|
+
// $ed = Editor
|
469
|
+
t.isTextarea = t.$ta.is('textarea');
|
470
|
+
if (t.isTextarea) {
|
471
|
+
html = t.$ta.val();
|
472
|
+
t.$ed = $('<div/>');
|
473
|
+
t.$box
|
474
|
+
.insertAfter(t.$ta)
|
475
|
+
.append(t.$ed, t.$ta);
|
476
|
+
} else {
|
477
|
+
t.$ed = t.$ta;
|
478
|
+
html = t.$ed.html();
|
316
479
|
|
317
|
-
|
318
|
-
|
480
|
+
t.$ta = $('<textarea/>', {
|
481
|
+
name: t.$ta.attr('id'),
|
482
|
+
height: t.height
|
483
|
+
}).val(html);
|
319
484
|
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
t.$box.insertAfter(t.$e)
|
324
|
-
.append(t.$editor)
|
325
|
-
.append(t.$e);
|
326
|
-
} else {
|
327
|
-
html = t.$editor.html();
|
328
|
-
t.$box.insertAfter(t.$editor)
|
329
|
-
.append(t.$e)
|
330
|
-
.append(t.$editor);
|
485
|
+
t.$box
|
486
|
+
.insertAfter(t.$ed)
|
487
|
+
.append(t.$ta, t.$ed);
|
331
488
|
t.syncCode();
|
332
489
|
}
|
333
490
|
|
334
|
-
t.$
|
335
|
-
|
336
|
-
|
337
|
-
|
491
|
+
t.$ta
|
492
|
+
.addClass(prefix + 'textarea')
|
493
|
+
.attr('tabindex', -1)
|
494
|
+
;
|
338
495
|
|
339
|
-
|
340
|
-
|
496
|
+
t.$ed
|
497
|
+
.addClass(prefix + 'editor')
|
498
|
+
.attr({
|
499
|
+
contenteditable: true,
|
500
|
+
dir: t.lang._dir || 'ltr'
|
501
|
+
})
|
502
|
+
.html(html)
|
503
|
+
;
|
341
504
|
|
342
|
-
if(
|
343
|
-
|
344
|
-
$el.css({
|
345
|
-
height: t.height,
|
346
|
-
overflow: 'auto'
|
347
|
-
});
|
348
|
-
});
|
505
|
+
if (t.o.tabindex) {
|
506
|
+
t.$ed.attr('tabindex', t.o.tabindex);
|
349
507
|
}
|
350
508
|
|
351
|
-
if(t.
|
352
|
-
t.$
|
353
|
-
t.$editor.html()
|
354
|
-
.replace('<br>', '</p><p>')
|
355
|
-
.replace(' ', '')
|
356
|
-
);
|
357
|
-
t.semanticCode();
|
509
|
+
if (t.$c.is('[placeholder]')) {
|
510
|
+
t.$ed.attr('placeholder', t.$c.attr('placeholder'));
|
358
511
|
}
|
359
512
|
|
513
|
+
if (t.o.resetCss) {
|
514
|
+
t.$ed.addClass(prefix + 'reset-css');
|
515
|
+
}
|
360
516
|
|
517
|
+
if (!t.o.autogrow) {
|
518
|
+
t.$ta.add(t.$ed).css({
|
519
|
+
height: t.height
|
520
|
+
});
|
521
|
+
}
|
361
522
|
|
362
|
-
t
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
523
|
+
t.semanticCode();
|
524
|
+
|
525
|
+
|
526
|
+
t._ctrl = false;
|
527
|
+
t.$ed
|
528
|
+
.on('dblclick', 'img', t.o.imgDblClickHandler)
|
529
|
+
.on('keydown', function (e) {
|
530
|
+
t._composition = (e.which === 229);
|
531
|
+
|
532
|
+
if (e.ctrlKey) {
|
533
|
+
t._ctrl = true;
|
534
|
+
var k = t.keys[String.fromCharCode(e.which).toUpperCase()];
|
535
|
+
|
536
|
+
try {
|
537
|
+
t.execCmd(k.fn, k.param);
|
538
|
+
return false;
|
539
|
+
} catch (c) {
|
540
|
+
}
|
541
|
+
}
|
542
|
+
})
|
543
|
+
.on('keyup', function (e) {
|
544
|
+
if (e.which >= 37 && e.which <= 40) {
|
545
|
+
return;
|
546
|
+
}
|
547
|
+
|
548
|
+
if (e.ctrlKey && (e.which === 89 || e.which === 90)) {
|
549
|
+
t.$c.trigger('tbwchange');
|
550
|
+
} else if (!t._ctrl && e.which !== 17 && !t._composition) {
|
551
|
+
t.semanticCode(false, e.which === 13);
|
552
|
+
t.$c.trigger('tbwchange');
|
553
|
+
}
|
554
|
+
|
555
|
+
setTimeout(function () {
|
556
|
+
t._ctrl = false;
|
557
|
+
}, 200);
|
558
|
+
})
|
559
|
+
.on('mouseup keydown keyup', function () {
|
560
|
+
t.updateButtonPaneStatus();
|
561
|
+
})
|
562
|
+
.on('focus blur', function (e) {
|
563
|
+
t.$c.trigger('tbw' + e.type);
|
564
|
+
if (e.type === 'blur') {
|
565
|
+
$('.' + prefix + 'active-button', t.$btnPane).removeClass(prefix + 'active-button ' + prefix + 'active');
|
374
566
|
}
|
375
|
-
}
|
376
|
-
|
377
|
-
|
567
|
+
})
|
568
|
+
.on('cut', function () {
|
569
|
+
t.$c.trigger('tbwchange');
|
570
|
+
})
|
571
|
+
.on('paste', function (e) {
|
572
|
+
if (t.o.removeformatPasted) {
|
573
|
+
e.preventDefault();
|
574
|
+
|
575
|
+
try {
|
576
|
+
// IE
|
577
|
+
var text = window.clipboardData.getData('Text');
|
578
|
+
|
579
|
+
try {
|
580
|
+
// <= IE10
|
581
|
+
t.doc.selection.createRange().pasteHTML(text);
|
582
|
+
} catch (c) {
|
583
|
+
// IE 11
|
584
|
+
t.doc.getSelection().getRangeAt(0).insertNode(t.doc.createTextNode(text));
|
585
|
+
}
|
586
|
+
} catch (d) {
|
587
|
+
// Not IE
|
588
|
+
t.execCmd('insertText', (e.originalEvent || e).clipboardData.getData('text/plain'));
|
589
|
+
}
|
590
|
+
}
|
591
|
+
|
592
|
+
// Call pasteHandlers
|
593
|
+
$.each(t.pasteHandlers, function (i, pasteHandler) {
|
594
|
+
pasteHandler(e);
|
595
|
+
});
|
596
|
+
|
597
|
+
setTimeout(function () {
|
598
|
+
if (t.o.semantic) {
|
599
|
+
t.semanticCode(false, true);
|
600
|
+
} else {
|
601
|
+
t.syncCode();
|
602
|
+
}
|
603
|
+
t.$c.trigger('tbwpaste', e);
|
604
|
+
}, 0);
|
378
605
|
});
|
379
|
-
|
380
|
-
|
381
|
-
.on('keyup', function(e){
|
382
|
-
t.semanticCode(false, e.which === 13);
|
383
|
-
})
|
384
|
-
.on('blur', function(){
|
385
|
-
t.syncCode();
|
606
|
+
t.$ta.on('keyup paste', function () {
|
607
|
+
t.$c.trigger('tbwchange');
|
386
608
|
});
|
387
|
-
},
|
388
|
-
|
389
609
|
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
610
|
+
$(t.doc).on('keydown', function (e) {
|
611
|
+
if (e.which === 27) {
|
612
|
+
t.closeModal();
|
613
|
+
return false;
|
614
|
+
}
|
395
615
|
});
|
396
616
|
},
|
397
617
|
|
398
618
|
|
399
|
-
// Build button pane, use o.btns
|
400
|
-
buildBtnPane: function(){
|
619
|
+
// Build button pane, use o.btns option
|
620
|
+
buildBtnPane: function () {
|
401
621
|
var t = this,
|
402
|
-
|
622
|
+
prefix = t.o.prefix;
|
403
623
|
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
t.$btnPane = $('<ul/>', {
|
408
|
-
class: pfx + 'button-pane'
|
624
|
+
var $btnPane = t.$btnPane = $('<div/>', {
|
625
|
+
class: prefix + 'button-pane'
|
409
626
|
});
|
410
627
|
|
411
|
-
$.each(t.o.btns
|
628
|
+
$.each(t.o.btns, function (i, btnGrps) {
|
412
629
|
// Managment of group of buttons
|
413
630
|
try {
|
414
|
-
var b =
|
415
|
-
if(b[1]
|
416
|
-
|
417
|
-
|
631
|
+
var b = btnGrps.split('btnGrp-');
|
632
|
+
if (b[1] != null) {
|
633
|
+
btnGrps = t.o.btnsGrps[b[1]];
|
634
|
+
}
|
635
|
+
} catch (c) {
|
636
|
+
}
|
418
637
|
|
419
|
-
if(!$.isArray(
|
420
|
-
|
638
|
+
if (!$.isArray(btnGrps)) {
|
639
|
+
btnGrps = [btnGrps];
|
640
|
+
}
|
421
641
|
|
422
|
-
|
642
|
+
var $btnGroup = $('<div/>', {
|
643
|
+
class: prefix + 'button-group ' + ((btnGrps.indexOf('fullscreen') >= 0) ? prefix + 'right' : '')
|
644
|
+
});
|
645
|
+
$.each(btnGrps, function (i, btn) {
|
423
646
|
try { // Prevent buildBtn error
|
424
|
-
var $
|
647
|
+
var $item;
|
425
648
|
|
426
|
-
if(
|
427
|
-
$
|
428
|
-
|
429
|
-
$li.append(t.buildBtn(b));
|
649
|
+
if (t.isSupportedBtn(btn)) { // It's a supported button
|
650
|
+
$item = t.buildBtn(btn);
|
651
|
+
}
|
430
652
|
|
431
|
-
|
432
|
-
} catch(
|
653
|
+
$btnGroup.append($item);
|
654
|
+
} catch (c) {
|
655
|
+
}
|
433
656
|
});
|
657
|
+
$btnPane.append($btnGroup);
|
434
658
|
});
|
435
659
|
|
436
|
-
|
437
|
-
var $liRight = $('<li/>', {
|
438
|
-
class: pfx + 'not-disable ' + pfx + 'buttons-right'
|
439
|
-
});
|
440
|
-
|
441
|
-
// Add the fullscreen button
|
442
|
-
if(t.o.fullscreenable)
|
443
|
-
$liRight
|
444
|
-
.append(t.buildRightBtn('fullscreen')
|
445
|
-
.on('click', function(){
|
446
|
-
var cssClass = pfx + 'fullscreen';
|
447
|
-
t.$box.toggleClass(cssClass);
|
448
|
-
|
449
|
-
if(t.$box.hasClass(cssClass)){
|
450
|
-
$('body').css('overflow', 'hidden');
|
451
|
-
$.each([t.$editor, t.$e], function(){
|
452
|
-
$(this).css({
|
453
|
-
height: 'calc(100% - 35px)',
|
454
|
-
overflow: 'auto'
|
455
|
-
});
|
456
|
-
});
|
457
|
-
t.$btnPane.css('width', '100%');
|
458
|
-
} else {
|
459
|
-
$('body').css('overflow', 'auto');
|
460
|
-
t.$box.removeAttr('style');
|
461
|
-
if(!t.o.autogrow)
|
462
|
-
$([t.$editor, t.$e]).each(function(i, $el){
|
463
|
-
$el.css('height', t.height);
|
464
|
-
});
|
465
|
-
}
|
466
|
-
$(window).trigger('scroll');
|
467
|
-
}));
|
468
|
-
|
469
|
-
// Build and add close button
|
470
|
-
if(t.o.closable)
|
471
|
-
$liRight
|
472
|
-
.append(
|
473
|
-
t.buildRightBtn('close')
|
474
|
-
.on('click', function(){
|
475
|
-
if(t.$box.hasClass(pfx + 'fullscreen'))
|
476
|
-
$('body').css('overflow', 'auto');
|
477
|
-
t.destroy();
|
478
|
-
})
|
479
|
-
);
|
480
|
-
|
481
|
-
|
482
|
-
// Add right li only if isn't empty
|
483
|
-
if($liRight.not(':empty'))
|
484
|
-
t.$btnPane.append($liRight);
|
485
|
-
|
486
|
-
t.$box.prepend(t.$btnPane);
|
660
|
+
t.$box.prepend($btnPane);
|
487
661
|
},
|
488
662
|
|
489
663
|
|
490
664
|
// Build a button and his action
|
491
|
-
buildBtn: function(
|
665
|
+
buildBtn: function (btnName) { // btnName is name of the button
|
492
666
|
var t = this,
|
493
|
-
|
494
|
-
btn = t.
|
495
|
-
|
496
|
-
textDef = t.lang[
|
667
|
+
prefix = t.o.prefix,
|
668
|
+
btn = t.btnsDef[btnName],
|
669
|
+
isDropdown = btn.dropdown,
|
670
|
+
textDef = t.lang[btnName] || btnName,
|
497
671
|
|
498
672
|
$btn = $('<button/>', {
|
499
673
|
type: 'button',
|
500
|
-
class:
|
501
|
-
|
502
|
-
title: btn.title || btn.text || textDef,
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
674
|
+
class: prefix + btnName + '-button ' + (btn.class || ''),
|
675
|
+
html: t.hasSvg ? '<svg><use xlink:href="' + t.svgPath + '#' + prefix + (btn.ico || btnName).replace(/([A-Z]+)/g, '-$1').toLowerCase() + '"/></svg>' : '',
|
676
|
+
title: (btn.title || btn.text || textDef) + ((btn.key) ? ' (Ctrl + ' + btn.key + ')' : ''),
|
677
|
+
tabindex: -1,
|
678
|
+
mousedown: function () {
|
679
|
+
if (!isDropdown || $('.' + btnName + '-' + prefix + 'dropdown', t.$box).is(':hidden')) {
|
680
|
+
$('body', t.doc).trigger('mousedown');
|
681
|
+
}
|
682
|
+
|
683
|
+
if (t.$btnPane.hasClass(prefix + 'disable') && !$(this).hasClass(prefix + 'active') && !$(this).hasClass(prefix + 'not-disable')) {
|
508
684
|
return false;
|
685
|
+
}
|
509
686
|
|
510
|
-
t.execCmd((
|
511
|
-
btn.param || n);
|
687
|
+
t.execCmd((isDropdown ? 'dropdown' : false) || btn.fn || btnName, btn.param || btnName, btn.forceCss || false);
|
512
688
|
|
513
|
-
|
514
|
-
e.preventDefault();
|
689
|
+
return false;
|
515
690
|
}
|
516
691
|
});
|
517
692
|
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
class: n + '-' + c + ' ' + c + ' ' + pfx + 'fixed-top'
|
693
|
+
if (isDropdown) {
|
694
|
+
$btn.addClass(prefix + 'open-dropdown');
|
695
|
+
var dropdownPrefix = prefix + 'dropdown',
|
696
|
+
$dropdown = $('<div/>', { // the dropdown
|
697
|
+
class: dropdownPrefix + '-' + btnName + ' ' + dropdownPrefix + ' ' + prefix + 'fixed-top',
|
698
|
+
'data-dropdown': btnName
|
525
699
|
});
|
526
|
-
|
527
|
-
if(t.
|
528
|
-
|
529
|
-
|
700
|
+
$.each(isDropdown, function (i, def) {
|
701
|
+
if (t.btnsDef[def] && t.isSupportedBtn(def)) {
|
702
|
+
$dropdown.append(t.buildSubBtn(def));
|
703
|
+
}
|
704
|
+
});
|
705
|
+
t.$box.append($dropdown.hide());
|
706
|
+
} else if (btn.key) {
|
707
|
+
t.keys[btn.key] = {
|
708
|
+
fn: btn.fn || btnName,
|
709
|
+
param: btn.param || btnName
|
710
|
+
};
|
711
|
+
}
|
712
|
+
|
713
|
+
if (!isDropdown) {
|
714
|
+
t.tagToButton[(btn.tag || btnName).toLowerCase()] = btnName;
|
530
715
|
}
|
531
716
|
|
532
717
|
return $btn;
|
533
718
|
},
|
534
719
|
// Build a button for dropdown menu
|
535
720
|
// @param n : name of the subbutton
|
536
|
-
buildSubBtn: function(
|
721
|
+
buildSubBtn: function (btnName) {
|
537
722
|
var t = this,
|
538
|
-
|
723
|
+
prefix = t.o.prefix,
|
724
|
+
btn = t.btnsDef[btnName];
|
725
|
+
|
726
|
+
if (btn.key) {
|
727
|
+
t.keys[btn.key] = {
|
728
|
+
fn: btn.fn || btnName,
|
729
|
+
param: btn.param || btnName
|
730
|
+
};
|
731
|
+
}
|
732
|
+
|
733
|
+
t.tagToButton[(btn.tag || btnName).toLowerCase()] = btnName;
|
734
|
+
|
539
735
|
return $('<button/>', {
|
540
736
|
type: 'button',
|
541
|
-
|
542
|
-
|
543
|
-
|
737
|
+
class: prefix + btnName + '-dropdown-button' + (btn.ico ? ' ' + prefix + btn.ico + '-button' : ''),
|
738
|
+
html: t.hasSvg ? '<svg><use xlink:href="' + t.svgPath + '#' + prefix + (btn.ico || btnName).replace(/([A-Z]+)/g, '-$1').toLowerCase() + '"/></svg>' + (btn.text || btn.title || t.lang[btnName] || btnName) : '',
|
739
|
+
title: ((btn.key) ? ' (Ctrl + ' + btn.key + ')' : null),
|
740
|
+
style: btn.style || null,
|
741
|
+
mousedown: function () {
|
742
|
+
$('body', t.doc).trigger('mousedown');
|
544
743
|
|
545
|
-
t.execCmd(
|
546
|
-
btnDef.param || n);
|
744
|
+
t.execCmd(btn.fn || btnName, btn.param || btnName, btn.forceCss || false);
|
547
745
|
|
548
|
-
e.stopPropagation();
|
549
|
-
e.preventDefault();
|
550
746
|
return false;
|
551
747
|
}
|
552
748
|
});
|
553
749
|
},
|
554
|
-
// Build a button for right li
|
555
|
-
// @param n : name of the right button
|
556
|
-
buildRightBtn: function(n){
|
557
|
-
return $('<button/>', {
|
558
|
-
type: 'button',
|
559
|
-
class: this.o.prefix + n + '-button',
|
560
|
-
title: this.lang[n],
|
561
|
-
text: this.lang[n]
|
562
|
-
});
|
563
|
-
},
|
564
750
|
// Check if button is supported
|
565
|
-
isSupportedBtn: function(
|
566
|
-
|
751
|
+
isSupportedBtn: function (b) {
|
752
|
+
try {
|
753
|
+
return this.btnsDef[b].isSupported();
|
754
|
+
} catch (c) {
|
755
|
+
}
|
756
|
+
return true;
|
567
757
|
},
|
568
758
|
|
569
759
|
// Build overlay for modal box
|
570
|
-
buildOverlay: function(){
|
760
|
+
buildOverlay: function () {
|
571
761
|
var t = this;
|
572
762
|
t.$overlay = $('<div/>', {
|
573
763
|
class: t.o.prefix + 'overlay'
|
574
764
|
}).css({
|
575
765
|
top: t.$btnPane.outerHeight(),
|
576
|
-
height: (
|
766
|
+
height: (t.$ed.outerHeight() + 1) + 'px'
|
577
767
|
}).appendTo(t.$box);
|
578
768
|
return t.$overlay;
|
579
769
|
},
|
580
|
-
showOverlay: function(){
|
770
|
+
showOverlay: function () {
|
581
771
|
var t = this;
|
582
772
|
$(window).trigger('scroll');
|
583
|
-
t.$overlay.fadeIn(
|
773
|
+
t.$overlay.fadeIn(200);
|
584
774
|
t.$box.addClass(t.o.prefix + 'box-blur');
|
585
775
|
},
|
586
|
-
hideOverlay: function(){
|
776
|
+
hideOverlay: function () {
|
587
777
|
var t = this;
|
588
|
-
t.$overlay.fadeOut(
|
778
|
+
t.$overlay.fadeOut(50);
|
589
779
|
t.$box.removeClass(t.o.prefix + 'box-blur');
|
590
780
|
},
|
591
781
|
|
592
782
|
// Management of fixed button pane
|
593
|
-
fixedBtnPaneEvents: function(){
|
783
|
+
fixedBtnPaneEvents: function () {
|
594
784
|
var t = this,
|
595
|
-
|
596
|
-
|
785
|
+
fixedFullWidth = t.o.fixedFullWidth,
|
786
|
+
$box = t.$box;
|
787
|
+
|
788
|
+
if (!t.o.fixedBtnPane) {
|
597
789
|
return;
|
790
|
+
}
|
598
791
|
|
599
792
|
t.isFixed = false;
|
600
793
|
|
601
794
|
$(window)
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
t.syncCode();
|
607
|
-
|
608
|
-
var s = $(window).scrollTop(), // s is top scroll
|
609
|
-
o = t.$box.offset().top + 1, // o is offset
|
610
|
-
toFixed = (s - o > 0) && ((s - o - parseInt(t.height)) < 0),
|
611
|
-
bp = t.$btnPane,
|
612
|
-
mt = bp.css('height'),
|
613
|
-
oh = bp.outerHeight();
|
795
|
+
.on('scroll resize', function () {
|
796
|
+
if (!$box) {
|
797
|
+
return;
|
798
|
+
}
|
614
799
|
|
615
|
-
|
616
|
-
|
617
|
-
|
800
|
+
t.syncCode();
|
801
|
+
|
802
|
+
var scrollTop = $(window).scrollTop(),
|
803
|
+
offset = $box.offset().top + 1,
|
804
|
+
bp = t.$btnPane,
|
805
|
+
oh = bp.outerHeight() - 2;
|
806
|
+
|
807
|
+
if ((scrollTop - offset > 0) && ((scrollTop - offset - t.height) < 0)) {
|
808
|
+
if (!t.isFixed) {
|
809
|
+
t.isFixed = true;
|
810
|
+
bp.css({
|
811
|
+
position: 'fixed',
|
812
|
+
top: 0,
|
813
|
+
left: fixedFullWidth ? '0' : 'auto',
|
814
|
+
zIndex: 7
|
815
|
+
});
|
816
|
+
$([t.$ta, t.$ed]).css({marginTop: bp.height()});
|
817
|
+
}
|
618
818
|
bp.css({
|
619
|
-
|
620
|
-
top: 0,
|
621
|
-
left: ffw ? '0' : 'auto',
|
622
|
-
zIndex: 7
|
819
|
+
width: fixedFullWidth ? '100%' : (($box.width() - 1) + 'px')
|
623
820
|
});
|
624
|
-
t.$editor.css({ marginTop: mt });
|
625
|
-
t.$e.css({ marginTop: mt });
|
626
|
-
}
|
627
|
-
bp.css({
|
628
|
-
width: ffw ? '100%' : ((parseInt(t.$box.css('width'))-1) + 'px')
|
629
|
-
});
|
630
821
|
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
}
|
645
|
-
}
|
646
|
-
});
|
822
|
+
$('.' + t.o.prefix + 'fixed-top', $box).css({
|
823
|
+
position: fixedFullWidth ? 'fixed' : 'absolute',
|
824
|
+
top: fixedFullWidth ? oh : oh + (scrollTop - offset) + 'px',
|
825
|
+
zIndex: 15
|
826
|
+
});
|
827
|
+
} else if (t.isFixed) {
|
828
|
+
t.isFixed = false;
|
829
|
+
bp.removeAttr('style');
|
830
|
+
$([t.$ta, t.$ed]).css({marginTop: 0});
|
831
|
+
$('.' + t.o.prefix + 'fixed-top', $box).css({
|
832
|
+
position: 'absolute',
|
833
|
+
top: oh
|
834
|
+
});
|
835
|
+
}
|
836
|
+
});
|
647
837
|
},
|
648
838
|
|
839
|
+
// Disable editor
|
840
|
+
toggleDisable: function (disable) {
|
841
|
+
var t = this,
|
842
|
+
prefix = t.o.prefix;
|
649
843
|
|
844
|
+
t.disabled = disable;
|
845
|
+
|
846
|
+
if (disable) {
|
847
|
+
t.$ta.attr('disabled', true);
|
848
|
+
} else {
|
849
|
+
t.$ta.removeAttr('disabled');
|
850
|
+
}
|
851
|
+
t.$box.toggleClass(prefix + 'disabled', disable);
|
852
|
+
t.$ed.attr('contenteditable', !disable);
|
853
|
+
},
|
650
854
|
|
651
855
|
// Destroy the editor
|
652
|
-
destroy: function(){
|
856
|
+
destroy: function () {
|
653
857
|
var t = this,
|
654
|
-
|
655
|
-
|
656
|
-
html = t.html();
|
858
|
+
prefix = t.o.prefix,
|
859
|
+
height = t.height;
|
657
860
|
|
658
|
-
if(t.isTextarea)
|
861
|
+
if (t.isTextarea) {
|
659
862
|
t.$box.after(
|
660
|
-
t.$
|
661
|
-
.
|
662
|
-
.
|
863
|
+
t.$ta
|
864
|
+
.css({height: height})
|
865
|
+
.val(t.html())
|
866
|
+
.removeClass(prefix + 'textarea')
|
663
867
|
.show()
|
664
868
|
);
|
665
|
-
else
|
869
|
+
} else {
|
666
870
|
t.$box.after(
|
667
|
-
t.$
|
668
|
-
.css({height:
|
669
|
-
.removeClass(
|
670
|
-
.
|
671
|
-
.html(html)
|
871
|
+
t.$ed
|
872
|
+
.css({height: height})
|
873
|
+
.removeClass(prefix + 'editor')
|
874
|
+
.removeAttr('contenteditable')
|
875
|
+
.html(t.html())
|
672
876
|
.show()
|
673
877
|
);
|
878
|
+
}
|
879
|
+
|
880
|
+
t.$ed.off('dblclick', 'img');
|
881
|
+
|
882
|
+
t.destroyPlugins();
|
674
883
|
|
675
884
|
t.$box.remove();
|
676
|
-
t.$
|
885
|
+
t.$c.removeData('trumbowyg');
|
886
|
+
$('body').removeClass(prefix + 'body-fullscreen');
|
677
887
|
},
|
678
888
|
|
679
889
|
|
680
|
-
|
681
890
|
// Empty the editor
|
682
|
-
empty: function(){
|
683
|
-
this.$
|
891
|
+
empty: function () {
|
892
|
+
this.$ta.val('');
|
684
893
|
this.syncCode(true);
|
685
894
|
},
|
686
895
|
|
687
896
|
|
688
|
-
|
689
897
|
// Function call when click on viewHTML button
|
690
|
-
toggle: function(){
|
898
|
+
toggle: function () {
|
691
899
|
var t = this,
|
692
|
-
|
900
|
+
prefix = t.o.prefix;
|
693
901
|
t.semanticCode(false, true);
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
902
|
+
setTimeout(function () {
|
903
|
+
t.doc.activeElement.blur();
|
904
|
+
t.$box.toggleClass(prefix + 'editor-hidden ' + prefix + 'editor-visible');
|
905
|
+
t.$btnPane.toggleClass(prefix + 'disable');
|
906
|
+
$('.' + prefix + 'viewHTML-button', t.$btnPane).toggleClass(prefix + 'active');
|
907
|
+
if (t.$box.hasClass(prefix + 'editor-visible')) {
|
908
|
+
t.$ta.attr('tabindex', -1);
|
909
|
+
} else {
|
910
|
+
t.$ta.removeAttr('tabindex');
|
911
|
+
}
|
912
|
+
}, 0);
|
698
913
|
},
|
699
914
|
|
700
915
|
// Open dropdown when click on a button which open that
|
701
|
-
dropdown: function(name){
|
916
|
+
dropdown: function (name) {
|
702
917
|
var t = this,
|
703
|
-
|
704
|
-
|
705
|
-
$
|
918
|
+
d = t.doc,
|
919
|
+
prefix = t.o.prefix,
|
920
|
+
$dropdown = $('[data-dropdown=' + name + ']', t.$box),
|
921
|
+
$btn = $('.' + prefix + name + '-button', t.$btnPane),
|
922
|
+
show = $dropdown.is(':hidden');
|
923
|
+
|
924
|
+
$('body', d).trigger('mousedown');
|
706
925
|
|
707
|
-
if(
|
926
|
+
if (show) {
|
708
927
|
var o = $btn.offset().left;
|
709
|
-
$btn.addClass(
|
928
|
+
$btn.addClass(prefix + 'active');
|
710
929
|
|
711
930
|
$dropdown.css({
|
712
931
|
position: 'absolute',
|
713
|
-
top: t.$btnPane.outerHeight(),
|
714
|
-
left: (t.o.fixedFullWidth && t.isFixed) ? o+'px' : (o - t.$btnPane.offset().left)+'px'
|
932
|
+
top: $btn.offset().top - t.$btnPane.offset().top + $btn.outerHeight(),
|
933
|
+
left: (t.o.fixedFullWidth && t.isFixed) ? o + 'px' : (o - t.$btnPane.offset().left) + 'px'
|
715
934
|
}).show();
|
716
935
|
|
717
936
|
$(window).trigger('scroll');
|
718
937
|
|
719
|
-
$('body').on('mousedown', function(){
|
720
|
-
$('.' +
|
721
|
-
$('.' +
|
722
|
-
$('body').off('mousedown');
|
938
|
+
$('body', d).on('mousedown', function () {
|
939
|
+
$('.' + prefix + 'dropdown', d).hide();
|
940
|
+
$('.' + prefix + 'active', d).removeClass(prefix + 'active');
|
941
|
+
$('body', d).off('mousedown');
|
723
942
|
});
|
724
|
-
}
|
725
|
-
$('body').trigger('mousedown');
|
943
|
+
}
|
726
944
|
},
|
727
945
|
|
728
946
|
|
729
|
-
|
730
|
-
|
731
947
|
// HTML Code management
|
732
|
-
html: function(html){
|
948
|
+
html: function (html) {
|
733
949
|
var t = this;
|
734
|
-
if(html){
|
735
|
-
t.$
|
950
|
+
if (html != null) {
|
951
|
+
t.$ta.val(html);
|
736
952
|
t.syncCode(true);
|
737
953
|
return t;
|
738
|
-
}
|
739
|
-
|
954
|
+
}
|
955
|
+
return t.$ta.val();
|
740
956
|
},
|
741
|
-
|
957
|
+
syncTextarea: function () {
|
742
958
|
var t = this;
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
t.$
|
959
|
+
t.$ta.val(t.$ed.text().trim().length > 0 || t.$ed.find('hr,img,embed,input').length > 0 ? t.$ed.html() : '');
|
960
|
+
},
|
961
|
+
syncCode: function (force) {
|
962
|
+
var t = this;
|
963
|
+
if (!force && t.$ed.is(':visible')) {
|
964
|
+
t.syncTextarea();
|
965
|
+
} else {
|
966
|
+
t.$ed.html(t.$ta.val());
|
967
|
+
}
|
968
|
+
|
969
|
+
if (t.o.autogrow) {
|
970
|
+
t.height = t.$ed.height();
|
971
|
+
if (t.height !== t.$ta.css('height')) {
|
972
|
+
t.$ta.css({height: t.height});
|
973
|
+
t.$c.trigger('tbwresize');
|
974
|
+
}
|
751
975
|
}
|
752
976
|
},
|
753
977
|
|
754
978
|
// Analyse and update to semantic code
|
755
979
|
// @param force : force to sync code from textarea
|
756
980
|
// @param full : wrap text nodes in <p>
|
757
|
-
semanticCode: function(force, full){
|
981
|
+
semanticCode: function (force, full) {
|
758
982
|
var t = this;
|
983
|
+
t.saveRange();
|
759
984
|
t.syncCode(force);
|
760
985
|
|
761
|
-
|
986
|
+
$(t.o.tagsToRemove.join(','), t.$ed).remove();
|
987
|
+
|
988
|
+
if (t.o.semantic) {
|
762
989
|
t.semanticTag('b', 'strong');
|
763
990
|
t.semanticTag('i', 'em');
|
764
991
|
t.semanticTag('strike', 'del');
|
765
992
|
|
766
|
-
if(full){
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
993
|
+
if (full) {
|
994
|
+
var inlineElementsSelector = t.o.inlineElementsSelector,
|
995
|
+
blockElementsSelector = ':not(' + inlineElementsSelector + ')';
|
996
|
+
|
997
|
+
// Wrap text nodes in span for easier processing
|
998
|
+
t.$ed.contents().filter(function () {
|
999
|
+
return this.nodeType === 3 && this.nodeValue.trim().length > 0;
|
1000
|
+
}).wrap('<span data-tbw/>');
|
1001
|
+
|
1002
|
+
// Wrap groups of inline elements in paragraphs (recursive)
|
1003
|
+
var wrapInlinesInParagraphsFrom = function ($from) {
|
1004
|
+
if ($from.length !== 0) {
|
1005
|
+
var $finalParagraph = $from.nextUntil(blockElementsSelector).andSelf().wrapAll('<p/>').parent(),
|
1006
|
+
$nextElement = $finalParagraph.nextAll(inlineElementsSelector).first();
|
1007
|
+
$finalParagraph.next('br').remove();
|
1008
|
+
wrapInlinesInParagraphsFrom($nextElement);
|
1009
|
+
}
|
1010
|
+
};
|
1011
|
+
wrapInlinesInParagraphsFrom(t.$ed.children(inlineElementsSelector).first());
|
773
1012
|
|
774
|
-
|
775
|
-
.filter('br').remove();
|
1013
|
+
t.semanticTag('div', 'p', true);
|
776
1014
|
|
777
|
-
|
778
|
-
t.
|
779
|
-
|
1015
|
+
// Unwrap paragraphs content, containing nothing usefull
|
1016
|
+
t.$ed.find('p').filter(function () {
|
1017
|
+
// Don't remove currently being edited element
|
1018
|
+
if (t.range && this === t.range.startContainer) {
|
1019
|
+
return false;
|
1020
|
+
}
|
1021
|
+
return $(this).text().trim().length === 0 && $(this).children().not('br,span').length === 0;
|
1022
|
+
}).contents().unwrap();
|
1023
|
+
|
1024
|
+
// Get rid of temporial span's
|
1025
|
+
$('[data-tbw]', t.$ed).contents().unwrap();
|
1026
|
+
|
1027
|
+
// Remove empty <p>
|
1028
|
+
t.$ed.find('p:empty').remove();
|
780
1029
|
}
|
781
1030
|
|
782
|
-
t
|
1031
|
+
t.restoreRange();
|
1032
|
+
|
1033
|
+
t.syncTextarea();
|
783
1034
|
}
|
784
1035
|
},
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
1036
|
+
|
1037
|
+
semanticTag: function (oldTag, newTag, copyAttributes) {
|
1038
|
+
$(oldTag, this.$ed).each(function () {
|
1039
|
+
var $oldTag = $(this);
|
1040
|
+
$oldTag.wrap('<' + newTag + '/>');
|
1041
|
+
if (copyAttributes) {
|
1042
|
+
$.each($oldTag.prop('attributes'), function () {
|
1043
|
+
$oldTag.parent().attr(this.name, this.value);
|
1044
|
+
});
|
1045
|
+
}
|
1046
|
+
$oldTag.contents().unwrap();
|
790
1047
|
});
|
791
1048
|
},
|
792
1049
|
|
793
|
-
|
794
1050
|
// Function call when user click on "Insert Link"
|
795
|
-
createLink: function(){
|
796
|
-
var t = this
|
797
|
-
|
1051
|
+
createLink: function () {
|
1052
|
+
var t = this,
|
1053
|
+
documentSelection = t.doc.getSelection(),
|
1054
|
+
node = documentSelection.focusNode,
|
1055
|
+
url,
|
1056
|
+
title,
|
1057
|
+
target;
|
1058
|
+
|
1059
|
+
while (['A', 'DIV'].indexOf(node.nodeName) < 0) {
|
1060
|
+
node = node.parentNode;
|
1061
|
+
}
|
1062
|
+
|
1063
|
+
if (node && node.nodeName === 'A') {
|
1064
|
+
var $a = $(node);
|
1065
|
+
url = $a.attr('href');
|
1066
|
+
title = $a.attr('title');
|
1067
|
+
target = $a.attr('target');
|
1068
|
+
var range = t.doc.createRange();
|
1069
|
+
range.selectNode(node);
|
1070
|
+
documentSelection.addRange(range);
|
1071
|
+
}
|
1072
|
+
|
1073
|
+
t.saveRange();
|
1074
|
+
|
798
1075
|
t.openModalInsert(t.lang.createLink, {
|
799
1076
|
url: {
|
800
1077
|
label: 'URL',
|
801
|
-
|
802
|
-
|
1078
|
+
required: true,
|
1079
|
+
value: url
|
803
1080
|
},
|
804
1081
|
title: {
|
805
1082
|
label: t.lang.title,
|
806
|
-
value:
|
1083
|
+
value: title
|
807
1084
|
},
|
808
1085
|
text: {
|
809
1086
|
label: t.lang.text,
|
810
|
-
value: t.
|
1087
|
+
value: t.getRangeText()
|
1088
|
+
},
|
1089
|
+
target: {
|
1090
|
+
label: t.lang.target,
|
1091
|
+
value: target
|
811
1092
|
}
|
812
|
-
}, function(v){ // v is value
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
1093
|
+
}, function (v) { // v is value
|
1094
|
+
var link = $(['<a href="', v.url, '">', v.text, '</a>'].join(''));
|
1095
|
+
if (v.title.length > 0) {
|
1096
|
+
link.attr('title', v.title);
|
1097
|
+
}
|
1098
|
+
if (v.target.length > 0) {
|
1099
|
+
link.attr('target', v.target);
|
1100
|
+
}
|
1101
|
+
t.range.deleteContents();
|
1102
|
+
t.range.insertNode(link[0]);
|
821
1103
|
return true;
|
822
1104
|
});
|
823
1105
|
},
|
824
|
-
|
1106
|
+
unlink: function () {
|
1107
|
+
var t = this,
|
1108
|
+
documentSelection = t.doc.getSelection(),
|
1109
|
+
node = documentSelection.focusNode;
|
1110
|
+
|
1111
|
+
if (documentSelection.isCollapsed) {
|
1112
|
+
while (['A', 'DIV'].indexOf(node.nodeName) < 0) {
|
1113
|
+
node = node.parentNode;
|
1114
|
+
}
|
1115
|
+
|
1116
|
+
if (node && node.nodeName === 'A') {
|
1117
|
+
var range = t.doc.createRange();
|
1118
|
+
range.selectNode(node);
|
1119
|
+
documentSelection.addRange(range);
|
1120
|
+
}
|
1121
|
+
}
|
1122
|
+
t.execCmd('unlink', undefined, undefined, true);
|
1123
|
+
},
|
1124
|
+
insertImage: function () {
|
825
1125
|
var t = this;
|
826
|
-
t.
|
1126
|
+
t.saveRange();
|
827
1127
|
t.openModalInsert(t.lang.insertImage, {
|
828
1128
|
url: {
|
829
1129
|
label: 'URL',
|
830
|
-
value: 'http://',
|
831
1130
|
required: true
|
832
1131
|
},
|
833
1132
|
alt: {
|
834
1133
|
label: t.lang.description,
|
835
|
-
value: t.
|
1134
|
+
value: t.getRangeText()
|
836
1135
|
}
|
837
|
-
}, function(v){ // v are values
|
1136
|
+
}, function (v) { // v are values
|
838
1137
|
t.execCmd('insertImage', v.url);
|
839
|
-
$('img[src="'+v.url+'"]:not([alt])', t.$box).attr('alt', v.alt);
|
1138
|
+
$('img[src="' + v.url + '"]:not([alt])', t.$box).attr('alt', v.alt);
|
840
1139
|
return true;
|
841
1140
|
});
|
842
1141
|
},
|
1142
|
+
fullscreen: function () {
|
1143
|
+
var t = this,
|
1144
|
+
prefix = t.o.prefix,
|
1145
|
+
fullscreenCssClass = prefix + 'fullscreen',
|
1146
|
+
isFullscreen;
|
1147
|
+
|
1148
|
+
t.$box.toggleClass(fullscreenCssClass);
|
1149
|
+
isFullscreen = t.$box.hasClass(fullscreenCssClass);
|
1150
|
+
$('body').toggleClass(prefix + 'body-fullscreen', isFullscreen);
|
1151
|
+
$(window).trigger('scroll');
|
1152
|
+
t.$c.trigger('tbw' + (isFullscreen ? 'open' : 'close') + 'fullscreen');
|
1153
|
+
},
|
843
1154
|
|
844
1155
|
|
845
1156
|
/*
|
@@ -847,56 +1158,69 @@
|
|
847
1158
|
* else try to call anonymous function
|
848
1159
|
* and finaly native execCommand
|
849
1160
|
*/
|
850
|
-
execCmd: function(cmd, param){
|
1161
|
+
execCmd: function (cmd, param, forceCss, skipTrumbowyg) {
|
851
1162
|
var t = this;
|
852
|
-
|
853
|
-
|
1163
|
+
skipTrumbowyg = !!skipTrumbowyg || '';
|
1164
|
+
|
1165
|
+
if (cmd !== 'dropdown') {
|
1166
|
+
t.$ed.focus();
|
1167
|
+
}
|
1168
|
+
|
1169
|
+
t.doc.execCommand('styleWithCSS', false, forceCss || false);
|
854
1170
|
|
855
1171
|
try {
|
856
|
-
t[cmd](param);
|
857
|
-
} catch(
|
1172
|
+
t[cmd + skipTrumbowyg](param);
|
1173
|
+
} catch (c) {
|
858
1174
|
try {
|
859
|
-
cmd(param
|
860
|
-
} catch(e2){
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
else if(cmd == 'formatBlock' && (navigator.userAgent.indexOf('MSIE') !== -1 || navigator.appVersion.indexOf('Trident/') > 0))
|
1175
|
+
cmd(param);
|
1176
|
+
} catch (e2) {
|
1177
|
+
if (cmd === 'insertHorizontalRule') {
|
1178
|
+
param = undefined;
|
1179
|
+
} else if (cmd === 'formatBlock' && (navigator.userAgent.indexOf('MSIE') !== -1 || navigator.appVersion.indexOf('Trident/') !== -1)) {
|
865
1180
|
param = '<' + param + '>';
|
1181
|
+
}
|
866
1182
|
|
867
|
-
|
1183
|
+
t.doc.execCommand(cmd, false, param);
|
1184
|
+
|
1185
|
+
t.syncCode();
|
1186
|
+
t.semanticCode(false, true);
|
1187
|
+
}
|
1188
|
+
|
1189
|
+
if (cmd !== 'dropdown') {
|
1190
|
+
t.updateButtonPaneStatus();
|
1191
|
+
t.$c.trigger('tbwchange');
|
868
1192
|
}
|
869
1193
|
}
|
870
|
-
t.syncCode();
|
871
1194
|
},
|
872
1195
|
|
873
1196
|
|
874
1197
|
// Open a modal box
|
875
|
-
openModal: function(title, content){
|
1198
|
+
openModal: function (title, content) {
|
876
1199
|
var t = this,
|
877
|
-
|
1200
|
+
prefix = t.o.prefix;
|
878
1201
|
|
879
1202
|
// No open a modal box when exist other modal box
|
880
|
-
if($('.' +
|
1203
|
+
if ($('.' + prefix + 'modal-box', t.$box).length > 0) {
|
881
1204
|
return false;
|
1205
|
+
}
|
882
1206
|
|
883
|
-
t.
|
1207
|
+
t.saveRange();
|
884
1208
|
t.showOverlay();
|
885
1209
|
|
886
1210
|
// Disable all btnPane btns
|
887
|
-
t.$btnPane.addClass(
|
1211
|
+
t.$btnPane.addClass(prefix + 'disable');
|
888
1212
|
|
889
1213
|
// Build out of ModalBox, it's the mask for animations
|
890
1214
|
var $modal = $('<div/>', {
|
891
|
-
class:
|
1215
|
+
class: prefix + 'modal ' + prefix + 'fixed-top'
|
892
1216
|
}).css({
|
893
|
-
top:
|
1217
|
+
top: t.$btnPane.height()
|
894
1218
|
}).appendTo(t.$box);
|
895
1219
|
|
896
|
-
// Click on
|
897
|
-
t.$overlay.one('click', function(
|
898
|
-
|
899
|
-
|
1220
|
+
// Click on overlay close modal by cancelling them
|
1221
|
+
t.$overlay.one('click', function () {
|
1222
|
+
$modal.trigger('tbwcancel');
|
1223
|
+
return false;
|
900
1224
|
});
|
901
1225
|
|
902
1226
|
// Build the form
|
@@ -904,41 +1228,43 @@
|
|
904
1228
|
action: '',
|
905
1229
|
html: content
|
906
1230
|
})
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
1231
|
+
.on('submit', function () {
|
1232
|
+
$modal.trigger('tbwconfirm');
|
1233
|
+
return false;
|
1234
|
+
})
|
1235
|
+
.on('reset', function () {
|
1236
|
+
$modal.trigger('tbwcancel');
|
1237
|
+
return false;
|
1238
|
+
});
|
915
1239
|
|
916
1240
|
|
917
1241
|
// Build ModalBox and animate to show them
|
918
1242
|
var $box = $('<div/>', {
|
919
|
-
class:
|
1243
|
+
class: prefix + 'modal-box',
|
920
1244
|
html: $form
|
921
1245
|
})
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
|
1246
|
+
.css({
|
1247
|
+
top: '-' + t.$btnPane.outerHeight() + 'px',
|
1248
|
+
opacity: 0
|
1249
|
+
})
|
1250
|
+
.appendTo($modal)
|
1251
|
+
.animate({
|
1252
|
+
top: 0,
|
1253
|
+
opacity: 1
|
1254
|
+
}, 100);
|
931
1255
|
|
932
1256
|
|
933
1257
|
// Append title
|
934
1258
|
$('<span/>', {
|
935
1259
|
text: title,
|
936
|
-
class:
|
1260
|
+
class: prefix + 'modal-title'
|
937
1261
|
}).prependTo($box);
|
938
1262
|
|
1263
|
+
$modal.height($box.outerHeight() + 10);
|
1264
|
+
|
939
1265
|
|
940
1266
|
// Focus in modal box
|
941
|
-
$
|
1267
|
+
$('input:first', $box).focus();
|
942
1268
|
|
943
1269
|
|
944
1270
|
// Append Confirm and Cancel buttons
|
@@ -951,146 +1277,246 @@
|
|
951
1277
|
return $modal;
|
952
1278
|
},
|
953
1279
|
// @param n is name of modal
|
954
|
-
buildModalBtn: function(n, modal){
|
1280
|
+
buildModalBtn: function (n, $modal) {
|
955
1281
|
var t = this,
|
956
|
-
|
1282
|
+
prefix = t.o.prefix;
|
957
1283
|
|
958
1284
|
return $('<button/>', {
|
959
|
-
class:
|
1285
|
+
class: prefix + 'modal-button ' + prefix + 'modal-' + n,
|
960
1286
|
type: n,
|
961
1287
|
text: t.lang[n] || n
|
962
|
-
}).appendTo(
|
1288
|
+
}).appendTo($('form', $modal));
|
963
1289
|
},
|
964
1290
|
// close current modal box
|
965
|
-
closeModal: function(){
|
1291
|
+
closeModal: function () {
|
966
1292
|
var t = this,
|
967
|
-
|
1293
|
+
prefix = t.o.prefix;
|
968
1294
|
|
969
|
-
t.$btnPane.removeClass(
|
1295
|
+
t.$btnPane.removeClass(prefix + 'disable');
|
970
1296
|
t.$overlay.off();
|
971
1297
|
|
972
|
-
|
1298
|
+
// Find the modal box
|
1299
|
+
var $mb = $('.' + prefix + 'modal-box', t.$box);
|
973
1300
|
|
974
|
-
$
|
975
|
-
top: '-' + $
|
976
|
-
},
|
977
|
-
$
|
1301
|
+
$mb.animate({
|
1302
|
+
top: '-' + $mb.height()
|
1303
|
+
}, 100, function () {
|
1304
|
+
$mb.parent().remove();
|
978
1305
|
t.hideOverlay();
|
979
1306
|
});
|
1307
|
+
|
1308
|
+
t.restoreRange();
|
980
1309
|
},
|
981
1310
|
// Preformated build and management modal
|
982
|
-
openModalInsert: function(title, fields, cmd){
|
1311
|
+
openModalInsert: function (title, fields, cmd) {
|
983
1312
|
var t = this,
|
984
|
-
|
1313
|
+
prefix = t.o.prefix,
|
985
1314
|
lg = t.lang,
|
986
|
-
html = ''
|
1315
|
+
html = '',
|
1316
|
+
CONFIRM_EVENT = 'tbwconfirm';
|
987
1317
|
|
988
|
-
|
989
|
-
var
|
990
|
-
|
1318
|
+
$.each(fields, function (fieldName, field) {
|
1319
|
+
var l = field.label,
|
1320
|
+
n = field.name || fieldName;
|
991
1321
|
|
992
|
-
|
993
|
-
|
994
|
-
|
995
|
-
|
996
|
-
fd.pattern = /^(http|https):\/\/([\w~#!:.?+=&%@!\-\/]+)$/;
|
997
|
-
fd.patternError = lg.invalidUrl;
|
998
|
-
}
|
999
|
-
|
1000
|
-
html += '<label><input type="'+(fd.type || 'text')+'" name="'+fd.name+'" value="'+(fd.value || '')+'"><span class="'+pfx+'input-infos"><span>'+label+'</span></span></label>';
|
1001
|
-
}
|
1322
|
+
html += '<label><input type="' + (field.type || 'text') + '" name="' + n + '" value="' + (field.value || '').replace(/"/g, '"') + '"><span class="' + prefix + 'input-infos"><span>' +
|
1323
|
+
((!l) ? (lg[fieldName] ? lg[fieldName] : fieldName) : (lg[l] ? lg[l] : l)) +
|
1324
|
+
'</span></span></label>';
|
1325
|
+
});
|
1002
1326
|
|
1003
1327
|
return t.openModal(title, html)
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
1014
|
-
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1328
|
+
.on(CONFIRM_EVENT, function () {
|
1329
|
+
var $form = $('form', $(this)),
|
1330
|
+
valid = true,
|
1331
|
+
values = {};
|
1332
|
+
|
1333
|
+
$.each(fields, function (fieldName, field) {
|
1334
|
+
var $field = $('input[name="' + fieldName + '"]', $form);
|
1335
|
+
|
1336
|
+
values[fieldName] = $.trim($field.val());
|
1337
|
+
|
1338
|
+
// Validate value
|
1339
|
+
if (field.required && values[fieldName] === '') {
|
1340
|
+
valid = false;
|
1341
|
+
t.addErrorOnModalField($field, t.lang.required);
|
1342
|
+
} else if (field.pattern && !field.pattern.test(values[fieldName])) {
|
1343
|
+
valid = false;
|
1344
|
+
t.addErrorOnModalField($field, field.patternError);
|
1345
|
+
}
|
1346
|
+
});
|
1023
1347
|
|
1024
|
-
|
1025
|
-
|
1348
|
+
if (valid) {
|
1349
|
+
t.restoreRange();
|
1026
1350
|
|
1027
|
-
|
1028
|
-
|
1029
|
-
|
1030
|
-
|
1351
|
+
if (cmd(values, fields)) {
|
1352
|
+
t.syncCode();
|
1353
|
+
t.$c.trigger('tbwchange');
|
1354
|
+
t.closeModal();
|
1355
|
+
$(this).off(CONFIRM_EVENT);
|
1356
|
+
}
|
1031
1357
|
}
|
1032
|
-
}
|
1033
|
-
|
1034
|
-
|
1035
|
-
|
1036
|
-
|
1037
|
-
t.restoreSelection();
|
1038
|
-
});
|
1358
|
+
})
|
1359
|
+
.one('tbwcancel', function () {
|
1360
|
+
$(this).off(CONFIRM_EVENT);
|
1361
|
+
t.closeModal();
|
1362
|
+
});
|
1039
1363
|
},
|
1040
|
-
addErrorOnModalField: function($field, err){
|
1041
|
-
var
|
1364
|
+
addErrorOnModalField: function ($field, err) {
|
1365
|
+
var prefix = this.o.prefix,
|
1042
1366
|
$label = $field.parent();
|
1043
1367
|
|
1044
|
-
$field
|
1045
|
-
|
1046
|
-
|
1368
|
+
$field
|
1369
|
+
.on('change keyup', function () {
|
1370
|
+
$label.removeClass(prefix + 'input-error');
|
1371
|
+
});
|
1372
|
+
|
1047
1373
|
$label
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1374
|
+
.addClass(prefix + 'input-error')
|
1375
|
+
.find('input+span')
|
1376
|
+
.append(
|
1377
|
+
$('<span/>', {
|
1378
|
+
class: prefix + 'msg-error',
|
1379
|
+
text: err
|
1380
|
+
})
|
1381
|
+
);
|
1055
1382
|
},
|
1056
1383
|
|
1057
1384
|
|
1385
|
+
// Range management
|
1386
|
+
saveRange: function () {
|
1387
|
+
var t = this,
|
1388
|
+
documentSelection = t.doc.getSelection();
|
1389
|
+
|
1390
|
+
t.range = null;
|
1391
|
+
|
1392
|
+
if (documentSelection.rangeCount) {
|
1393
|
+
var savedRange = t.range = documentSelection.getRangeAt(0),
|
1394
|
+
range = t.doc.createRange(),
|
1395
|
+
rangeStart;
|
1396
|
+
range.selectNodeContents(t.$ed[0]);
|
1397
|
+
range.setEnd(savedRange.startContainer, savedRange.startOffset);
|
1398
|
+
rangeStart = (range + '').length;
|
1399
|
+
t.metaRange = {
|
1400
|
+
start: rangeStart,
|
1401
|
+
end: rangeStart + (savedRange + '').length
|
1402
|
+
};
|
1403
|
+
}
|
1404
|
+
},
|
1405
|
+
restoreRange: function () {
|
1406
|
+
var t = this,
|
1407
|
+
metaRange = t.metaRange,
|
1408
|
+
savedRange = t.range,
|
1409
|
+
documentSelection = t.doc.getSelection(),
|
1410
|
+
range;
|
1411
|
+
|
1412
|
+
if (!savedRange) {
|
1413
|
+
return;
|
1414
|
+
}
|
1415
|
+
|
1416
|
+
if (metaRange && metaRange.start !== metaRange.end) { // Algorithm from http://jsfiddle.net/WeWy7/3/
|
1417
|
+
var charIndex = 0,
|
1418
|
+
nodeStack = [t.$ed[0]],
|
1419
|
+
node,
|
1420
|
+
foundStart = false,
|
1421
|
+
stop = false;
|
1422
|
+
|
1423
|
+
range = t.doc.createRange();
|
1424
|
+
|
1425
|
+
while (!stop && (node = nodeStack.pop())) {
|
1426
|
+
if (node.nodeType === 3) {
|
1427
|
+
var nextCharIndex = charIndex + node.length;
|
1428
|
+
if (!foundStart && metaRange.start >= charIndex && metaRange.start <= nextCharIndex) {
|
1429
|
+
range.setStart(node, metaRange.start - charIndex);
|
1430
|
+
foundStart = true;
|
1431
|
+
}
|
1432
|
+
if (foundStart && metaRange.end >= charIndex && metaRange.end <= nextCharIndex) {
|
1433
|
+
range.setEnd(node, metaRange.end - charIndex);
|
1434
|
+
stop = true;
|
1435
|
+
}
|
1436
|
+
charIndex = nextCharIndex;
|
1437
|
+
} else {
|
1438
|
+
var cn = node.childNodes,
|
1439
|
+
i = cn.length;
|
1440
|
+
|
1441
|
+
while (i > 0) {
|
1442
|
+
i -= 1;
|
1443
|
+
nodeStack.push(cn[i]);
|
1444
|
+
}
|
1445
|
+
}
|
1446
|
+
}
|
1447
|
+
}
|
1058
1448
|
|
1449
|
+
documentSelection.removeAllRanges();
|
1450
|
+
documentSelection.addRange(range || savedRange);
|
1451
|
+
},
|
1452
|
+
getRangeText: function () {
|
1453
|
+
return this.range + '';
|
1454
|
+
},
|
1059
1455
|
|
1060
|
-
|
1061
|
-
saveSelection: function(){
|
1456
|
+
updateButtonPaneStatus: function () {
|
1062
1457
|
var t = this,
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
1069
|
-
|
1070
|
-
|
1071
|
-
|
1458
|
+
prefix = t.o.prefix,
|
1459
|
+
tags = t.getTagsRecursive(t.doc.getSelection().focusNode.parentNode),
|
1460
|
+
activeClasses = prefix + 'active-button ' + prefix + 'active';
|
1461
|
+
|
1462
|
+
$('.' + prefix + 'active-button', t.$btnPane).removeClass(activeClasses);
|
1463
|
+
$.each(tags, function (i, tag) {
|
1464
|
+
var btnName = t.tagToButton[tag.toLowerCase()],
|
1465
|
+
$btn = $('.' + prefix + btnName + '-button', t.$btnPane);
|
1466
|
+
|
1467
|
+
if ($btn.length > 0) {
|
1468
|
+
$btn.addClass(activeClasses);
|
1469
|
+
} else {
|
1470
|
+
try {
|
1471
|
+
$btn = $('.' + prefix + 'dropdown .' + prefix + btnName + '-dropdown-button', t.$box);
|
1472
|
+
var dropdownBtnName = $btn.parent().data('dropdown');
|
1473
|
+
$('.' + prefix + dropdownBtnName + '-button', t.$box).addClass(activeClasses);
|
1474
|
+
} catch (e) {
|
1475
|
+
}
|
1476
|
+
}
|
1477
|
+
});
|
1072
1478
|
},
|
1073
|
-
|
1074
|
-
var
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1479
|
+
getTagsRecursive: function (element, tags) {
|
1480
|
+
var t = this;
|
1481
|
+
tags = tags || [];
|
1482
|
+
|
1483
|
+
var tag = element.tagName;
|
1484
|
+
if (tag === 'DIV') {
|
1485
|
+
return tags;
|
1486
|
+
}
|
1487
|
+
if (tag === 'P' && element.style.textAlign !== '') {
|
1488
|
+
tags.push(element.style.textAlign);
|
1082
1489
|
}
|
1083
|
-
},
|
1084
1490
|
|
1491
|
+
$.each(t.tagHandlers, function (i, tagHandler) {
|
1492
|
+
tags = tags.concat(tagHandler(element, t));
|
1493
|
+
});
|
1085
1494
|
|
1495
|
+
tags.push(tag);
|
1086
1496
|
|
1087
|
-
|
1088
|
-
|
1089
|
-
var exprTablet = new RegExp("(iPad|webOS)"),
|
1090
|
-
exprMobile = new RegExp("(iPhone|iPod|Android|BlackBerry|Windows Phone|ZuneWP7)"),
|
1091
|
-
ua = navigator.userAgent;
|
1497
|
+
return t.getTagsRecursive(element.parentNode, tags);
|
1498
|
+
},
|
1092
1499
|
|
1093
|
-
|
1500
|
+
// Plugins
|
1501
|
+
initPlugins: function () {
|
1502
|
+
var t = this;
|
1503
|
+
t.loadedPlugins = [];
|
1504
|
+
$.each($.trumbowyg.plugins, function (name, plugin) {
|
1505
|
+
if (!plugin.shouldInit || plugin.shouldInit(t)) {
|
1506
|
+
plugin.init(t);
|
1507
|
+
if (plugin.tagHandler) {
|
1508
|
+
t.tagHandlers.push(plugin.tagHandler);
|
1509
|
+
}
|
1510
|
+
t.loadedPlugins.push(plugin);
|
1511
|
+
}
|
1512
|
+
});
|
1513
|
+
},
|
1514
|
+
destroyPlugins: function () {
|
1515
|
+
$.each(this.loadedPlugins, function (i, plugin) {
|
1516
|
+
if (plugin.destroy) {
|
1517
|
+
plugin.destroy();
|
1518
|
+
}
|
1519
|
+
});
|
1094
1520
|
}
|
1095
1521
|
};
|
1096
|
-
})(window, document, jQuery);
|
1522
|
+
})(navigator, window, document, jQuery);
|