Completed
Push — development ( 57103e...96e27e )
by Stephen
17s
created

ml   B

Complexity

Conditions 3
Paths 4

Size

Total Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 4
nop 3
dl 0
loc 25
rs 8.8571
c 0
b 0
f 0

1 Function

Rating   Name   Duplication   Size   Complexity  
A tml 0 7 1
1
/*!
2
 * @name      ElkArte Forum
3
 * @copyright ElkArte Forum contributors
4
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause
5
 *
6
 * This file contains code covered by:
7
 * copyright:	2011 Simple Machines (http://www.simplemachines.org)
8
 * license:		BSD, See included LICENSE.TXT for terms and conditions.
9
 *
10
 * @version 2.0 dev
11
 */
12
13
/** global: elk_session_var, elk_session_id, ila_filename, elk_scripturl  */
14
15
/**
16
 * Extension functions to provide ElkArte compatibility with sceditor
17
 */
18
(function ($) {
19
	var extensionMethods = {
20
		addEvent: function (id, event, func) {
21
			var current_event = event,
0 ignored issues
show
Unused Code introduced by
The variable current_event seems to be never used. Consider removing it.
Loading history...
22
				$_id = $('#' + id);
23
24
			$_id.parent().on(event, 'textarea', func);
25
26
			var oIframe = $_id.parent().find('iframe')[0],
27
				oIframeWindow = oIframe.contentWindow;
28
29
			if (oIframeWindow !== null && oIframeWindow.document) {
30
				var oIframeDoc = oIframeWindow.document,
31
					oIframeBody = oIframeDoc.body;
32
33
				$(oIframeBody).on(event, func);
34
			}
35
		},
36
		InsertText: function (text, bClear) {
37
			var bIsSource = this.inSourceMode();
38
39
			if (!bIsSource)
40
				this.toggleSourceMode();
41
42
			var current_value = this.getSourceEditorValue(false),
43
				iEmpty = current_value.length;
44
45
			current_value = bClear ? text + "\n" : current_value + (iEmpty > 0 ? "\n" : "") + text + "\n";
46
			this.setSourceEditorValue(current_value);
47
48
			if (!bIsSource)
49
				this.toggleSourceMode();
50
		},
51
		getText: function (filter) {
52
			var current_value = '';
53
54
			if (this.inSourceMode())
55
				current_value = this.getSourceEditorValue(false);
56
			else
57
				current_value = this.getWysiwygEditorValue(filter);
58
59
			return current_value;
60
		},
61
		appendEmoticon: function (code, emoticon) {
62
			if (emoticon === '')
63
				line.append($('<br />'));
0 ignored issues
show
Bug introduced by
The variable line seems to be never declared. If this is a global, consider adding a /** global: line */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
64
			else {
65
				$img = $('<img />')
0 ignored issues
show
Bug introduced by
The variable $img seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.$img.
Loading history...
66
					.attr({
67
						src: emoticon.url || emoticon,
68
						alt: code,
69
						title: emoticon.tooltip || emoticon
70
					})
71
					.on('click', function (e) {
72
						var start = '',
73
							end = '';
74
75
						if (base.opts.emoticonsCompat) {
0 ignored issues
show
Bug introduced by
The variable base seems to be never declared. If this is a global, consider adding a /** global: base */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
76
							start = '<span> ';
77
							end = ' </span>';
78
						}
79
80
						if (base.inSourceMode())
81
							base.sourceEditorInsertText(' ' + $(this).attr('alt') + ' ');
82
						else
83
							base.wysiwygEditorInsertHtml(start + '<img src="' + $(this).attr("src") + '" data-sceditor-emoticon="' + $(this).attr('alt') + '" />' + end);
84
85
						e.preventDefault();
86
					});
87
				$wrapper = $('<span class="smiley"></span>').append($img);
0 ignored issues
show
Bug introduced by
The variable $wrapper seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.$wrapper.
Loading history...
88
				line.append($wrapper);
0 ignored issues
show
Bug introduced by
The variable line seems to be never declared. If this is a global, consider adding a /** global: line */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
89
			}
90
		},
91
		storeLastState: function () {
92
			this.wasSource = this.inSourceMode();
93
		},
94
		setTextMode: function () {
95
			if (!this.inSourceMode())
96
				this.toggleSourceMode();
97
		},
98
		createPermanentDropDown: function () {
99
			var emoticons = $.extend({}, this.opts.emoticons.dropdown);
100
101
			base = this;
0 ignored issues
show
Bug introduced by
The variable base seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.base.
Loading history...
102
			content = $('<div class="sceditor-insertemoticon" />');
0 ignored issues
show
Bug introduced by
The variable content seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.content.
Loading history...
103
			line = $('<div id="sceditor-smileycontainer" />');
0 ignored issues
show
Bug introduced by
The variable line seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.line.
Loading history...
104
105
			// For any smileys that go in the more popup
106
			if (!$.isEmptyObject(this.opts.emoticons.popup)) {
107
				this.opts.emoticons.more = this.opts.emoticons.popup;
108
				moreButton = $('<div class="sceditor-more" />').text(this._('More')).on('click', function () {
0 ignored issues
show
Bug introduced by
The variable moreButton seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.moreButton.
Loading history...
109
					var popup_box = $('.sceditor-smileyPopup');
110
111
					if (popup_box.length > 0)
112
						popup_box.fadeIn('fast');
113
					else {
114
						var emoticons = $.extend({}, base.opts.emoticons.popup),
115
							titlebar = $('<div class="category_header sceditor-popup-grip"/>');
116
117
						popupContent = $('<div id="sceditor-popup" />');
0 ignored issues
show
Bug introduced by
The variable popupContent seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.popupContent.
Loading history...
118
						line = $('<div id="sceditor-popup-smiley" />');
0 ignored issues
show
Bug introduced by
The variable line seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.line.
Loading history...
119
120
						// create our popup, title bar, smiles, then the close button
121
						popupContent.append(titlebar);
122
123
						// Add in all the smileys / lines
124
						$.each(emoticons, base.appendEmoticon);
125
						if (line.children().length > 0)
126
							popupContent.append(line);
127
128
						closeButton = $('<div id="sceditor-popup-close" />').text('[' + base._('Close') + ']').on('click', function () {
0 ignored issues
show
Bug introduced by
The variable closeButton seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.closeButton.
Loading history...
129
							$(".sceditor-smileyPopup").fadeOut('fast');
130
						});
131
132
						if (typeof closeButton !== 'undefined')
133
							popupContent.append(closeButton);
134
135
						// IE needs unselectable attr to stop it from unselecting the text in the editor.
136
						// The editor can cope if IE does unselect the text it's just not nice.
137
						if (base.ieUnselectable !== false) {
138
							content = $(content);
0 ignored issues
show
Bug introduced by
The variable content seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.content.
Loading history...
139
							content.find(':not(input,textarea)').filter(function () {
140
								return this.nodeType === 1;
141
							}).attr('unselectable', 'on');
142
						}
143
144
						// Show the smiley popup
145
						$dropdown = $('<div class="sceditor-dropdown sceditor-smileyPopup" />')
0 ignored issues
show
Bug introduced by
The variable $dropdown seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.$dropdown.
Loading history...
146
							.append(popupContent)
147
							.appendTo($('body'))
148
							.css({
149
								"top": $(window).height() * 0.2,
150
								"left": $(window).width() * 0.5 - (popupContent.find('#sceditor-popup-smiley').width() / 2)
151
							});
152
						dropdownIgnoreLastClick = true;
0 ignored issues
show
Bug introduced by
The variable dropdownIgnoreLastClick seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.dropdownIgnoreLastClick.
Loading history...
153
154
						// Allow the smiley window to be moved about
155
						$('.sceditor-smileyPopup').draggable({handle: '.sceditor-popup-grip'});
156
157
						// stop clicks within the dropdown from being handled
158
						$dropdown.on('click', function (e) {
159
							e.stopPropagation();
160
						});
161
					}
162
				});
163
			}
164
165
			// show the standard placement icons
166
			$.each(emoticons, base.appendEmoticon);
167
168
			if (line.children().length > 0)
169
				content.append(line);
170
171
			$(".sceditor-toolbar").append(content);
172
173
			// Show the more button on the editor if we have more
174
			if (typeof moreButton !== 'undefined')
175
				content.append(moreButton);
176
		}
177
	};
178
179
	$.extend(true, $['sceditor'].prototype, extensionMethods);
0 ignored issues
show
Coding Style introduced by
['sceditor'] could be written in dot notation.

You can rewrite this statement in dot notation:

var obj = { };
obj['foo'] = 'bar'; // Bad
obj.foo = 'bar'; // Good
Loading history...
180
})(jQuery);
181
182
/**
183
 * ElkArte unique commands to add to the toolbar, when a button
184
 * with the same name is selected, it will trigger these definitions
185
 *
186
 * tooltip - the hover text, this is the name in the editors.(language).php file
187
 * txtExec - this is the text to insert before and after the cursor or selected text
188
 *           when in the plain text part of the editor
189
 * exec - this is called when in the wizzy part of the editor to insert text or html tags
190
 * state - this is used to determine if a button should be shown as active or not
191
 *
192
 * Adds Tt, Pre, Spoiler, Footnote commands
193
 */
