PluginProbe
wpForo Forum / 1.4.11
wpForo Forum v1.4.11
3.1.6 3.1.5 3.1.4 3.1.2 3.1.1 3.1.0 3.0.9 3.0.8 3.0.7 trunk 1.0.0 1.0.1 1.0.2 1.1.0 1.1.1 1.1.2 1.2.0 1.3.0 1.3.1 1.4.0 1.4.1 1.4.10 1.4.11 1.4.12 1.4.13 All 138 releases
wpforo / wpf-assets / js / tinymce-link.js

tinymce-link.js in wpForo Forum 1.4.11, at wpf-assets/js/tinymce-link.js

408 lines 9.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function() {
2
3 tinymce.create('tinymce.plugins.wpforo_link_button', {
4 /**
5 * Initializes the plugin, this will be executed after the plugin has been created.
6 * This call is done before the editor instance has finished it's initialization so use the onInit event
7 * of the editor instance to intercept that event.
8 *
9 * @param {tinymce.Editor} ed Editor instance that the plugin is initialized in.
10 * @param {string} url Absolute URL to where the plugin is located.
11 */
12 init : function(ed, url) {
13
14
15 function createLinkList(callback) {
16 return function() {
17 var linkList = ed.settings.link_list;
18
19 if (typeof linkList == "string") {
20 tinymce.util.XHR.send({
21 url: linkList,
22 success: function(text) {
23 callback(tinymce.util.JSON.parse(text));
24 }
25 });
26 } else if (typeof linkList == "function") {
27 linkList(callback);
28 } else {
29 callback(linkList);
30 }
31 };
32 }
33
34 function buildListItems(inputList, itemCallback, startItems) {
35 function appendItems(values, output) {
36 output = output || [];
37
38 tinymce.each(values, function(item) {
39 var menuItem = {text: item.text || item.title};
40
41 if (item.menu) {
42 menuItem.menu = appendItems(item.menu);
43 } else {
44 menuItem.value = item.value;
45
46 if (itemCallback) {
47 itemCallback(menuItem);
48 }
49 }
50
51 output.push(menuItem);
52 });
53
54 return output;
55 }
56
57 return appendItems(inputList, startItems || []);
58 }
59
60 function showDialog(linkList) {
61 var data = {}, selection = ed.selection, dom = ed.dom, selectedElm, anchorElm, initialText;
62 var win, onlyText, textListCtrl, linkListCtrl, relListCtrl, targetListCtrl, classListCtrl, linkTitleCtrl, value;
63
64 function linkListChangeHandler(e) {
65 var textCtrl = win.find('#text');
66
67 if (!textCtrl.value() || (e.lastControl && textCtrl.value() == e.lastControl.text())) {
68 textCtrl.value(e.control.text());
69 }
70
71 win.find('#href').value(e.control.value());
72 }
73
74 function buildAnchorListControl(url) {
75 var anchorList = [];
76
77 tinymce.each(ed.dom.select('a:not([href])'), function(anchor) {
78 var id = anchor.name || anchor.id;
79
80 if (id) {
81 anchorList.push({
82 text: id,
83 value: '#' + id,
84 selected: url.indexOf('#' + id) != -1
85 });
86 }
87 });
88
89 if (anchorList.length) {
90 anchorList.unshift({text: 'None', value: ''});
91
92 return {
93 name: 'anchor',
94 type: 'listbox',
95 label: 'Anchors',
96 values: anchorList,
97 onselect: linkListChangeHandler
98 };
99 }
100 }
101
102 function updateText() {
103 if (!initialText && data.text.length === 0 && onlyText) {
104 this.parent().parent().find('#text')[0].value(this.value());
105 }
106 }
107
108 function urlChange(e) {
109 var meta = e.meta || {};
110
111 if (linkListCtrl) {
112 linkListCtrl.value(ed.convertURL(this.value(), 'href'));
113 }
114
115 tinymce.each(e.meta, function(value, key) {
116 win.find('#' + key).value(value);
117 });
118
119 if (!meta.text) {
120 updateText.call(this);
121 }
122 }
123
124 function isOnlyTextSelected(anchorElm) {
125 var html = selection.getContent();
126
127 // Partial html and not a fully selected anchor element
128 if (/</.test(html) && (!/^<a [^>]+>[^<]+<\/a>$/.test(html) || html.indexOf('href=') == -1)) {
129 return false;
130 }
131
132 if (anchorElm) {
133 var nodes = anchorElm.childNodes, i;
134
135 if (nodes.length === 0) {
136 return false;
137 }
138
139 for (i = nodes.length - 1; i >= 0; i--) {
140 if (nodes[i].nodeType != 3) {
141 return false;
142 }
143 }
144 }
145
146 return true;
147 }
148
149 selectedElm = selection.getNode();
150 anchorElm = dom.getParent(selectedElm, 'a[href]');
151 onlyText = isOnlyTextSelected();
152
153 data.text = initialText = anchorElm ? (anchorElm.innerText || anchorElm.textContent) : selection.getContent({format: 'text'});
154 data.href = anchorElm ? dom.getAttrib(anchorElm, 'href') : '';
155
156 if (anchorElm) {
157 data.target = dom.getAttrib(anchorElm, 'target');
158 } else if (ed.settings.default_link_target) {
159 data.target = ed.settings.default_link_target;
160 }
161
162 if ((value = dom.getAttrib(anchorElm, 'rel'))) {
163 data.rel = value;
164 }
165
166 if ((value = dom.getAttrib(anchorElm, 'class'))) {
167 data['class'] = value;
168 }
169
170 if ((value = dom.getAttrib(anchorElm, 'title'))) {
171 data.title = value;
172 }
173
174 if (onlyText) {
175 textListCtrl = {
176 name: 'text',
177 type: 'textbox',
178 size: 40,
179 label: 'Link Text',
180 onchange: function() {
181 data.text = this.value();
182 }
183 };
184 }
185
186 if (linkList) {
187 linkListCtrl = {
188 type: 'listbox',
189 label: 'Link list',
190 values: buildListItems(
191 linkList,
192 function(item) {
193 item.value = ed.convertURL(item.value || item.url, 'href');
194 },
195 [{text: 'None', value: ''}]
196 ),
197 onselect: linkListChangeHandler,
198 value: ed.convertURL(data.href, 'href'),
199 onPostRender: function() {
200 /*eslint consistent-this:0*/
201 linkListCtrl = this;
202 }
203 };
204 }
205
206 if (ed.settings.target_list !== false) {
207 targetListCtrl = {
208 name: 'target',
209 type: 'checkbox',
210 checked: true,
211 text: 'Open link in a new tab'
212 };
213 }
214
215 if (ed.settings.rel_list) {
216 relListCtrl = {
217 name: 'rel',
218 type: 'listbox',
219 label: 'Rel',
220 values: buildListItems(ed.settings.rel_list)
221 };
222 }
223
224 if (ed.settings.link_class_list) {
225 classListCtrl = {
226 name: 'class',
227 type: 'listbox',
228 label: 'Class',
229 values: buildListItems(
230 ed.settings.link_class_list,
231 function(item) {
232 if (item.value) {
233 item.textStyle = function() {
234 return ed.formatter.getCssText({inline: 'a', classes: [item.value]});
235 };
236 }
237 }
238 )
239 };
240 }
241
242 if (ed.settings.link_title !== false) {
243 linkTitleCtrl = {
244 name: 'title',
245 type: 'textbox',
246 label: 'Title',
247 value: data.title
248 };
249 }
250
251 win = ed.windowManager.open({
252 title: 'Insert link',
253 data: data,
254 body: [
255 {
256 name: 'href',
257 type: 'filepicker',
258 filetype: 'file',
259 size: 40,
260 autofocus: true,
261 label: 'URL',
262 onchange: urlChange,
263 onkeyup: updateText
264 },
265 textListCtrl,
266 linkTitleCtrl,
267 buildAnchorListControl(data.href),
268 linkListCtrl,
269 relListCtrl,
270 targetListCtrl,
271 classListCtrl
272 ],
273 onSubmit: function(e) {
274 /*eslint dot-notation: 0*/
275 var href;
276
277 data = tinymce.extend(data, e.data);
278 href = data.href;
279 if ( href && ! /^(?:[a-z]+:|#|\?|\.|\/)/.test( href ) ) {
280 href = 'http://' + href;
281 }
282
283 // Delay confirm since onSubmit will move focus
284 function delayedConfirm(message, callback) {
285 var rng = ed.selection.getRng();
286
287 tinymce.util.Delay.setEditorTimeout(editor, function() {
288 ed.windowManager.confirm(message, function(state) {
289 ed.selection.setRng(rng);
290 callback(state);
291 });
292 });
293 }
294
295 function insertLink() {
296 var linkAttrs = {
297 href: href,
298 target: data.target ? data.target : null,
299 rel: data.rel ? data.rel : null,
300 "class": data["class"] ? data["class"] : null,
301 title: data.title ? data.title : null
302 };
303
304 if (anchorElm) {
305 ed.focus();
306
307 if (onlyText && data.text != initialText) {
308 if ("innerText" in anchorElm) {
309 anchorElm.innerText = data.text;
310 } else {
311 anchorElm.textContent = data.text;
312 }
313 }
314
315 dom.setAttribs(anchorElm, linkAttrs);
316
317 selection.select(anchorElm);
318 ed.undoManager.add();
319 } else {
320 if (onlyText) {
321 ed.insertContent(dom.createHTML('a', linkAttrs, dom.encode(data.text)));
322 } else {
323 ed.execCommand('mceInsertLink', false, linkAttrs);
324 }
325 }
326 }
327
328 if (!href) {
329 ed.execCommand('unlink');
330 return;
331 }
332
333 // Is email and not //user@domain.com
334 if (href.indexOf('@') > 0 && href.indexOf('//') == -1 && href.indexOf('mailto:') == -1) {
335 delayedConfirm(
336 'The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?',
337 function(state) {
338 if (state) {
339 href = 'mailto:' + href;
340 }
341
342 insertLink();
343 }
344 );
345
346 return;
347 }
348
349 // Is not protocol prefixed
350 if ((ed.settings.link_assume_external_targets && !/^\w+:/i.test(href)) ||
351 (!ed.settings.link_assume_external_targets && /^\s*www[\.|\d\.]/i.test(href))) {
352 delayedConfirm(
353 'The URL you entered seems to be an external link. Do you want to add the required http:// prefix?',
354 function(state) {
355 if (state) {
356 href = 'http://' + href;
357 }
358
359 insertLink();
360 }
361 );
362
363 return;
364 }
365
366 insertLink();
367 }
368 });
369 }
370
371 ed.addButton('link', {
372 icon: 'link',
373 tooltip: 'Insert/edit link',
374 shortcut: 'Meta+K',
375 onclick: createLinkList(showDialog),
376 stateSelector: 'a[href]'
377 });
378
379 ed.addButton('unlink', {
380 icon: 'unlink',
381 tooltip: 'Remove link',
382 cmd: 'unlink',
383 stateSelector: 'a[href]'
384 });
385
386 ed.addShortcut('Meta+K', '', createLinkList(showDialog));
387 ed.addCommand('mceLink', createLinkList(showDialog));
388
389 this.showDialog = showDialog;
390
391 ed.addMenuItem('link', {
392 icon: 'link',
393 text: 'Insert/edit link',
394 shortcut: 'Meta+K',
395 onclick: createLinkList(showDialog),
396 stateSelector: 'a[href]',
397 context: 'insert',
398 prependToContext: true
399 });
400
401
402 },
403 });
404
405 // Register plugin
406 tinymce.PluginManager.add('wpforo_link_button', tinymce.plugins.wpforo_link_button);
407
408 })();