2018-04-20 13:40:09 +00:00
|
|
|
|
/*!
|
|
|
|
|
@package wdt-emoji-bundle - Slack like emoji selector with apple, twitter, google, emojione and custom emoji support.
|
|
|
|
|
@version version: 0.2.1
|
|
|
|
|
@contributors https://github.com/needim/wdt-emoji-bundle/graphs/contributors
|
|
|
|
|
@documentation Examples and Documentation - http://ned.im/wdt-emoji-bundle/
|
|
|
|
|
@license Licensed under the MIT licenses: http://www.opensource.org/licenses/mit-license.php
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
;
|
|
|
|
|
(function (root, factory) {
|
|
|
|
|
if (typeof define === 'function' && define.amd) {
|
|
|
|
|
define(['emoji-js'], factory);
|
|
|
|
|
} else if (typeof exports === 'object') {
|
|
|
|
|
module.exports = factory(require('emoji-js'));
|
|
|
|
|
} else {
|
|
|
|
|
root.wdtEmojiBundle = factory(root.EmojiConvertor);
|
|
|
|
|
}
|
|
|
|
|
})(this, function (EmojiConvertor) {
|
|
|
|
|
var wdtEmojiBundle = {};
|
|
|
|
|
|
|
|
|
|
wdtEmojiBundle.defaults = {
|
|
|
|
|
pickerColors : ['green', 'pink', 'yellow', 'blue', 'gray'],
|
|
|
|
|
textMode : true,
|
|
|
|
|
disabledCategories: ['Skin Tones'],
|
|
|
|
|
sectionOrders: {
|
|
|
|
|
'Recent' : 10,
|
|
|
|
|
'Custom' : 9,
|
|
|
|
|
'People' : 8,
|
|
|
|
|
'Nature' : 7,
|
|
|
|
|
'Foods' : 6,
|
|
|
|
|
'Activity': 5,
|
|
|
|
|
'Places' : 4,
|
|
|
|
|
'Objects' : 3,
|
|
|
|
|
'Symbols' : 2,
|
|
|
|
|
'Flags' : 1
|
|
|
|
|
},
|
|
|
|
|
skinColor : 'skin-1',
|
|
|
|
|
allowNative : false,
|
|
|
|
|
emojiType : 'apple',
|
|
|
|
|
emojiSheets: {
|
|
|
|
|
'apple' : '/sheets/sheet_apple_64_indexed_128.png',
|
|
|
|
|
'google' : '/sheets/sheet_google_64_indexed_128.png',
|
|
|
|
|
'twitter' : '/sheets/sheet_twitter_64_indexed_128.png',
|
|
|
|
|
'emojione' : '/sheets/sheet_emojione_64_indexed_128.png',
|
|
|
|
|
'facebook' : '/sheets/sheet_facebook_64_indexed_128.png',
|
|
|
|
|
'messenger': '/sheets/sheet_messenger_64_indexed_128.png'
|
|
|
|
|
},
|
|
|
|
|
emojiData: {"Symbols":[{"has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_emojione":true,"has_img_facebook":true,"has_img_messenger":true,"name":"HEAVY BLACK HEART","short_name":"heart","short_names":["heart"],"sort_order":1},{"has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_emojione":true,"has_img_facebook":true,"has_img_messenger":true,"name":"YELLOW HEART","short_name":"yellow_heart","short_names":["yellow_heart"],"sort_order":2},{"has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_emojione":true,"has_img_facebook":true,"has_img_messenger":true,"name":"GREEN HEART","short_name":"green_heart","short_names":["green_heart"],"sort_order":3},{"has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_emojione":true,"has_img_facebook":true,"has_img_messenger":true,"name":"BLUE HEART","short_name":"blue_heart","short_names":["blue_heart"],"sort_order":4},{"has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_emojione":true,"has_img_facebook":true,"has_img_messenger":true,"name":"PURPLE HEART","short_name":"purple_heart","short_names":["purple_heart"],"sort_order":5},{"has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_emojione":true,"has_img_facebook":true,"has_img_messenger":true,"name":"BROKEN HEART","short_name":"broken_heart","short_names":["broken_heart"],"sort_order":6},{"has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_emojione":true,"has_img_facebook":true,"has_img_messenger":false,"name":"HEAVY HEART EXCLAMATION MARK ORNAMENT","short_name":"heavy_heart_exclamation_mark_ornament","short_names":["heavy_heart_exclamation_mark_ornament"],"sort_order":7},{"has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_emojione":true,"has_img_facebook":true,"has_img_messenger":true,"name":"TWO HEARTS","short_name":"two_hearts","short_names":["two_hearts"],"sort_order":8},{"has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_emojione":true,"has_img_facebook":true,"has_img_messenger":true,"name":"REVOLVING HEARTS","short_name":"revolving_hearts","short_names":["revolving_hearts"],"sort_order":9},{"has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_emojione":true,"has_img_facebook":true,"has_img_messenger":true,"name":"BEATING HEART","short_name":"heartbeat","short_names":["heartbeat"],"sort_order":10},{"has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_emojione":true,"has_img_facebook":true,"has_img_messenger":true,"name":"GROWING HEART","short_name":"heartpulse","short_names":["heartpulse"],"sort_order":11},{"has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_emojione":true,"has_img_facebook":true,"has_img_messenger":true,"name":"SPARKLING HEART","short_name":"sparkling_heart","short_names":["sparkling_heart"],"sort_order":12},{"has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_emojione":true,"has_img_facebook":true,"has_img_messenger":true,"name":"HEART WITH ARROW","short_name":"cupid","short_names":["cupid"],"sort_order":13},{"has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_emojione":true,"has_img_facebook":true,"has_img_messenger":true,"name":"HEART WITH RIBBON","short_name":"gift_heart","short_names":["gift_heart"],"sort_order":14},{"has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_emojione":true,"has_img_facebook":true,"has_img_messenger":true,"name":"HEART DECORATION","short_name":"heart_decoration","short_names":["heart_decoration"],"sort_order":15},{"has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_emojione":true,"has_img_facebook":true,"has_img_messenger":false,"name":"PEACE SYMBOL","short_name":"peace_symbol","short_names":["peace_symbol"],"sort_order":16},{"has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_emojione":true,"has_img_facebook":true,"has_img_messenger":false,"name":"LATIN CROSS","short_name":"latin_cross","short_names"
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Init the bundle with selector, YAY!
|
|
|
|
|
*/
|
|
|
|
|
wdtEmojiBundle.init = function (selector) {
|
|
|
|
|
|
|
|
|
|
var self = this;
|
|
|
|
|
|
|
|
|
|
// emoji.js overrides
|
|
|
|
|
|
|
|
|
|
self.emoji = new EmojiConvertor();
|
|
|
|
|
|
|
|
|
|
self.emoji.allow_native = this.defaults.allowNative;
|
|
|
|
|
self.emoji.img_set = this.defaults.emojiType;
|
|
|
|
|
self.emoji.use_sheet = true;
|
|
|
|
|
self.emoji.supports_css = true;
|
|
|
|
|
self.emoji.img_sets['apple']['sheet'] = this.defaults.emojiSheets.apple;
|
|
|
|
|
self.emoji.img_sets['google']['sheet'] = this.defaults.emojiSheets.google;
|
|
|
|
|
self.emoji.img_sets['twitter']['sheet'] = this.defaults.emojiSheets.twitter;
|
|
|
|
|
self.emoji.img_sets['emojione']['sheet'] = this.defaults.emojiSheets.emojione;
|
|
|
|
|
self.emoji.img_sets['facebook']['sheet'] = this.defaults.emojiSheets.facebook;
|
|
|
|
|
self.emoji.img_sets['messenger']['sheet'] = this.defaults.emojiSheets.messenger;
|
|
|
|
|
|
|
|
|
|
self.selector = selector;
|
|
|
|
|
self.elements = document.querySelectorAll(selector);
|
|
|
|
|
|
|
|
|
|
self.popup = document.querySelector('.wdt-emoji-popup');
|
|
|
|
|
self.scroller = self.popup.querySelector('.wdt-emoji-scroll-wrapper');
|
|
|
|
|
self.searchInput = self.popup.querySelector('#wdt-emoji-search');
|
|
|
|
|
self.previewImg = self.popup.querySelector('#wdt-emoji-preview-img');
|
|
|
|
|
self.previewName = self.popup.querySelector('#wdt-emoji-preview-name');
|
|
|
|
|
self.previewAliases = self.popup.querySelector('#wdt-emoji-preview-aliases');
|
|
|
|
|
|
|
|
|
|
document.querySelector('body').dataset.wdtEmojiBundle = wdtEmojiBundle.defaults.emojiType;
|
|
|
|
|
|
|
|
|
|
var recent = self.popup.querySelector('[data-group-name="Recent"]');
|
|
|
|
|
if (recent)
|
|
|
|
|
recent.innerHTML = self.emoji.replace_colons(':clock3:');
|
|
|
|
|
|
|
|
|
|
var people = self.popup.querySelector('[data-group-name="People"]');
|
|
|
|
|
if (people)
|
|
|
|
|
people.innerHTML = self.emoji.replace_colons(':sunglasses:');
|
|
|
|
|
|
|
|
|
|
var nature = self.popup.querySelector('[data-group-name="Nature"]');
|
|
|
|
|
if (nature)
|
|
|
|
|
nature.innerHTML = self.emoji.replace_colons(':shamrock:');
|
|
|
|
|
|
|
|
|
|
var foods = self.popup.querySelector('[data-group-name="Foods"]');
|
|
|
|
|
if (foods)
|
|
|
|
|
foods.innerHTML = self.emoji.replace_colons(':pizza:');
|
|
|
|
|
|
|
|
|
|
var activity = self.popup.querySelector('[data-group-name="Activity"]');
|
|
|
|
|
if (activity)
|
|
|
|
|
activity.innerHTML = self.emoji.replace_colons(':football:');
|
|
|
|
|
|
|
|
|
|
var places = self.popup.querySelector('[data-group-name="Places"]');
|
|
|
|
|
if (places)
|
|
|
|
|
places.innerHTML = self.emoji.replace_colons(':airplane:');
|
|
|
|
|
|
|
|
|
|
var objects = self.popup.querySelector('[data-group-name="Objects"]');
|
|
|
|
|
if (objects)
|
|
|
|
|
objects.innerHTML = self.emoji.replace_colons(':bulb:');
|
|
|
|
|
|
|
|
|
|
var symbols = self.popup.querySelector('[data-group-name="Symbols"]');
|
|
|
|
|
if (symbols)
|
|
|
|
|
symbols.innerHTML = self.emoji.replace_colons(':heart:');
|
|
|
|
|
|
|
|
|
|
var flags = self.popup.querySelector('[data-group-name="Flags"]');
|
|
|
|
|
if (flags)
|
|
|
|
|
flags.innerHTML = self.emoji.replace_colons(':waving_white_flag:');
|
|
|
|
|
|
|
|
|
|
var custom = self.popup.querySelector('[data-group-name="Custom"]');
|
|
|
|
|
if (custom)
|
|
|
|
|
custom.innerHTML = self.emoji.replace_colons(':dark_sunglasses:');
|
|
|
|
|
|
|
|
|
|
// a trick for contenteditable blur range clear
|
|
|
|
|
self.ranges = {};
|
|
|
|
|
|
|
|
|
|
if (this.elements.length) {
|
|
|
|
|
for (var i = 0; i < self.elements.length; i++) {
|
|
|
|
|
|
|
|
|
|
var el = self.elements[i];
|
|
|
|
|
|
|
|
|
|
if (el.getAttribute('contenteditable')) {
|
|
|
|
|
el.dataset.rangeIndex = i;
|
|
|
|
|
wdtEmojiBundle.addRangeStore(el);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
self.addPicker(self.elements[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return self;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param element
|
|
|
|
|
*/
|
|
|
|
|
wdtEmojiBundle.addPicker = function (element) {
|
|
|
|
|
var self = this;
|
|
|
|
|
if (!hasClass(element, 'wdt-emoji-picker-ready')) {
|
|
|
|
|
var p = document.createElement('div');
|
|
|
|
|
addClass(p, 'wdt-emoji-picker');
|
|
|
|
|
|
|
|
|
|
p.innerHTML = self.emoji.replace_colons(':smile:');
|
|
|
|
|
|
|
|
|
|
p.addEventListener('click', wdtEmojiBundle.openPicker);
|
|
|
|
|
|
|
|
|
|
var parent = element.parentNode;
|
|
|
|
|
addClass(parent, 'wdt-emoji-picker-parent');
|
|
|
|
|
parent.appendChild(p);
|
|
|
|
|
if (hasClass(element, 'wdt-emoji-open-on-colon')) {
|
|
|
|
|
parent.addEventListener('keyup', wdtEmojiBundle.onKeyup)
|
|
|
|
|
}
|
|
|
|
|
addClass(element, 'wdt-emoji-picker-ready');
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param ev
|
|
|
|
|
* @returns {void}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
wdtEmojiBundle.onKeyup = function (ev) {
|
|
|
|
|
var element = ev.target,
|
|
|
|
|
parent = findParent(element, 'wdt-emoji-picker-parent'),
|
|
|
|
|
emojiPicker = findChild(parent, 'wdt-emoji-picker'),
|
|
|
|
|
val = element.value,
|
|
|
|
|
selection = getSelection(element),
|
|
|
|
|
textBeforeCursor = val.substring(0, selection.start),
|
|
|
|
|
// `<space>:` OR `^:` followed by text
|
|
|
|
|
// text is captured
|
|
|
|
|
matches = textBeforeCursor.match(/(\s|^):(\S*)$/),
|
|
|
|
|
text = matches && matches[2];
|
|
|
|
|
|
|
|
|
|
wdtEmojiBundle.searchAfterColon(text, emojiPicker);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param text
|
|
|
|
|
* @param emojiPicker
|
|
|
|
|
* @returns {void}
|
|
|
|
|
*/
|
|
|
|
|
wdtEmojiBundle.searchAfterColon = function (text, emojiPicker) {
|
|
|
|
|
// no text or not enough text after colon
|
|
|
|
|
if (!text || text.length < 2) {
|
|
|
|
|
wdtEmojiBundle.close();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// is closed
|
|
|
|
|
if (!hasClass(emojiPicker, 'wdt-emoji-picker-open')) {
|
|
|
|
|
wdtEmojiBundle.openPicker.call(emojiPicker, {target: emojiPicker});
|
|
|
|
|
}
|
|
|
|
|
// execute the search
|
|
|
|
|
wdtEmojiBundle.fillSearch(text);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param ev
|
|
|
|
|
* @returns {boolean}
|
|
|
|
|
*/
|
|
|
|
|
wdtEmojiBundle.openPicker = function (ev) {
|
|
|
|
|
var self = this;
|
|
|
|
|
var parent = findParent(ev.target, 'wdt-emoji-picker-parent');
|
|
|
|
|
|
|
|
|
|
wdtEmojiBundle.input = parent.querySelector(wdtEmojiBundle.selector);
|
|
|
|
|
|
|
|
|
|
// @todo - [needim] - popup must be visible in viewport calculate carefully
|
|
|
|
|
function findBestAvailablePosition(el) {
|
|
|
|
|
|
|
|
|
|
var bodyRect = document.body.getBoundingClientRect();
|
|
|
|
|
var elRect = el.getBoundingClientRect();
|
|
|
|
|
var popupRect = wdtEmojiBundle.popup.getBoundingClientRect();
|
|
|
|
|
|
|
|
|
|
var pos = {
|
|
|
|
|
left: (elRect.left - popupRect.width) + elRect.width,
|
|
|
|
|
top : elRect.top + Math.abs(bodyRect.top) + elRect.height
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
pos.left = pos.left < 0 ? 0 : pos.left;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (bodyRect.width < 415) { // mobile specific @todo - [needim] - better mobile detection needed
|
|
|
|
|
addClass(wdtEmojiBundle.popup, 'wdt-emoji-mobile');
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
left : '0px',
|
|
|
|
|
bottom : '0px',
|
|
|
|
|
top : 'auto',
|
|
|
|
|
width : '100%',
|
|
|
|
|
position: 'fixed'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//COMUNIC EDIT
|
|
|
|
|
|
|
|
|
|
var body = document.body,
|
|
|
|
|
html = document.documentElement;
|
|
|
|
|
|
|
|
|
|
var heigth = Math.max(body.scrollHeight, body.offsetHeight,
|
|
|
|
|
html.clientHeight, html.scrollHeight, html.offsetHeight);
|
|
|
|
|
|
|
|
|
|
if(pos.top + 358 > heigth)
|
|
|
|
|
pos.top = heigth - 358;
|
|
|
|
|
|
|
|
|
|
//END COMUNIC EDIT
|
|
|
|
|
|
|
|
|
|
//COMUNIC MOVE
|
|
|
|
|
pos.left += 'px';
|
|
|
|
|
pos.top += 'px';
|
|
|
|
|
//END COMUNIC MOVE
|
|
|
|
|
|
|
|
|
|
return pos;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
css(wdtEmojiBundle.popup, findBestAvailablePosition(ev.target));
|
|
|
|
|
|
|
|
|
|
// On window resized
|
|
|
|
|
window.addEventListener('resize', function(new_event){
|
|
|
|
|
css(wdtEmojiBundle.popup, findBestAvailablePosition(ev.target));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
addClass(wdtEmojiBundle.popup, 'open');
|
|
|
|
|
|
|
|
|
|
// fill with emoji
|
|
|
|
|
wdtEmojiBundle.fillPickerPopup();
|
|
|
|
|
|
|
|
|
|
if (hasClass(this, 'wdt-emoji-picker-open')) {
|
|
|
|
|
wdtEmojiBundle.closePicker(this);
|
|
|
|
|
removeClass(wdtEmojiBundle.popup, 'open');
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wdtEmojiBundle.closePickers();
|
|
|
|
|
|
|
|
|
|
addClass(this, 'wdt-emoji-picker-open');
|
|
|
|
|
//this.innerHTML = wdtEmojiBundle.emoji.replace_colons(':sunglasses:'); //COMUNIC - EDIT
|
2018-04-20 14:52:17 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//COMUNIC EDIT
|
|
|
|
|
//Make the picker close automatically if the parent element is removed
|
|
|
|
|
var interval = setInterval(function(){
|
|
|
|
|
if(!parent.isConnected){
|
|
|
|
|
wdtEmojiBundle.close();
|
|
|
|
|
clearInterval(interval);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}, 2500);
|
|
|
|
|
//END COMUNIC EDIT
|
|
|
|
|
|
|
|
|
|
|
2018-04-20 13:40:09 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* Main function to fill picker popup with emoji
|
|
|
|
|
*
|
|
|
|
|
* @returns void | boolean | mixed
|
|
|
|
|
*/
|
|
|
|
|
wdtEmojiBundle.fillPickerPopup = function () {
|
|
|
|
|
|
|
|
|
|
var self = this;
|
|
|
|
|
|
|
|
|
|
if (hasClass(this.popup, 'ready'))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
// @todo - [needim] - Support for recent and custom emoji list
|
|
|
|
|
var sectionsContainer = this.popup.querySelector('.wdt-emoji-sections'),
|
|
|
|
|
sections = {'Recent': [], 'Custom': []},
|
|
|
|
|
sortedSections = [];
|
|
|
|
|
|
|
|
|
|
for (var category in wdtEmojiBundle.defaults.emojiData) {
|
|
|
|
|
if (wdtEmojiBundle.defaults.emojiData.hasOwnProperty(category)) {
|
|
|
|
|
|
|
|
|
|
if (inArray(category, wdtEmojiBundle.defaults.disabledCategories))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
emojiList = wdtEmojiBundle.defaults.emojiData[category];
|
|
|
|
|
sections[category] = emojiList;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var sortedSectionsArray = Object.keys(sections).sort(function (a, b) {
|
|
|
|
|
return wdtEmojiBundle.defaults.sectionOrders[a] < wdtEmojiBundle.defaults.sectionOrders[b] ? 1 : -1;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < sortedSectionsArray.length; i++) {
|
|
|
|
|
sortedSections[sortedSectionsArray[i]] = sections[sortedSectionsArray[i]];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (var title in sortedSections) {
|
|
|
|
|
if (sortedSections.hasOwnProperty(title)) {
|
|
|
|
|
var emojiList = sortedSections[title];
|
|
|
|
|
|
|
|
|
|
if (emojiList.length) {
|
|
|
|
|
var emojiSection = document.createElement('div'),
|
|
|
|
|
emojiTitle = document.createElement('h3'),
|
|
|
|
|
emojiListDiv = document.createElement('div');
|
|
|
|
|
|
|
|
|
|
emojiTitle.innerHTML = title;
|
|
|
|
|
emojiTitle.dataset.emojiGroup = title;
|
|
|
|
|
emojiListDiv.dataset.emojiGroup = title;
|
|
|
|
|
|
|
|
|
|
addClass(emojiListDiv, 'wdt-emoji-list');
|
|
|
|
|
addClass(emojiSection, 'wdt-emoji-section');
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < emojiList.length; i++) {
|
|
|
|
|
var em = emojiList[i];
|
|
|
|
|
|
|
|
|
|
if (em.has_img_apple || em.has_img_emojione || em.has_img_google || em.has_img_twitter || em.has_img_facebook || em.has_img_messenger) {
|
|
|
|
|
var emojiLink = document.createElement('a');
|
|
|
|
|
|
|
|
|
|
addClass(emojiLink, 'wdt-emoji');
|
|
|
|
|
addClass(emojiLink, wdtEmojiBundle.getRandomPickerColor());
|
|
|
|
|
|
|
|
|
|
emojiLink.dataset.hasImgApple = em.has_img_apple;
|
|
|
|
|
emojiLink.dataset.hasImgEmojione = em.has_img_emojione;
|
|
|
|
|
emojiLink.dataset.hasImgGoogle = em.has_img_google;
|
|
|
|
|
emojiLink.dataset.hasImgTwitter = em.has_img_twitter;
|
|
|
|
|
emojiLink.dataset.hasImgFacebook = em.has_img_facebook;
|
|
|
|
|
emojiLink.dataset.hasImgMessenger = em.has_img_messenger;
|
|
|
|
|
emojiLink.dataset.wdtEmojiName = em.name;
|
|
|
|
|
emojiLink.dataset.wdtEmojiShortnames = ':' + em.short_names.join(': :') + ':';
|
|
|
|
|
emojiLink.dataset.wdtEmojiShortname = em.short_name;
|
|
|
|
|
emojiLink.dataset.wdtEmojiOrder = em.sort_order;
|
|
|
|
|
|
|
|
|
|
emojiLink.innerHTML = self.emoji.replace_colons(':' + em.short_name + ':');
|
|
|
|
|
|
|
|
|
|
emojiListDiv.appendChild(emojiLink);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
emojiSection.appendChild(emojiTitle);
|
|
|
|
|
emojiSection.appendChild(emojiListDiv);
|
|
|
|
|
sectionsContainer.appendChild(emojiSection);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addClass(this.popup, 'ready');
|
|
|
|
|
|
|
|
|
|
wdtEmojiBundle.bindEvents();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Random css class getter for picker hover colors
|
|
|
|
|
* @returns string
|
|
|
|
|
*/
|
|
|
|
|
wdtEmojiBundle.getRandomPickerColor = function () {
|
|
|
|
|
return wdtEmojiBundle.defaults.pickerColors[Math.floor(Math.random() * wdtEmojiBundle.defaults.pickerColors.length)]
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Close the bundle popup
|
|
|
|
|
*/
|
|
|
|
|
wdtEmojiBundle.close = function () {
|
|
|
|
|
removeClass(wdtEmojiBundle.popup, 'open');
|
|
|
|
|
wdtEmojiBundle.closePickers();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Closes all the pickers
|
|
|
|
|
*/
|
|
|
|
|
wdtEmojiBundle.closePickers = function () {
|
|
|
|
|
var openPickers = document.querySelectorAll('.wdt-emoji-picker-open');
|
|
|
|
|
if (openPickers.length) {
|
|
|
|
|
for (var i = 0; i < openPickers.length; i++) {
|
|
|
|
|
wdtEmojiBundle.closePicker(openPickers[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param element
|
|
|
|
|
*/
|
|
|
|
|
wdtEmojiBundle.closePicker = function (element) {
|
|
|
|
|
removeClass(element, 'wdt-emoji-picker-open');
|
|
|
|
|
//element.innerHTML = this.emoji.replace_colons(':smile:'); //COMUNIC - EDIT
|
|
|
|
|
var parent = findParent(element, 'wdt-emoji-picker-parent');
|
|
|
|
|
if (wdtEmojiBundle.searchInput) {
|
|
|
|
|
wdtEmojiBundle.searchInput.value = "";
|
|
|
|
|
wdtEmojiBundle.search("");
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* void function binds some events for the bundle
|
|
|
|
|
*/
|
|
|
|
|
wdtEmojiBundle.bindEvents = function () {
|
|
|
|
|
var self = this;
|
|
|
|
|
var stickers = document.querySelectorAll('.wdt-emoji-section h3');
|
|
|
|
|
if (stickers.length) {
|
|
|
|
|
for (var i = 0; i < stickers.length; i++) {
|
|
|
|
|
sticky(stickers[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
live('click', '.wdt-emoji-list a.wdt-emoji', function (event) {
|
|
|
|
|
var selection = getSelection(wdtEmojiBundle.input);
|
|
|
|
|
|
|
|
|
|
replaceText(wdtEmojiBundle.input, selection, ':' + this.dataset.wdtEmojiShortname + ':');
|
|
|
|
|
fire('select', {el: wdtEmojiBundle.input, event: event, emoji: ':' + this.dataset.wdtEmojiShortname + ':'});
|
|
|
|
|
|
|
|
|
|
var ce = document.createEvent('Event');
|
|
|
|
|
ce.initEvent('input', true, true);
|
|
|
|
|
wdtEmojiBundle.input.dispatchEvent(ce);
|
|
|
|
|
wdtEmojiBundle.close();
|
|
|
|
|
fire('afterSelect', {el: wdtEmojiBundle.input, event: event, emoji: ':' + this.dataset.wdtEmojiShortname + ':'});
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
live('click', '.wdt-emoji-popup-mobile-closer', function (event) {
|
|
|
|
|
wdtEmojiBundle.close();
|
|
|
|
|
return false;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
live('mouseover', '.wdt-emoji-list a.wdt-emoji', function (event) {
|
|
|
|
|
|
|
|
|
|
if (wdtEmojiBundle.previewTimer)
|
|
|
|
|
clearTimeout(wdtEmojiBundle.previewTimer);
|
|
|
|
|
|
|
|
|
|
if (wdtEmojiBundle.previewExitTimer)
|
|
|
|
|
clearTimeout(wdtEmojiBundle.previewExitTimer);
|
|
|
|
|
|
|
|
|
|
var emo = this;
|
|
|
|
|
|
|
|
|
|
wdtEmojiBundle.previewTimer = setTimeout(function () {
|
|
|
|
|
|
|
|
|
|
addClass(wdtEmojiBundle.popup, 'preview-mode');
|
|
|
|
|
|
|
|
|
|
wdtEmojiBundle.previewImg.innerHTML = self.emoji.replace_colons(':' + emo.dataset.wdtEmojiShortname + ':');
|
|
|
|
|
wdtEmojiBundle.previewName.innerHTML = emo.dataset.wdtEmojiShortname;
|
|
|
|
|
wdtEmojiBundle.previewAliases.innerHTML = emo.dataset.wdtEmojiShortnames;
|
|
|
|
|
|
|
|
|
|
}, 100);
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
live('mouseout', '.wdt-emoji-list a.wdt-emoji', function () {
|
|
|
|
|
if (wdtEmojiBundle.previewExitTimer)
|
|
|
|
|
clearTimeout(wdtEmojiBundle.previewExitTimer);
|
|
|
|
|
|
|
|
|
|
wdtEmojiBundle.previewExitTimer = setTimeout(function () {
|
|
|
|
|
removeClass(wdtEmojiBundle.popup, 'preview-mode');
|
|
|
|
|
}, 1000);
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
live('click', '.wdt-emoji-tab', function (e) {
|
|
|
|
|
var group = this.dataset.groupName,
|
|
|
|
|
groupHeader = wdtEmojiBundle.popup.querySelector('.wdt-emoji-section h3[data-emoji-group="' + group + '"]');
|
|
|
|
|
|
|
|
|
|
if (groupHeader) {
|
|
|
|
|
wdtEmojiBundle.setActiveTab(group);
|
|
|
|
|
wdtEmojiBundle.scroller.scrollTop = groupHeader.offsetTop - groupHeader.getBoundingClientRect().height - 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
live('input', '#wdt-emoji-search', function (e) {
|
|
|
|
|
var input = this;
|
|
|
|
|
if (wdtEmojiBundle.searchTimer) {
|
|
|
|
|
clearTimeout(wdtEmojiBundle.searchTimer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wdtEmojiBundle.searchTimer = setTimeout(function () {
|
|
|
|
|
wdtEmojiBundle.search(input.value);
|
|
|
|
|
}, 225);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
addListenerMulti(wdtEmojiBundle.scroller, 'mousewheel DOMMouseScroll', function(e) {
|
|
|
|
|
var delta = e.wheelDelta || (e.originalEvent && e.originalEvent.wheelDelta) || -e.detail,
|
|
|
|
|
bottomOverflow = this.scrollTop + this.getBoundingClientRect().height - this.scrollHeight >= 0,
|
|
|
|
|
topOverflow = this.scrollTop <= 0;
|
|
|
|
|
if ((delta < 0 && bottomOverflow) || (delta > 0 && topOverflow)) {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param q
|
|
|
|
|
* @returns {boolean}
|
|
|
|
|
*/
|
|
|
|
|
wdtEmojiBundle.fillSearch = function (q) {
|
|
|
|
|
if (wdtEmojiBundle.searchInput) {
|
|
|
|
|
wdtEmojiBundle.searchInput.value = q;
|
|
|
|
|
return wdtEmojiBundle.search(q);
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param q
|
|
|
|
|
* @returns {boolean}
|
|
|
|
|
*/
|
|
|
|
|
wdtEmojiBundle.search = function (q) {
|
|
|
|
|
|
|
|
|
|
var sections = wdtEmojiBundle.popup.querySelector('.wdt-emoji-sections'),
|
|
|
|
|
searchResultH3 = wdtEmojiBundle.popup.querySelector('#wdt-emoji-search-result-title'),
|
|
|
|
|
emojiList = sections.querySelectorAll('.wdt-emoji'),
|
|
|
|
|
zeroText = wdtEmojiBundle.popup.querySelector('#wdt-emoji-no-result'),
|
|
|
|
|
found = 0;
|
|
|
|
|
|
|
|
|
|
if (q == '') {
|
|
|
|
|
removeClass(searchResultH3, 'wdt-show');
|
|
|
|
|
removeClass(zeroText, 'wdt-show');
|
|
|
|
|
removeClassAll('.wdt-emoji.not-matched', 'not-matched');
|
|
|
|
|
removeClassAll('.wdt-emoji-section', 'wdt-inline');
|
|
|
|
|
removeClassAll('.wdt-emoji-list', 'wdt-inline');
|
|
|
|
|
removeClassAll('.wdt-emoji-section h3', 'wdt-search-on');
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < emojiList.length; i++) {
|
|
|
|
|
var emo = emojiList[i];
|
|
|
|
|
var sst = emo.dataset.wdtEmojiName + ' ' + emo.dataset.wdtEmojiShortnames;
|
|
|
|
|
|
|
|
|
|
removeClass(emo, 'not-matched');
|
|
|
|
|
if (sst.match(new RegExp(q, "gi"))) {
|
|
|
|
|
found++;
|
|
|
|
|
} else {
|
|
|
|
|
addClass(emo, 'not-matched');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addClass(searchResultH3, 'wdt-show');
|
|
|
|
|
addClassAll('.wdt-emoji-section', 'wdt-inline');
|
|
|
|
|
addClassAll('.wdt-emoji-list', 'wdt-inline');
|
|
|
|
|
addClassAll('.wdt-emoji-section h3', 'wdt-search-on');
|
|
|
|
|
|
|
|
|
|
if (found) {
|
|
|
|
|
removeClass(zeroText, 'wdt-show');
|
|
|
|
|
} else {
|
|
|
|
|
addClass(zeroText, 'wdt-show');
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @type {{select: Array, afterSelect: Array, afterPickerOpen: Array}}
|
|
|
|
|
*/
|
|
|
|
|
wdtEmojiBundle.dispatchHandlers = {
|
|
|
|
|
'select' : [],
|
|
|
|
|
'afterSelect' : [],
|
|
|
|
|
'afterPickerOpen': [] // not implemented
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param eventName
|
|
|
|
|
* @param handler
|
|
|
|
|
* @returns mixed
|
|
|
|
|
*/
|
|
|
|
|
wdtEmojiBundle.on = function (eventName, handler) {
|
|
|
|
|
switch (eventName) {
|
|
|
|
|
case "select":
|
|
|
|
|
return wdtEmojiBundle.dispatchHandlers.select.push(handler);
|
|
|
|
|
break;
|
|
|
|
|
case "afterSelect":
|
|
|
|
|
return wdtEmojiBundle.dispatchHandlers.afterSelect.push(handler);
|
|
|
|
|
break;
|
|
|
|
|
case "afterPickerOpen":
|
|
|
|
|
return wdtEmojiBundle.dispatchHandlers.afterPickerOpen.push(handler);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
console.error('wdt-emoji-bundle - Not supported event type!', eventName);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* On the fly emoji type changer apple, google, twitter, emojione
|
|
|
|
|
* @param changeType
|
|
|
|
|
*/
|
|
|
|
|
wdtEmojiBundle.changeType = function (changeType) {
|
|
|
|
|
var nextSheet = wdtEmojiBundle.defaults.emojiSheets[changeType],
|
|
|
|
|
currentEmojiList = document.querySelectorAll('.emoji-inner'),
|
|
|
|
|
i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < currentEmojiList.length; i++) {
|
|
|
|
|
var e = currentEmojiList[i];
|
|
|
|
|
css(e, {
|
|
|
|
|
'background-image': 'url(' + nextSheet + ')'
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wdtEmojiBundle.defaults.emojiType = changeType;
|
|
|
|
|
document.querySelector('body').dataset.wdtEmojiBundle = changeType;
|
|
|
|
|
this.emoji.img_set = changeType;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param color
|
|
|
|
|
*/
|
|
|
|
|
wdtEmojiBundle.changeSkinColor = function (color) {
|
|
|
|
|
// @todo - [needim] - support skin colors for apple emoji set
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param text
|
|
|
|
|
* @returns {string}
|
|
|
|
|
*/
|
|
|
|
|
wdtEmojiBundle.render = function (text) {
|
|
|
|
|
return this.emoji.replace_colons(this.emoji.replace_emoticons(this.emoji.replace_unified(text)));
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A trick for contenteditable range clear on blur
|
|
|
|
|
* @param el
|
|
|
|
|
*/
|
|
|
|
|
wdtEmojiBundle.addRangeStore = function (el) {
|
|
|
|
|
el.addEventListener('focus', function () {
|
|
|
|
|
var s = window.getSelection();
|
|
|
|
|
if (!wdtEmojiBundle.ranges[this.dataset.rangeIndex]) {
|
|
|
|
|
wdtEmojiBundle.ranges[this.dataset.rangeIndex] = new Range();
|
|
|
|
|
} else if (s.rangeCount > 0) {
|
|
|
|
|
s.removeAllRanges();
|
|
|
|
|
s.addRange(wdtEmojiBundle.ranges[this.dataset.rangeIndex]);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
addListenerMulti(el, 'mouseup keyup', function () {
|
|
|
|
|
wdtEmojiBundle.ranges[this.dataset.rangeIndex] = window.getSelection().getRangeAt(0);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
addListenerMulti(el, 'mousedown click', function (e) {
|
|
|
|
|
if (document.activeElement != this) {
|
|
|
|
|
if (e.stopPropagation) {
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
} else {
|
|
|
|
|
e.cancelBubble = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (e.preventDefault) {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
} else {
|
|
|
|
|
e.returnValue = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.focus();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param el
|
|
|
|
|
* @param events
|
|
|
|
|
* @param cb
|
|
|
|
|
*/
|
|
|
|
|
var addListenerMulti = function (el, events, cb) {
|
|
|
|
|
events = events.split(' ');
|
|
|
|
|
for (var i = 0; i < events.length; i++) {
|
|
|
|
|
el.addEventListener(events[i], cb, false);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Stick section header controls
|
|
|
|
|
* @param el
|
|
|
|
|
*/
|
|
|
|
|
var sticky = function (el) {
|
|
|
|
|
|
|
|
|
|
var scrollerRect = wdtEmojiBundle.scroller.getBoundingClientRect(),
|
|
|
|
|
elTop = el.getBoundingClientRect().top - scrollerRect.top,
|
|
|
|
|
tabHeaderHeight = wdtEmojiBundle.popup.querySelector('#wdt-emoji-menu-header').getBoundingClientRect().height;
|
|
|
|
|
|
|
|
|
|
wdtEmojiBundle.scroller.addEventListener("scroll", check);
|
|
|
|
|
|
|
|
|
|
function check() {
|
|
|
|
|
var scrollTop = wdtEmojiBundle.scroller.scrollTop;
|
|
|
|
|
|
|
|
|
|
if (hasClass(el, 'sticky') && scrollTop < elTop) {
|
|
|
|
|
|
|
|
|
|
removeClass(el, 'sticky');
|
|
|
|
|
css(el, {top: null});
|
|
|
|
|
css(el.parentNode, {'padding-top': null});
|
|
|
|
|
|
|
|
|
|
} else if (scrollTop > elTop && !hasClass(el, 'sticky')) {
|
|
|
|
|
|
|
|
|
|
var stickers = document.querySelectorAll('.wdt-emoji-section h3');
|
|
|
|
|
if (stickers.length) {
|
|
|
|
|
for (var i = 0; i < stickers.length; i++) {
|
|
|
|
|
removeClass(stickers[i], 'sticky');
|
|
|
|
|
css(stickers[i], {top: null});
|
|
|
|
|
css(stickers[i].parentNode, {'padding-top': null});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addClass(el, 'sticky');
|
|
|
|
|
css(el, {'top': tabHeaderHeight + 'px'});
|
|
|
|
|
css(el.parentNode, {'padding-top': el.getBoundingClientRect().height + 'px'});
|
|
|
|
|
|
|
|
|
|
wdtEmojiBundle.setActiveTab(el.dataset.emojiGroup);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param group
|
|
|
|
|
*/
|
|
|
|
|
wdtEmojiBundle.setActiveTab = function (group) {
|
|
|
|
|
var tabs = document.querySelectorAll('.wdt-emoji-tab');
|
|
|
|
|
if (tabs.length) {
|
|
|
|
|
for (var t = 0; t < tabs.length; t++) {
|
|
|
|
|
removeClass(tabs[t], 'active');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var activeTab = wdtEmojiBundle.popup.querySelector('.wdt-emoji-tab[data-group-name="' + group + '"]');
|
|
|
|
|
addClass(activeTab, 'active');
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param el
|
|
|
|
|
* @param cls
|
|
|
|
|
* @returns {*}
|
|
|
|
|
*/
|
|
|
|
|
var findParent = function (el, cls) {
|
|
|
|
|
while ((el = el.parentElement) && !el.classList.contains(cls));
|
|
|
|
|
return el;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param el
|
|
|
|
|
* @param cls
|
|
|
|
|
* @returns {*}
|
|
|
|
|
*/
|
|
|
|
|
var findChild = function (el, cls) {
|
|
|
|
|
var children = el.children;
|
|
|
|
|
for (var i = 0; i < children.length; i++) {
|
|
|
|
|
var child = children[i];
|
|
|
|
|
if (child.classList.contains(cls)) {
|
|
|
|
|
return child;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param el
|
|
|
|
|
* @returns {*}
|
|
|
|
|
*/
|
|
|
|
|
var getSelection = function (el) {
|
|
|
|
|
var result = {};
|
|
|
|
|
|
|
|
|
|
if (el.getAttribute('contenteditable')) {
|
|
|
|
|
return {
|
|
|
|
|
el: el,
|
|
|
|
|
ce: true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (window.getSelection) {
|
|
|
|
|
var val = el.value || el.innerHTML,
|
|
|
|
|
len = val.length,
|
|
|
|
|
start = el.selectionStart,
|
|
|
|
|
end = el.selectionEnd,
|
|
|
|
|
sel = val.substring(start, end);
|
|
|
|
|
|
|
|
|
|
result = {
|
|
|
|
|
"el" : el,
|
|
|
|
|
"start": start,
|
|
|
|
|
"end" : end,
|
|
|
|
|
"len" : len,
|
|
|
|
|
"sel" : sel
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
else if (document.selection) { // ie
|
|
|
|
|
var range = document.selection.createRange(),
|
|
|
|
|
value = el.value || el.innerHTML,
|
|
|
|
|
stored_range = range.duplicate();
|
|
|
|
|
|
|
|
|
|
stored_range.moveToElementText(el);
|
|
|
|
|
stored_range.setEndPoint('EndToEnd', range);
|
|
|
|
|
el.selectionStart = stored_range.text.length - range.text.length;
|
|
|
|
|
el.selectionEnd = el.selectionStart + range.text.length;
|
|
|
|
|
|
|
|
|
|
result = {
|
|
|
|
|
"el" : el,
|
|
|
|
|
"start": el.selectionStart,
|
|
|
|
|
"end" : el.selectionEnd,
|
|
|
|
|
"len" : value.length,
|
|
|
|
|
"sel" : range.text
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Replace selection text for :input
|
|
|
|
|
*
|
|
|
|
|
* @param el
|
|
|
|
|
* @param selection
|
|
|
|
|
* @param emo
|
|
|
|
|
*/
|
|
|
|
|
var replaceText = function (el, selection, emo) {
|
|
|
|
|
var val = el.value || el.innerHTML || '';
|
|
|
|
|
emo = emo + ' '; //append a space
|
|
|
|
|
|
|
|
|
|
if (selection.ce) { // if contenteditable
|
|
|
|
|
el.focus();
|
|
|
|
|
document.execCommand('insertText', false, emo);
|
|
|
|
|
} else {
|
|
|
|
|
var textBefore = val.substring(0, selection.start);
|
|
|
|
|
textBefore = textBefore.replace(/:\S*$/, '')
|
|
|
|
|
el.value = textBefore + emo + val.substring(selection.end, selection.len);
|
|
|
|
|
|
|
|
|
|
// @todo - [needim] - check browser compatibilities
|
|
|
|
|
el.selectionStart = el.selectionEnd = (textBefore.length + emo.length);
|
|
|
|
|
el.focus();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Fire custom events
|
|
|
|
|
*
|
|
|
|
|
* @param eventName
|
|
|
|
|
* @param params
|
|
|
|
|
*/
|
|
|
|
|
var fire = function (eventName, params) {
|
|
|
|
|
var handler, i, len, ref;
|
|
|
|
|
ref = wdtEmojiBundle.dispatchHandlers[eventName];
|
|
|
|
|
for (i = 0, len = ref.length; i < len; i++) {
|
|
|
|
|
handler = ref[i];
|
|
|
|
|
handler(params);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param eventType
|
|
|
|
|
* @param elementQuerySelector
|
|
|
|
|
* @param cb
|
|
|
|
|
*/
|
|
|
|
|
var live = function (eventType, elementQuerySelector, cb) {
|
|
|
|
|
document.addEventListener(eventType, function (event) {
|
|
|
|
|
|
|
|
|
|
var qs = document.querySelectorAll(elementQuerySelector);
|
|
|
|
|
|
|
|
|
|
if (qs) {
|
|
|
|
|
var el = event.target, index = -1;
|
|
|
|
|
while (el && ((index = Array.prototype.indexOf.call(qs, el)) === -1)) {
|
|
|
|
|
el = el.parentElement;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (index > -1) {
|
|
|
|
|
cb.call(el, event);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Applies css properties to an element, similar to the jQuery
|
|
|
|
|
* css method.
|
|
|
|
|
*
|
|
|
|
|
* While this helper does assist with vendor prefixed property names, it
|
|
|
|
|
* does not perform any manipulation of values prior to setting styles.
|
|
|
|
|
*/
|
|
|
|
|
var css = (function () {
|
|
|
|
|
var cssPrefixes = ['Webkit', 'O', 'Moz', 'ms'],
|
|
|
|
|
cssProps = {};
|
|
|
|
|
|
|
|
|
|
function camelCase(string) {
|
|
|
|
|
return string.replace(/^-ms-/, 'ms-').replace(/-([\da-z])/gi, function (match, letter) {
|
|
|
|
|
return letter.toUpperCase();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getVendorProp(name) {
|
|
|
|
|
var style = document.body.style;
|
|
|
|
|
if (name in style) return name;
|
|
|
|
|
|
|
|
|
|
var i = cssPrefixes.length,
|
|
|
|
|
capName = name.charAt(0).toUpperCase() + name.slice(1),
|
|
|
|
|
vendorName;
|
|
|
|
|
while (i--) {
|
|
|
|
|
vendorName = cssPrefixes[i] + capName;
|
|
|
|
|
if (vendorName in style) return vendorName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getStyleProp(name) {
|
|
|
|
|
name = camelCase(name);
|
|
|
|
|
return cssProps[name] || (cssProps[name] = getVendorProp(name));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function applyCss(element, prop, value) {
|
|
|
|
|
prop = getStyleProp(prop);
|
|
|
|
|
element.style[prop] = value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return function (element, properties) {
|
|
|
|
|
var args = arguments,
|
|
|
|
|
prop,
|
|
|
|
|
value;
|
|
|
|
|
|
|
|
|
|
if (args.length == 2) {
|
|
|
|
|
for (prop in properties) {
|
|
|
|
|
value = properties[prop];
|
|
|
|
|
if (value !== undefined && properties.hasOwnProperty(prop)) applyCss(element, prop, value);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
applyCss(element, args[1], args[2]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param element
|
|
|
|
|
* @param name
|
|
|
|
|
* @returns {boolean}
|
|
|
|
|
*/
|
|
|
|
|
function hasClass(element, name) {
|
|
|
|
|
var list = typeof element == 'string' ? element : classList(element);
|
|
|
|
|
return list.indexOf(' ' + name + ' ') >= 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param element
|
|
|
|
|
* @param name
|
|
|
|
|
*/
|
|
|
|
|
function addClass(element, name) {
|
|
|
|
|
var oldList = classList(element),
|
|
|
|
|
newList = oldList + name;
|
|
|
|
|
|
|
|
|
|
if (hasClass(oldList, name)) return;
|
|
|
|
|
|
|
|
|
|
// Trim the opening space.
|
|
|
|
|
element.className = newList.substring(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param query
|
|
|
|
|
* @param name
|
|
|
|
|
*/
|
|
|
|
|
function addClassAll(query, name) {
|
|
|
|
|
|
|
|
|
|
var elements = document.querySelectorAll(query);
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < elements.length; i++) {
|
|
|
|
|
var element = elements[i];
|
|
|
|
|
|
|
|
|
|
var oldList = classList(element),
|
|
|
|
|
newList = oldList + name;
|
|
|
|
|
|
|
|
|
|
if (hasClass(oldList, name)) return;
|
|
|
|
|
|
|
|
|
|
// Trim the opening space.
|
|
|
|
|
element.className = newList.substring(1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param element
|
|
|
|
|
* @param name
|
|
|
|
|
*/
|
|
|
|
|
function removeClass(element, name) {
|
|
|
|
|
var oldList = classList(element),
|
|
|
|
|
newList;
|
|
|
|
|
|
|
|
|
|
if (!hasClass(element, name)) return;
|
|
|
|
|
|
|
|
|
|
// Replace the class name.
|
|
|
|
|
newList = oldList.replace(' ' + name + ' ', ' ');
|
|
|
|
|
|
|
|
|
|
// Trim the opening and closing spaces.
|
|
|
|
|
element.className = newList.substring(1, newList.length - 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param query
|
|
|
|
|
* @param name
|
|
|
|
|
*/
|
|
|
|
|
function removeClassAll(query, name) {
|
|
|
|
|
|
|
|
|
|
var elements = document.querySelectorAll(query);
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < elements.length; i++) {
|
|
|
|
|
var element = elements[i];
|
|
|
|
|
|
|
|
|
|
var oldList = classList(element),
|
|
|
|
|
newList;
|
|
|
|
|
|
|
|
|
|
if (!hasClass(element, name)) return;
|
|
|
|
|
|
|
|
|
|
// Replace the class name.
|
|
|
|
|
newList = oldList.replace(' ' + name + ' ', ' ');
|
|
|
|
|
|
|
|
|
|
// Trim the opening and closing spaces.
|
|
|
|
|
element.className = newList.substring(1, newList.length - 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function inArray(needle, haystack) {
|
|
|
|
|
var length = haystack.length;
|
|
|
|
|
for(var i = 0; i < length; i++) {
|
|
|
|
|
if(haystack[i] == needle) return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param element
|
|
|
|
|
* @returns {string}
|
|
|
|
|
*/
|
|
|
|
|
function classList(element) {
|
|
|
|
|
return (' ' + (element && element.className || '') + ' ').replace(/\s+/gi, ' ');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return wdtEmojiBundle;
|
|
|
|
|
});
|