194
$.sceditor.command
195
	.set('space', {})
196
	.set('spoiler', {
197
		state: function () {
198
			var currentNode = this.currentNode(),
199
				currentRange = this.getRangeHelper();
200
201
			// We don't have a node since we don't render the tag in the wizzy editor
202
			// however we can spot check to see if the cursor is inside the tags.
203
			if (currentRange.selectedRange()) {
204
				var end = currentRange.selectedRange().startOffset,
205
					text = $(currentNode).text();
206
207
				// Left and right text from the cursor position and tag positions
208
				var left = text.substr(0, end),
209
					right = text.substr(end),
210
					l1 = left.lastIndexOf("[spoiler]"),
211
					l2 = left.lastIndexOf("[/spoiler]"),
212
					r1 = right.indexOf("[spoiler]"),
213
					r2 = right.indexOf("[/spoiler]");
214
215
				// Inside spoiler tags
216
				if ((l1 > -1 && l1 > l2) || (r2 > -1 && (r1 === -1 || (r1 > r2))))
217
					return 1;
218
			}
219
220
			return 0;
221
		},
222
		exec: function () {
223
			this.insert('[spoiler]', '[/spoiler]');
224
		},
225
		txtExec: ['[spoiler]', '[/spoiler]'],
226
		tooltip: 'Insert Spoiler'
227
	})
