PageSourceSearch

https://avtoservice-profit.ru/nassets/7aad1ce7/jquery.emojiarea.js?v=1765633899

js avtoservice-profit.ru collected 2026-09-26 11:03:21 UTC 14,291 bytes, 524 lines download raw bytes

1/** 
2 * emojiarea - A rich textarea control that supports emojis, WYSIWYG-style.
3 * Copyright (c) 2012 DIY Co
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this 
6 * file except in compliance with the License. You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under 
10 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 
11 * ANY KIND, either express or implied. See the License for the specific language 
12 * governing permissions and limitations under the License.
13 *
14 * @author Brian Reavis <[email protected]>
15 */
16
17(function($, window, document) {
18
19	var ELEMENT_NODE = 1;
20	var TEXT_NODE = 3;
21	var TAGS_BLOCK = ['p', 'div', 'pre', 'form'];
22	var KEY_ESC = 27;
23	var KEY_TAB = 9;
24
25	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
26
27	$.emojiarea = {
28		path: '',
29		icons: {},
30		defaults: {
31			button: null,
32			buttonLabel: 'Emojis',
33			buttonPosition: 'after',
34            contentEditable: 'always' // always - contentEditable always creates, empty - check if textarea is empty, any other - no contentEditable
35		}
36	};
37
38	$.fn.emojiarea = function(options) {
39		options = $.extend({}, $.emojiarea.defaults, options);
40		return this.each(function() {
41			var $textarea = $(this);
42
43            var wysiwyg = false;
44            if (options.contentEditable == 'always' || (options.contentEditable == 'empty' && $textarea.val().length)) {
45                wysiwyg = true;
46            }
47
48			if ('contentEditable' in document.body && options.wysiwyg !== false && wysiwyg) {
49				new EmojiArea_WYSIWYG($textarea, options);
50			} else {
51				new EmojiArea_Plain($textarea, options);
52			}
53		});
54	};
55
56	$.fn.emoji = function() {
57        this.each(function () {
58            var html = $(this).html();
59            var emojis = $.emojiarea.icons;
60			//console.log(html);
61			//debugger;
62            for (var key in emojis) {
63                if (emojis.hasOwnProperty(key)) {
64                    html = html.replace(new RegExp(util.escapeRegex(key), 'g'), EmojiArea.createIcon(key));
65                }
66            }
67
68            $(this).html(html);
69        });
70	};
71
72    $.emoji = function(html) {
73        if (html) {
74            var emojis = $.emojiarea.icons;
75
76            for (var key in emojis) {
77                if (emojis.hasOwnProperty(key)) {
78                    html = html.replace(new RegExp(util.escapeRegex(key), 'g'), EmojiArea.createIcon(key));
79                }
80            }
81
82            return html;
83        } else {
84            return html;
85        }
86    };
87
88    $.fn.emojiButton = function() {
89        this.each(function () {
90            $(this).after('<div class="emoji-button"><span class="fa fa-smile-o fa-lg"></span></div>');
91            $(this).next('.emoji-button').andSelf().wrapAll('<div class="emoji-container" />');
92        });
93    };
94
95	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
96
97	var util = {};
98
99	util.restoreSelection = (function() {
100		if (window.getSelection) {
101			return function(savedSelection) {
102				var sel = window.getSelection();
103				sel.removeAllRanges();
104				for (var i = 0, len = savedSelection.length; i < len; ++i) {
105					sel.addRange(savedSelection[i]);
106				}
107			};
108		} else if (document.selection && document.selection.createRange) {
109			return function(savedSelection) {
110				if (savedSelection) {
111					savedSelection.select();
112				}
113			};
114		}
115	})();
116
117	util.saveSelection = (function() {
118		if (window.getSelection) {
119			return function() {
120				var sel = window.getSelection(), ranges = [];
121				if (sel.rangeCount) {
122					for (var i = 0, len = sel.rangeCount; i < len; ++i) {
123						ranges.push(sel.getRangeAt(i));
124					}
125				}
126				return ranges;
127			};
128		} else if (document.selection && document.selection.createRange) {
129			return function() {
130				var sel = document.selection;
131				return (sel.type.toLowerCase() !== 'none') ? sel.createRange() : null;
132			};
133		}
134	})();
135
136	util.replaceSelection = (function() {
137		if (window.getSelection) {
138			return function(content) {
139				var range, sel = window.getSelection();
140				var node = typeof content === 'string' ? document.createTextNode(content) : content;
141				if (sel.getRangeAt && sel.rangeCount) {
142					range = sel.getRangeAt(0);
143					range.deleteContents();
144					range.insertNode(document.createTextNode(' '));
145					range.insertNode(node);
146					range.setStart(node, 0);
147					
148					window.setTimeout(function() {
149						range = document.createRange();
150						range.setStartAfter(node);
151						range.collapse(false);
152						sel.removeAllRanges();
153						sel.addRange(range);
154					}, 0);
155				}
156			}
157		} else if (document.selection && document.selection.createRange) {
158			return function(content) {
159				var range = document.selection.createRange();
160				if (typeof content === 'string') {
161					range.text = content;
162				} else {
163					range.pasteHTML(content.outerHTML);
164				}
165			}
166		}
167	})();
168
169	util.insertAtCursor = function(text, el) {
170		text = ' ' + text;
171		var val = el.value, endIndex, startIndex, range;
172		if (typeof el.selectionStart != 'undefined' && typeof el.selectionEnd != 'undefined') {
173			startIndex = el.selectionStart;
174			endIndex = el.selectionEnd;
175			el.value = val.substring(0, startIndex) + text + val.substring(el.selectionEnd);
176			el.selectionStart = el.selectionEnd = startIndex + text.length;
177		} else if (typeof document.selection != 'undefined' && typeof document.selection.createRange != 'undefined') {
178			el.focus();
179			range = document.selection.createRange();
180			range.text = text;
181			range.select();
182		}
183	};
184
185	util.extend = function(a, b) {
186		if (typeof a === 'undefined' || !a) { a = {}; }
187		if (typeof b === 'object') {
188			for (var key in b) {
189				if (b.hasOwnProperty(key)) {
190					a[key] = b[key];
191				}
192			}
193		}
194		return a;
195	};
196
197	util.escapeRegex = function(str) {
198		return (str + '').replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1');
199	};
200
201	util.htmlEntities = function(str) {
202		return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
203	};
204
205	util.nl2br = function(str) {
206        return str.replace(/(\r\n|\n\r|\r|\n)/g, "<br>");
207	};
208
209    util.removeBr = function(str) {
210        return str.replace(/<br>/g, "\r");
211    };
212
213	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
214
215	var EmojiArea = function() {};
216
217	EmojiArea.prototype.setup = function() {
218		var self = this;
219		
220		this.$editor.on('focus', function() { self.hasFocus = true; });
221		this.$editor.on('blur', function() { self.hasFocus = false; });
222		
223		this.setupButton();
224	};
225
226	EmojiArea.prototype.setupButton = function() {
227		var self = this;
228		var $button;
229
230		if (this.options.button) {
231			$button = this.$textarea.siblings(this.options.button);
232		} else if (this.options.button !== false) {
233			$button = $('<a href="javascript:void(0)">');
234			$button.html(this.options.buttonLabel);
235			$button.addClass('emoji-button');
236			$button.attr({title: this.options.buttonLabel});
237			this.$editor[this.options.buttonPosition]($button);
238		} else {
239			$button = $('');
240		}
241
242		$button.on('click', function(e) {
243			EmojiMenu.show(self);
244			e.stopPropagation();
245		});
246
247		this.$button = $button;
248	};
249
250	EmojiArea.createIcon = function(emoji) {
251		return '<span class="smile-box">'+ $.emojiarea.entities[emoji] +'</span>';
252	};
253
254	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
255
256	/**
257	 * Editor (plain-text)
258	 * 
259	 * @constructor
260	 * @param {object} $textarea
261	 * @param {object} options
262	 */
263
264	var EmojiArea_Plain = function($textarea, options) {
265		this.options = options;
266		this.$textarea = $textarea;
267		this.$editor = $textarea;
268		this.setup();
269	};
270
271	EmojiArea_Plain.prototype.insert = function(emoji) {
272		if (!$.emojiarea.icons.hasOwnProperty(emoji)) return;
273		util.insertAtCursor(emoji, this.$textarea[0]);
274		this.$textarea.trigger('change');
275	};
276
277	EmojiArea_Plain.prototype.val = function() {
278		return this.$textarea.val();
279	};
280
281	util.extend(EmojiArea_Plain.prototype, EmojiArea.prototype);
282
283	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
284
285	/**
286	 * Editor (rich)
287	 * 
288	 * @constructor
289	 * @param {object} $textarea
290	 * @param {object} options
291	 */
292
293	var EmojiArea_WYSIWYG = function($textarea, options) {
294		var self = this;
295
296		this.options = options;
297		this.$textarea = $textarea;
298		this.$editor = $('<div>')
299			.addClass('emoji-wysiwyg-editor')
300			.css({
301				minHeight: $textarea.css('height'),
302				maxHeight: $textarea.css('max-height')
303			});
304		this.$editor.html($textarea.val());
305
306		this.$editor.attr({contenteditable: 'true'});
307		this.$editor.on('blur keyup paste', function() { return self.onChange.apply(self, arguments); });
308		this.$editor.on('mousedown focus', function() { document.execCommand('enableObjectResizing', false, false); });
309		this.$editor.on('blur', function() { document.execCommand('enableObjectResizing', true, true); });
310
311		var html = util.nl2br(this.$editor.html());
312
313		var emojis = $.emojiarea.icons;
314		for (var key in emojis) {
315			if (emojis.hasOwnProperty(key)) {
316				html = html.replace(new RegExp(util.escapeRegex(key), 'g'), EmojiArea.createIcon(key));
317			}
318		}
319		this.$editor.html(html);
320
321		$textarea.hide().after(this.$editor);
322
323		this.setup();
324
325		this.$button.on('mousedown', function() {
326			if (self.hasFocus) {
327				self.selection = util.saveSelection();
328			}
329		});
330
331        this.$button.trigger('click');
332
333        this.$editor.height('auto');
334	};
335
336	EmojiArea_WYSIWYG.prototype.onChange = function() {
337		this.$textarea.val(util.removeBr(this.val())).trigger('change');
338	};
339
340	EmojiArea_WYSIWYG.prototype.insert = function(emoji) {
341		var content;
342		var $img = $(EmojiArea.createIcon(emoji));
343		if ($img[0].attachEvent) {
344			$img[0].attachEvent('onresizestart', function(e) { e.returnValue = false; }, false);
345		}
346		
347		this.$editor.trigger('focus');
348		if (this.selection) {
349			util.restoreSelection(this.selection);
350		}
351		try { util.replaceSelection($img[0]); } catch (e) {}
352		this.onChange();
353	};
354
355	EmojiArea_WYSIWYG.prototype.val = function() {
356		var lines = [];
357		var line  = [];
358
359		var flush = function() {
360			lines.push(line.join(''));
361			line = [];
362		};
363
364		var sanitizeNode = function(node) {
365			if (node.nodeType === TEXT_NODE) {
366				line.push(node.nodeValue);
367			} else if (node.nodeType === ELEMENT_NODE) {
368				var tagName = node.tagName.toLowerCase();
369				var isBlock = TAGS_BLOCK.indexOf(tagName) !== -1;
370
371				if (isBlock && line.length) flush();
372
373				if (tagName === 'img') {
374					var alt = node.getAttribute('alt') || '';
375					if (alt) line.push(alt);
376					return;
377				} else if (tagName === 'br') {
378					flush();
379				}
380
381				var children = node.childNodes;
382				for (var i = 0; i < children.length; i++) {
383					sanitizeNode(children[i]);
384				}
385
386				if (isBlock && line.length) flush();
387			}
388		};
389
390		var children = this.$editor[0].childNodes;
391		for (var i = 0; i < children.length; i++) {
392			sanitizeNode(children[i]);
393		}
394
395		if (line.length) flush();
396
397		return lines.join('\n');
398	};
399
400	util.extend(EmojiArea_WYSIWYG.prototype, EmojiArea.prototype);
401
402	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
403
404	/**
405	 * Emoji Dropdown Menu
406	 *
407	 * @constructor
408	 * @param {object} emojiarea
409	 */
410	var EmojiMenu = function() {
411		var self = this;
412		var $body = $(document.body);
413		var $window = $(window);
414
415		this.visible = false;
416		this.emojiarea = null;
417		this.$menu = $('<div>');
418		this.$menu.addClass('emoji-menu');
419		this.$menu.hide();
420		this.$items = $('<div>').appendTo(this.$menu);
421
422		$body.append(this.$menu);
423
424		$body.on('keydown', function(e) {
425			if (e.keyCode === KEY_ESC || e.keyCode === KEY_TAB) {
426				self.hide();
427			}
428		});
429
430		$body.on('mouseup', function() {
431			self.hide();
432		});
433
434		$window.on('resize', function() {
435			if (self.visible) self.reposition();
436		});
437
438		this.$menu.on('mouseup', 'a', function(e) {
439			e.stopPropagation();
440			return false;
441		});
442
443		this.$menu.on('click', 'a', function(e) {
444			var emoji = $('.label', $(this)).text();
445			window.setTimeout(function() {
446				self.onItemSelected.apply(self, [emoji]);
447			}, 0);
448			e.stopPropagation();
449			return false;
450		});
451
452		this.load();
453	};
454
455	EmojiMenu.prototype.onItemSelected = function(emoji) {
456		this.emojiarea.insert(emoji);
457		this.hide();
458	};
459
460	EmojiMenu.prototype.load = function() {
461		var html = [];
462		var options = $.emojiarea.icons;
463		var path = $.emojiarea.path;
464		if (path.length && path.charAt(path.length - 1) !== '/') {
465			path += '/';
466		}
467
468		for (var key in options) {
469			if (options.hasOwnProperty(key)) {
470				var filename = options[key];
471				html.push('<a href="javascript:void(0)" title="' + util.htmlEntities(key) + '">' + EmojiArea.createIcon(key) + '<span class="label">' + util.htmlEntities(key) + '</span></a>');
472			}
473		}
474
475		this.$items.html(html.join(''));
476	};
477
478	EmojiMenu.prototype.reposition = function() {
479		var $button = this.emojiarea.$button;
480		var offset = $button.offset();
481
482		//offset.left += Math.round($button.outerWidth() / 2);
483		var dW = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
484		var dH = Math.max(document.documentElement.clientHeight, window.innerHeight || 0, $(document).height());
485		var mW = this.$menu.outerWidth();
486		var mH = this.$menu.outerHeight();
487
488		this.$menu.css({
489			top: (offset.top + mH) < dH ? offset.top + $button.outerHeight() : (offset.top - mH - Math.round($button.outerHeight()/2.4))
490			,left: (offset.left + $button.outerWidth() + mW) > dW ?
491				(offset.left - Math.round($button.outerWidth()*2) - Math.round(mW/2)) :
492				(offset.left - Math.round($button.outerWidth()*2) + Math.round(mW/2.4))
493		});
494	};
495
496	EmojiMenu.prototype.hide = function(callback) {
497		if (this.emojiarea) {
498			this.emojiarea.menu = null;
499			this.emojiarea.$button.removeClass('on');
500			this.emojiarea = null;
501		}
502		this.visible = false;
503		this.$menu.hide();
504	};
505
506	EmojiMenu.prototype.show = function(emojiarea) {
507		if (this.emojiarea && this.emojiarea === emojiarea) return;
508		this.emojiarea = emojiarea;
509		this.emojiarea.menu = this;
510
511		this.reposition();
512		this.$menu.show();
513		this.visible = true;
514	};
515
516	EmojiMenu.show = (function() {
517		var menu = null;
518		return function(emojiarea) {
519			menu = menu || new EmojiMenu();
520			menu.show(emojiarea);
521		};
522	})();
523
524})(jQuery, window, document);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.