228
	.set('footnote', {
229
		state: function () {
230
			var currentNode = this.currentNode(),
231
				currentRange = this.getRangeHelper();
232
233
			// We don't have an html node since we don't render the tag in the editor
234
			// but we can do a spot check to see if the cursor is placed between plain tags.  This
235
			// will miss with nested tags but its nicer than nothing.
236
			if (currentRange.selectedRange()) {
237
				var end = currentRange.selectedRange().startOffset,
238
					text = $(currentNode).text();
239
240
				// Left and right text from the cursor position and tag positions
241
				var left = text.substr(0, end),
242
					right = text.substr(end),
243
					l1 = left.lastIndexOf("[footnote]"),
244
					l2 = left.lastIndexOf("[/footnote]"),
245
					r1 = right.indexOf("[footnote]"),
246
					r2 = right.indexOf("[/footnote]");
247
248
				// Inside footnote tags
249
				if ((l1 > -1 && l1 > l2) || (r2 > -1 && (r1 === -1 || (r1 > r2))))
250
					return 1;
251
			}
252
253
			return 0;
254
		},
255
		exec: function () {
256
			this.insert('[footnote] ', '[/footnote]');
257
		},
258
		txtExec: ['[footnote]', '[/footnote]'],
259
		tooltip: 'Insert Footnote'
260
	})
261
	.set('tt', {
262
		state: function () {
263
			var currentNode = this.currentNode();
264
265
			return $(currentNode).is('span.tt') || $(currentNode).parents('span.tt').length > 0 ? 1 : 0;
266
		},
267
		exec: function () {
268
			var editor = this,
269
				currentNode = this.currentNode();
270
271
			// Add a TT span if not in one
272
			if (!$(currentNode).is('span.tt') && $(currentNode).parents('span.tt').length === 0)
273
				editor.insert('<span class="tt">', '</span>', false);
274
			// Remove a TT span if in one and its empty
275
			else if ($(currentNode).is('span.tt') && $(currentNode).text().length === 1) {
276
				$(currentNode).replaceWith('');
277
				editor.insert('<span> ', '</span>', false);
278
			}
279
			// Escape from this one then
280
			else if (!$(currentNode).is('span.tt') && $(currentNode).parents('span.tt').length > 0)
281
				editor.insert('<span> ', '</span>', false);
282
		},
283
		txtExec: ['[tt]', '[/tt]'],
284
		tooltip: 'Teletype'
285
	})
286
	.set('pre', {
287
		state: function () {
288
			var currentNode = this.currentNode();
289
290
			return $(currentNode).is('pre') || $(currentNode).parents('pre').length > 0 ? 1 : 0;
291
		},
292
		exec: function () {
293
			var editor = this,
294
				currentNode = this.currentNode();
295
296
			if (!$(currentNode).is('pre') && $(currentNode).parents('pre').length === 0)
297
				editor.insert('<pre>', '</pre>', false);
298
			// In a pre node and selected pre again, lets try to end it and escape
299
			else if (!$(currentNode).is('pre') && $(currentNode).parents('pre').length > 0) {
300
				var rangerhelper = this.getRangeHelper(),
301
					firstblock = rangerhelper.getFirstBlockParent(),
302
					sceditor = $("#" + post_box_name).sceditor("instance"),
0 ignored issues
show
Bug introduced by
The variable post_box_name seems to be never declared. If this is a global, consider adding a /** global: post_box_name */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
303
					newnode;
304
305
				editor.insert('<p id="blank"> ', '</p>', false);
306
				rangerhelper.saveRange();
307
				newnode = sceditor.getBody().find('#blank').get(0);
308
				firstblock.parentNode.insertBefore(newnode, firstblock.nextSibling);
309
				rangerhelper.restoreRange();
310
				editor.focus();
311
			}
312
		},
313
		txtExec: ['[pre]', '[/pre]'],
314
		tooltip: 'Preformatted Text'
315
	})
316
	/*
317
	 * ElkArte modifications to existing commands so they display as we like
318
	 *
319
	 * Makes changes to the text inserted for Bulletlist, OrderedList and Table
320
	 */
321
	.set('bulletlist', {
322
		txtExec: ['[list]\n[li]', '[/li]\n[li][/li]\n[/list]']
323
	})
324
	.set('orderedlist', {
325
		txtExec: ['[list type=decimal]\n[li]', '[/li]\n[li][/li]\n[/list]']
326
	})
327
	.set('table', {
328
		txtExec: ['[table]\n[tr]\n[td]', '[/td]\n[/tr]\n[/table]']
329
	});
330
331
/**
332
 * ElkArte custom bbc tags added to provide for the existing user experience
333
 *
334
 * These command define what happens to tags as to toggle from and to wizzy mode
335
 * It converts html back to bbc or bbc back to html.  Read the sceditor docs for more
336
 *
337
 * Adds / modifies BBC codes List, Tt, Pre, quote, footnote, code, img
338
 */
339
$.sceditor.plugins.bbcode.bbcode
340
	.set('tt', {
341
		tags: {
342
			tt: null,
343
			span: {'class': ['tt']}
344
		},
345
		format: '[tt]{0}[/tt]',
346
		html: '<span class="tt">{0}</span>'
347
	})
348
	.set('pre', {
349
		tags: {
350
			pre: null
351
		},
352
		isInline: false,
353
		format: '[pre]{0}[/pre]',
354
		html: '<pre>{0}</pre>'
355
	})
356
	.set('member', {
357
		isInline: true,
358
		format: function (element, content) {
359
			return '[member=' + element.attr('data-mention') + ']' + content.replace('@', '') + '[/member]';
360
		},
361
		html: function (token, attrs, content) {
362
			if (typeof attrs.defaultattr === 'undefined' || attrs.defaultattr.length === 0)
363
				attrs.defaultattr = content;
364
365
			return '<a href="' + elk_scripturl + '?action=profile;u=' + attrs.defaultattr + '" class="mention" data-mention="' + attrs.defaultattr + '">@' + content.replace('@', '') + '</a>';
366
		}
367
	})
368
	.set('me', {
369
		tags: {
370
			me: {
371
				'data-me' : null
372
			}
373
		},
374
		isInline: true,
375
		quoteType: $.sceditor.BBCodeParser.QuoteType.always,
376
		format: function (element, content) {
377
			return '[me=' + element.attr('data-me') + ']' + content.replace(element.attr('data-me') + ' ', '') + '[/me]';
378
		},
379
		html: function (token, attrs, content) {
380
			if (typeof attrs.defaultattr === 'undefined' || attrs.defaultattr.length === 0)
381
				attrs.defaultattr = '';
382
383
			return '<me data-me="' + attrs.defaultattr + '">' + attrs.defaultattr + ' ' + content + '</me>';
384
		}
385
	})
386
	.set('attachurl', {
387
		allowsEmpty: false,
388
		quoteType: $.sceditor.BBCodeParser.QuoteType.never,
389
		format: function (element, content) {
390
			return '[attachurl]' + content + '[/attachurl]';
391
		},
392
		html: function (token, attrs, content) {
393
			// @todo new action to return real filename?
394
			return '<a href="' + elk_scripturl + '?action=dlattach;attach=' + content + ';' + elk_session_var + '=' + elk_session_id + '" data-ila="' + content + '">(<i class="icon i-paperclip"></i>&nbsp;' + ila_filename + ')</a>';
395
		}
396
	})
397
	.set('attach', {
398
		allowsEmpty: false,
399
		quoteType: $.sceditor.BBCodeParser.QuoteType.never,
400
		format: function (element, content) {
401
			/**
402
			 * This function is not used because no specific html tag is associated,
403
			 * instead the 'img'.format takes care of finding the ILA images and process
404
			 * them accordingly to return the [attach] tag.
405
			 */
406
			var	attribs = '',
407
				params = function(names) {
408
					names.forEach(function(name) {
409
						if (element.attr(name))
410
							attribs += ' ' + name + '=' + element.attr(name);
411
						else if (element.style[name])
412
							attribs += ' ' + name + '=' + element.style[name];
413
					});
414
				};
415
416
			params(['width', 'height', 'align', 'type']);
417
418
			return '[attach' + attribs + ']' + content + '[/attach]';
419
		},
420
		html: function (token, attrs, content) {
421
			var attribs = ''
0 ignored issues
show
Coding Style introduced by
There should be a semicolon.

Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers.

Further Readings:

Loading history...
422
				align = '',
0 ignored issues
show
Comprehensibility introduced by
Usage of the sequence operator is discouraged, since it may lead to obfuscated code.

The sequence or comma operator allows the inclusion of multiple expressions where only is permitted. The result of the sequence is the value of the last expression.

This operator is most often used in for statements.

Used in another places it can make code hard to read, especially when people do not realize it even exists as a seperate operator.

This check looks for usage of the sequence operator in locations where it is not necessary and could be replaced by a series of expressions or statements.

var a,b,c;

a = 1, b = 1,  c= 3;

could just as well be written as:

var a,b,c;

a = 1;
b = 1;
c = 3;

To learn more about the sequence operator, please refer to the MDN.

Loading history...
Bug introduced by
The variable align seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.align.
Loading history...
423
				thumb = '',
0 ignored issues
show
Bug introduced by
The variable thumb seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.thumb.
Loading history...
424
				params = function(names) {
0 ignored issues
show
Bug introduced by
The variable params seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.params.
Loading history...
425
					names.forEach(function(name) {
426
						if (typeof attrs[name] !== 'undefined') {
427
							attribs += ' ' + name + '=' + attrs[name];
428
						}
429
					});
430
				};
0 ignored issues
show
Bug introduced by
Did you forget to assign or call a function?

This error message can for example pop up if you forget to assign the result of a function call to a variable or pass it to another function:

function someFunction(x) {
    (x > 0) ? callFoo() : callBar();
}

// JSHint expects you to assign the result to a variable:
function someFunction(x) {
    var rs = (x > 0) ? callFoo() : callBar();
}

// If you do not use the result, you could also use if statements in the
// case above.
function someFunction(x) {
    if (x > 0) {
        callFoo();
    } else {
        callBar();
    }
}
Loading history...
431
432
			params(['width', 'height', 'align', 'type']);
433
			a_attribs = attribs;
0 ignored issues
show
Bug introduced by
The variable a_attribs seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.a_attribs.
Loading history...
434
			if (typeof attrs.align !== 'undefined')
435
			{
436
				align = ' class="img_bbc float' + attrs.align + '"';
0 ignored issues
show
Bug introduced by
The variable align seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.align.
Loading history...
437
			}
438
			if (typeof attrs.type !== 'undefined')
439
			{
440
				thumb = ';' + attrs.type;
0 ignored issues
show
Bug introduced by
The variable thumb seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.thumb.
Loading history...
441
			}
442
443
			return '<img' + attribs + align + ' src="' + elk_scripturl + '?action=dlattach;attach=' + content + thumb + ';' + elk_session_var + '=' + elk_session_id + '" data-ila="' + content + '" />';
444
		}
445
	})
446
	.set('center', {
447
		tags: {
448
			center: null
449
		},
450
		styles: {
451
			'text-align': ['center', '-webkit-center', '-moz-center', '-khtml-center']
452
		},
453
		isInline: true,
454
		format: '[center]{0}[/center]',
455
		html: '<span style="display:block;text-align:center">{0}</span>'
456
	})
457
	/*
458
	 * ElkArte modified tags, modified so they support the existing paradigm
459
	 *
460
	 * Changes the way existing editor tags work
461
	 * Modifies code, quote, list, ul, ol, li
462
	 */
463
	.set('code', {
464
		tags: {
465
			code: null
466
		},
467
		isInline: false,
468
		allowedChildren: ['#', '#newline'],
469
		format: function (element, content) {
470
			var from = '';
471
472
			if (element.children("cite:first").length === 1) {
473
				from = element.children("cite:first").text().trim();
474
				element.attr({'from': from.php_htmlspecialchars()});
475
				from = '=' + from;
476
				element.children("cite:first").remove();
477
				content = this.elementToBbcode(element);
478
			}
479
			else if (typeof element.attr('from') !== 'undefined') {
480
				from = '=' + element.attr('from').php_unhtmlspecialchars();
481
			}
482
483
			return '[code' + from + ']' + content.replace('&#91;', '[') + '[/code]';
484
		},
485
		quoteType: function (element) {
486
			return element;
487
		},
488
		html: function (element, attrs, content) {
489
			var from = '';
490
491
			if (typeof attrs.defaultattr !== 'undefined')
492
				from = '<cite>' + attrs.defaultattr + '</cite>';
493
494
			return '<code>' + from + content.replace('[', '&#91;') + '</code>';
495
		}
496
	})
497
	.set('quote', {
498
		tags: {
499
			blockquote: null,
500
			cite: null
501
		},
502
		isInline: false,
503
		format: function (element, content) {
504
			var author = '',
505
				date = '',
506
				link = '';
507
508
			if (element[0].tagName.toLowerCase() === 'cite')
509
				return '';
510
			if (element.attr('author'))
511
				author = ' author=' + element.attr('author').php_unhtmlspecialchars();
512
			if (element.attr('date'))
513
				date = ' date=' + element.attr('date');
514
			if (element.attr('link'))
515
				link = ' link=' + element.attr('link');
516
			if (author === '' && date === '' && link !== '')
517
				link = '=' + element.attr('link');
518
519
			return '[quote' + author + date + link + ']' + content + '[/quote]';
520
		},
521
		html: function (element, attrs, content) {
522
			var attr_author = '',
523
				sAuthor = '',
524
				attr_date = '',
525
				sDate = '',
526
				attr_link = '',
527
				sLink = '';
528
529
			// Author tag in the quote ?
530
			if (typeof attrs.author !== 'undefined') {
531
				attr_author = attrs.author;
532
				sAuthor = bbc_quote_from + ': ' + attr_author;
0 ignored issues
show
Bug introduced by
The variable bbc_quote_from seems to be never declared. If this is a global, consider adding a /** global: bbc_quote_from */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
533
			}
534
			// Done as [quote=someone]
535
			else if (typeof attrs.defaultattr !== 'undefined') {
536
				// Convert it to an author tag
537
				attr_link = attrs.defaultattr;
538
				sLink = attr_link.substr(0, 7) === 'http://' ? attr_link : elk_scripturl + '?' + attr_link;
539
				sAuthor = '<a href="' + sLink + '">' + bbc_quote_from + ': ' + sLink + '</a>';
540
			}
541
542
			// Links could be in the form: link=topic=71.msg201#msg201 that would fool javascript, so we need a workaround
543
			for (var key in attrs) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
544
				if (key.substr(0, 4) === 'link' && attrs.hasOwnProperty(key)) {
545
					attr_link = key.length > 4 ? key.substr(5) + '=' + attrs[key] : attrs[key];
546
547
					sLink = attr_link.substr(0, 7) === 'http://' ? attr_link : elk_scripturl + '?' + attr_link;
548
					sAuthor = sAuthor === '' ? '<a href="' + sLink + '">' + bbc_quote_from + ': ' + sLink + '</a>' : '<a href="' + sLink + '">' + sAuthor + '</a>';
549
				}
550
			}
551
552
			// A date perhaps
553
			if (typeof attrs.date !== 'undefined') {
554
				attr_date = attrs.date;
555
				sDate = '<date timestamp="' + attr_date + '">' + new Date(attrs.date * 1000) + '</date>';
556
			}
557
558
			// Build the blockquote up with the data
559
			if (sAuthor === '' && sDate === '')
560
				sAuthor = bbc_quote;
0 ignored issues
show
Bug introduced by
The variable bbc_quote seems to be never declared. If this is a global, consider adding a /** global: bbc_quote */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
561
			else
562
				sAuthor += sDate !== '' ? ' ' + bbc_search_on : '';
0 ignored issues
show
Bug introduced by
The variable bbc_search_on seems to be never declared. If this is a global, consider adding a /** global: bbc_search_on */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
563
564
			content = '<blockquote author="' + attr_author + '" link="' + attr_link + '" date="' + attr_date + '"><cite>' + sAuthor + ' ' + sDate + '</cite>' + content + '</blockquote>';
565
566
			return content;
567
		}
568
	})
569
	.set('img', {
570
		tags: {
571
			img: {
572
				src: null
573
			}
574
		},
575
		allowsEmpty: true,
576
		quoteType: $.sceditor.BBCodeParser.QuoteType.never,
577
		format: function (element, content) {
578
			var attribs = '',
579
				params = function (names) {
580
					names.forEach(function (name) {
581
						if (element.attr(name))
582
							attribs += ' ' + name + '=' + element.attr(name);
583
						else if (element[0].style[name])
584
							attribs += ' ' + name + '=' + element[0].style[name];
585
					});
586
				};
587
588
			// check if this is an emoticon image
589
			if (typeof element.attr('data-sceditor-emoticon') !== 'undefined')
590
				return content;
591
592
			// check if this is an ILA ?
593
			if (element.attr('data-ila'))
594
			{
595
				params(['width', 'height', 'align', 'type']);
596
				return '[attach' + attribs + ']' + element.attr('data-ila') + '[/attach]';
597
			}
598
599
			// normal image then
600
			params(['width', 'height', 'title', 'alt']);
601
			return '[img' + attribs + ']' + element.attr('src') + '[/img]';
602
		},
603
604
		html: function (token, attrs, content) {
605
			var attribs = '',
606
				params = function (names) {
607
					names.forEach(function (name) {
608
						if (typeof attrs[name] !== 'undefined')
609
							attribs += ' ' + name + '="' + attrs[name] + '"';
610
					});
611
				};
612
613
			// handle [img alt=alt title=title width=123 height=123]url[/img]
614
			params(['width', 'height', 'alt', 'title']);
615
			return '<img' + attribs + ' src="' + content + '" />';
616
		}
617
	})
618
	.set('list', {
619
		breakStart: true,
620
		isInline: false,
621
		skipLastLineBreak: true,
622
		allowedChildren: ['#', '*', 'li'],
623
		html: function (element, attrs, content) {
624
			var style = '',
625
				code = 'ul';
626
627
			if (attrs.type)
628
				style = 'style="list-style-type: ' + attrs.type + '"';
629
			return '<' + code + ' ' + style + '>' + content.replace(/<\/li><br \/>/g, '</li>') + '</' + code + '>';
630
		}
631
	})
632
	.set('li', {
633
		breakAfter: false
634
	})
635
	.set('ul', {
636
		tags: {
637
			ul: null
638
		},
639
		breakStart: true,
640
		format: function (element, content) {
641
			var type = $(element[0]).prop('style')['list-style-type'];
642
643
			if (type === 'disc' || type === '')
644
				return '[list]' + content + '[/list]';
645
			else
646
				return '[list type=' + type + ']' + content + '[/list]';
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
647
		},
648
		isInline: false,
649
		skipLastLineBreak: true,
650
		html: '<ul>{0}</ul>'
651
	})
652
	.set('ol', {
653
		tags: {
654
			ol: null
655
		},
656
		breakStart: true,
657
		isInline: false,
658
		skipLastLineBreak: true,
659
		format: '[list type=decimal]{0}[/list]',
660
		html: '<ol>{0}</ol>'
661
	})
662
	.set('url', {
663
		allowsEmpty: true,
664
		tags: {
665
			a: {
666
				href: null
667
			}
668
		},
669
		quoteType: $.sceditor.BBCodeParser.QuoteType.never,
670
		format: function (element, content) {
671
			var url = element.attr('href');
672
673
			// return the type of link we are currently dealing with
674
			if (url.substr(0, 7) === 'mailto:')
675
				return '[email="' + url.substr(7) + '"]' + content + '[/email]';
676
			if (typeof element.attr('data-mention') !== 'undefined')
677
				return '[member=' + element.attr('data-mention') + ']' + content.replace('@', '') + '[/member]';
678
			if (typeof element.attr('data-ila') !== 'undefined')
679
				return '[attachurl]' + element.attr('data-ila') + '[/attachurl]';
680
681
			return '[url=' + url + ']' + content + '[/url]';
682
		},
683
		html: function (token, attrs, content) {
684
			attrs.defaultattr = $.sceditor.escapeEntities(attrs.defaultattr, true) || content;
685
686
			return '<a href="' + $.sceditor.escapeUriScheme(attrs.defaultattr) + '" class="mention">' + content + '</a>';
687
		}
688
	});
689