Path: blob/master/emojionearea/dist/emojionearea.js
572 views
/*!1* EmojioneArea v3.1.52* https://github.com/mervick/emojionearea3* Copyright Andrey Izman and other contributors4* Released under the MIT license5* Date: 2017-01-20T14:56Z6*/7(function(document, window, $) {8'use strict';910var unique = 0;11var eventStorage = {};12var possibleEvents = {};13var emojione = window.emojione;14var readyCallbacks = [];15function emojioneReady (fn) {16if (emojione) {17fn();18} else {19readyCallbacks.push(fn);20}21};22var blankImg = 'data:image/gif;base64,R0lGODlhAQABAJH/AP///wAAAMDAwAAAACH5BAEAAAIALAAAAAABAAEAAAICVAEAOw==';23var slice = [].slice;24var css_class = "emojionearea";25var emojioneSupportMode = 0;26var invisibleChar = '​';27function trigger(self, event, args) {28var result = true, j = 1;29if (event) {30event = event.toLowerCase();31do {32var _event = j==1 ? '@' + event : event;33if (eventStorage[self.id][_event] && eventStorage[self.id][_event].length) {34$.each(eventStorage[self.id][_event], function (i, fn) {35return result = fn.apply(self, args|| []) !== false;36});37}38} while (result && !!j--);39}40return result;41}42function attach(self, element, events, target) {43target = target || function (event, callerEvent) { return $(callerEvent.currentTarget) };44$.each(events, function(event, link) {45event = $.isArray(events) ? link : event;46(possibleEvents[self.id][link] || (possibleEvents[self.id][link] = []))47.push([element, event, target]);48});49}50function getTemplate(template, unicode, shortname) {51var imageType = emojione.imageType, imagePath;52if (imageType=='svg'){53imagePath = emojione.imagePathSVG;54} else {55imagePath = emojione.imagePathPNG;56}57return template58.replace('{name}', shortname || '')59.replace('{img}', imagePath + (emojioneSupportMode < 2 ? unicode.toUpperCase() : unicode) + '.' + imageType)60.replace('{uni}', unicode)61.replace('{alt}', emojione.convert(unicode));62};63function shortnameTo(str, template, clear) {64return str.replace(/:?\+?[\w_\-]+:?/g, function(shortname) {65shortname = ":" + shortname.replace(/:$/,'').replace(/^:/,'') + ":";66var unicode = emojione.emojioneList[shortname];67if (unicode) {68if (emojioneSupportMode > 3) unicode = unicode.unicode;69return getTemplate(template, unicode[unicode.length-1], shortname);70}71return clear ? '' : shortname;72});73};74function pasteHtmlAtCaret(html) {75var sel, range;76if (window.getSelection) {77sel = window.getSelection();78if (sel.getRangeAt && sel.rangeCount) {79range = sel.getRangeAt(0);80range.deleteContents();81var el = document.createElement("div");82el.innerHTML = html;83var frag = document.createDocumentFragment(), node, lastNode;84while ( (node = el.firstChild) ) {85lastNode = frag.appendChild(node);86}87range.insertNode(frag);88if (lastNode) {89range = range.cloneRange();90range.setStartAfter(lastNode);91range.collapse(true);92sel.removeAllRanges();93sel.addRange(range);94}95}96} else if (document.selection && document.selection.type != "Control") {97document.selection.createRange().pasteHTML(html);98}99}100var getDefaultOptions = function () {101return $.fn.emojioneArea && $.fn.emojioneArea.defaults ? $.fn.emojioneArea.defaults : {102attributes: {103dir : "ltr",104spellcheck : false,105autocomplete : "off",106autocorrect : "off",107autocapitalize : "off",108},109placeholder : null,110emojiPlaceholder : ":smiley:",111container : null,112hideSource : true,113shortnames : true,114sprite : true,115pickerPosition : "top", // top | bottom | right116filtersPosition : "top", // top | bottom117hidePickerOnBlur : true,118buttonTitle : "Use the TAB key to insert emoji faster",119tones : true,120tonesStyle : "bullet", // bullet | radio | square | checkbox121inline : null, // null - auto122saveEmojisAs : "unicode", // unicode | shortname | image123shortcuts : true,124autocomplete : true,125autocompleteTones : false,126standalone : false,127useInternalCDN : true, // Use the self loading mechanism128imageType : "png", // Default image type used by internal CDN129recentEmojis : true,130textcomplete: {131maxCount : 15,132placement : null // null - default | top | absleft | absright133},134135filters: {136tones: {137title: "Diversity",138emoji: "santa runner surfer swimmer lifter ear nose point_up_2 point_down point_left point_right punch " +139"wave ok_hand thumbsup thumbsdown clap open_hands boy girl man woman cop bride_with_veil person_with_blond_hair " +140"man_with_gua_pi_mao man_with_turban older_man grandma baby construction_worker princess angel " +141"information_desk_person guardsman dancer nail_care massage haircut muscle spy hand_splayed middle_finger " +142"vulcan no_good ok_woman bow raising_hand raised_hands person_frowning person_with_pouting_face pray rowboat " +143"bicyclist mountain_bicyclist walking bath metal point_up basketball_player fist raised_hand v writing_hand"144},145146recent: {147icon: "clock3",148title: "Recent",149emoji: ""150},151152smileys_people: {153icon: "yum",154title: "Smileys & People",155emoji: "grinning grimacing grin joy smiley smile sweat_smile laughing innocent wink blush slight_smile " +156"upside_down relaxed yum relieved heart_eyes kissing_heart kissing kissing_smiling_eyes " +157"kissing_closed_eyes stuck_out_tongue_winking_eye stuck_out_tongue_closed_eyes stuck_out_tongue " +158"money_mouth nerd sunglasses hugging smirk no_mouth neutral_face expressionless unamused rolling_eyes " +159"thinking flushed disappointed worried angry rage pensive confused slight_frown frowning2 persevere " +160"confounded tired_face weary triumph open_mouth scream fearful cold_sweat hushed frowning anguished " +161"cry disappointed_relieved sleepy sweat sob dizzy_face astonished zipper_mouth mask thermometer_face " +162"head_bandage sleeping zzz poop smiling_imp imp japanese_ogre japanese_goblin skull ghost alien robot " +163"smiley_cat smile_cat joy_cat heart_eyes_cat smirk_cat kissing_cat scream_cat crying_cat_face " +164"pouting_cat raised_hands clap wave thumbsup thumbsdown punch fist v ok_hand raised_hand open_hands " +165"muscle pray point_up point_up_2 point_down point_left point_right middle_finger hand_splayed metal " +166"vulcan writing_hand nail_care lips tongue ear nose eye eyes bust_in_silhouette busts_in_silhouette " +167"speaking_head baby boy girl man woman person_with_blond_hair older_man older_woman man_with_gua_pi_mao " +168"man_with_turban cop construction_worker guardsman spy santa angel princess bride_with_veil walking " +169"runner dancer dancers couple two_men_holding_hands two_women_holding_hands bow information_desk_person " +170"no_good ok_woman raising_hand person_with_pouting_face person_frowning haircut massage couple_with_heart " +171"couple_ww couple_mm couplekiss kiss_ww kiss_mm family family_mwg family_mwgb family_mwbb family_mwgg " +172"family_wwb family_wwg family_wwgb family_wwbb family_wwgg family_mmb family_mmg family_mmgb family_mmbb " +173"family_mmgg womans_clothes shirt jeans necktie dress bikini kimono lipstick kiss footprints high_heel " +174"sandal boot mans_shoe athletic_shoe womans_hat tophat helmet_with_cross mortar_board crown school_satchel " +175"pouch purse handbag briefcase eyeglasses dark_sunglasses ring closed_umbrella"176},177178animals_nature: {179icon: "hamster",180title: "Animals & Nature",181emoji: "dog cat mouse hamster rabbit bear panda_face koala tiger lion_face cow pig pig_nose frog " +182"octopus monkey_face see_no_evil hear_no_evil speak_no_evil monkey chicken penguin bird baby_chick " +183"hatching_chick hatched_chick wolf boar horse unicorn bee bug snail beetle ant spider scorpion crab " +184"snake turtle tropical_fish fish blowfish dolphin whale whale2 crocodile leopard tiger2 water_buffalo " +185"ox cow2 dromedary_camel camel elephant goat ram sheep racehorse pig2 rat mouse2 rooster turkey dove " +186"dog2 poodle cat2 rabbit2 chipmunk feet dragon dragon_face cactus christmas_tree evergreen_tree " +187"deciduous_tree palm_tree seedling herb shamrock four_leaf_clover bamboo tanabata_tree leaves " +188"fallen_leaf maple_leaf ear_of_rice hibiscus sunflower rose tulip blossom cherry_blossom bouquet " +189"mushroom chestnut jack_o_lantern shell spider_web earth_americas earth_africa earth_asia full_moon " +190"waning_gibbous_moon last_quarter_moon waning_crescent_moon new_moon waxing_crescent_moon " +191"first_quarter_moon waxing_gibbous_moon new_moon_with_face full_moon_with_face first_quarter_moon_with_face " +192"last_quarter_moon_with_face sun_with_face crescent_moon star star2 dizzy sparkles comet sunny " +193"white_sun_small_cloud partly_sunny white_sun_cloud white_sun_rain_cloud cloud cloud_rain " +194"thunder_cloud_rain cloud_lightning zap fire boom snowflake cloud_snow snowman2 snowman wind_blowing_face " +195"dash cloud_tornado fog umbrella2 umbrella droplet sweat_drops ocean"196},197198food_drink: {199icon: "pizza",200title: "Food & Drink",201emoji: "green_apple apple pear tangerine lemon banana watermelon grapes strawberry melon cherries peach " +202"pineapple tomato eggplant hot_pepper corn sweet_potato honey_pot bread cheese poultry_leg meat_on_bone " +203"fried_shrimp egg hamburger fries hotdog pizza spaghetti taco burrito ramen stew fish_cake sushi bento " +204"curry rice_ball rice rice_cracker oden dango shaved_ice ice_cream icecream cake birthday custard candy " +205"lollipop chocolate_bar popcorn doughnut cookie beer beers wine_glass cocktail tropical_drink champagne " +206"sake tea coffee baby_bottle fork_and_knife fork_knife_plate"207},208209activity: {210icon: "basketball",211title: "Activity",212emoji: "soccer basketball football baseball tennis volleyball rugby_football 8ball golf golfer ping_pong " +213"badminton hockey field_hockey cricket ski skier snowboarder ice_skate bow_and_arrow fishing_pole_and_fish " +214"rowboat swimmer surfer bath basketball_player lifter bicyclist mountain_bicyclist horse_racing levitate " +215"trophy running_shirt_with_sash medal military_medal reminder_ribbon rosette ticket tickets performing_arts " +216"art circus_tent microphone headphones musical_score musical_keyboard saxophone trumpet guitar violin " +217"clapper video_game space_invader dart game_die slot_machine bowling"218},219220travel_places: {221icon: "rocket",222title: "Travel & Places",223emoji: "red_car taxi blue_car bus trolleybus race_car police_car ambulance fire_engine minibus truck " +224"articulated_lorry tractor motorcycle bike rotating_light oncoming_police_car oncoming_bus " +225"oncoming_automobile oncoming_taxi aerial_tramway mountain_cableway suspension_railway railway_car " +226"train monorail bullettrain_side bullettrain_front light_rail mountain_railway steam_locomotive train2 " +227"metro tram station helicopter airplane_small airplane airplane_departure airplane_arriving sailboat " +228"motorboat speedboat ferry cruise_ship rocket satellite_orbital seat anchor construction fuelpump busstop " +229"vertical_traffic_light traffic_light checkered_flag ship ferris_wheel roller_coaster carousel_horse " +230"construction_site foggy tokyo_tower factory fountain rice_scene mountain mountain_snow mount_fuji volcano " +231"japan camping tent park motorway railway_track sunrise sunrise_over_mountains desert beach island " +232"city_sunset city_dusk cityscape night_with_stars bridge_at_night milky_way stars sparkler fireworks " +233"rainbow homes european_castle japanese_castle stadium statue_of_liberty house house_with_garden " +234"house_abandoned office department_store post_office european_post_office hospital bank hotel " +235"convenience_store school love_hotel wedding classical_building church mosque synagogue kaaba shinto_shrine"236},237238objects: {239icon: "bulb",240title: "Objects",241emoji: "watch iphone calling computer keyboard desktop printer mouse_three_button trackball joystick " +242"compression minidisc floppy_disk cd dvd vhs camera camera_with_flash video_camera movie_camera projector " +243"film_frames telephone_receiver telephone pager fax tv radio microphone2 level_slider control_knobs " +244"stopwatch timer alarm_clock clock hourglass_flowing_sand hourglass satellite battery electric_plug bulb " +245"flashlight candle wastebasket oil money_with_wings dollar yen euro pound moneybag credit_card gem scales " +246"wrench hammer hammer_pick tools pick nut_and_bolt gear chains gun bomb knife dagger crossed_swords shield " +247"smoking skull_crossbones coffin urn amphora crystal_ball prayer_beads barber alembic telescope microscope " +248"hole pill syringe thermometer label bookmark toilet shower bathtub key key2 couch sleeping_accommodation " +249"bed door bellhop frame_photo map beach_umbrella moyai shopping_bags balloon flags ribbon gift confetti_ball " +250"tada dolls wind_chime crossed_flags izakaya_lantern envelope envelope_with_arrow incoming_envelope e-mail " +251"love_letter postbox mailbox_closed mailbox mailbox_with_mail mailbox_with_no_mail package postal_horn " +252"inbox_tray outbox_tray scroll page_with_curl bookmark_tabs bar_chart chart_with_upwards_trend " +253"chart_with_downwards_trend page_facing_up date calendar calendar_spiral card_index card_box ballot_box " +254"file_cabinet clipboard notepad_spiral file_folder open_file_folder dividers newspaper2 newspaper notebook " +255"closed_book green_book blue_book orange_book notebook_with_decorative_cover ledger books book link " +256"paperclip paperclips scissors triangular_ruler straight_ruler pushpin round_pushpin triangular_flag_on_post " +257"flag_white flag_black closed_lock_with_key lock unlock lock_with_ink_pen pen_ballpoint pen_fountain " +258"black_nib pencil pencil2 crayon paintbrush mag mag_right"259},260261symbols: {262icon: "heartpulse",263title: "Symbols",264emoji: "heart yellow_heart green_heart blue_heart purple_heart broken_heart heart_exclamation two_hearts " +265"revolving_hearts heartbeat heartpulse sparkling_heart cupid gift_heart heart_decoration peace cross " +266"star_and_crescent om_symbol wheel_of_dharma star_of_david six_pointed_star menorah yin_yang orthodox_cross " +267"place_of_worship ophiuchus aries taurus gemini cancer leo virgo libra scorpius sagittarius capricorn " +268"aquarius pisces id atom u7a7a u5272 radioactive biohazard mobile_phone_off vibration_mode u6709 u7121 " +269"u7533 u55b6 u6708 eight_pointed_black_star vs accept white_flower ideograph_advantage secret congratulations " +270"u5408 u6e80 u7981 a b ab cl o2 sos no_entry name_badge no_entry_sign x o anger hotsprings no_pedestrians " +271"do_not_litter no_bicycles non-potable_water underage no_mobile_phones exclamation grey_exclamation question " +272"grey_question bangbang interrobang 100 low_brightness high_brightness trident fleur-de-lis part_alternation_mark " +273"warning children_crossing beginner recycle u6307 chart sparkle eight_spoked_asterisk negative_squared_cross_mark " +274"white_check_mark diamond_shape_with_a_dot_inside cyclone loop globe_with_meridians m atm sa passport_control " +275"customs baggage_claim left_luggage wheelchair no_smoking wc parking potable_water mens womens baby_symbol " +276"restroom put_litter_in_its_place cinema signal_strength koko ng ok up cool new free zero one two three four " +277"five six seven eight nine ten 1234 arrow_forward pause_button play_pause stop_button record_button track_next " +278"track_previous fast_forward rewind twisted_rightwards_arrows repeat repeat_one arrow_backward arrow_up_small " +279"arrow_down_small arrow_double_up arrow_double_down arrow_right arrow_left arrow_up arrow_down arrow_upper_right " +280"arrow_lower_right arrow_lower_left arrow_upper_left arrow_up_down left_right_arrow arrows_counterclockwise " +281"arrow_right_hook leftwards_arrow_with_hook arrow_heading_up arrow_heading_down hash asterisk information_source " +282"abc abcd capital_abcd symbols musical_note notes wavy_dash curly_loop heavy_check_mark arrows_clockwise " +283"heavy_plus_sign heavy_minus_sign heavy_division_sign heavy_multiplication_x heavy_dollar_sign currency_exchange " +284"copyright registered tm end back on top soon ballot_box_with_check radio_button white_circle black_circle " +285"red_circle large_blue_circle small_orange_diamond small_blue_diamond large_orange_diamond large_blue_diamond " +286"small_red_triangle black_small_square white_small_square black_large_square white_large_square small_red_triangle_down " +287"black_medium_square white_medium_square black_medium_small_square white_medium_small_square black_square_button " +288"white_square_button speaker sound loud_sound mute mega loudspeaker bell no_bell black_joker mahjong spades " +289"clubs hearts diamonds flower_playing_cards thought_balloon anger_right speech_balloon clock1 clock2 clock3 " +290"clock4 clock5 clock6 clock7 clock8 clock9 clock10 clock11 clock12 clock130 clock230 clock330 clock430 " +291"clock530 clock630 clock730 clock830 clock930 clock1030 clock1130 clock1230 eye_in_speech_bubble"292},293294flags: {295icon: "flag_gb",296title: "Flags",297emoji: "ac af al dz ad ao ai ag ar am aw au at az bs bh bd bb by be bz bj bm bt bo ba bw br bn bg bf bi " +298"cv kh cm ca ky cf td flag_cl cn co km cg flag_cd cr hr cu cy cz dk dj dm do ec eg sv gq er ee et fk fo " +299"fj fi fr pf ga gm ge de gh gi gr gl gd gu gt gn gw gy ht hn hk hu is in flag_id ir iq ie il it ci jm jp " +300"je jo kz ke ki xk kw kg la lv lb ls lr ly li lt lu mo mk mg mw my mv ml mt mh mr mu mx fm md mc mn me " +301"ms ma mz mm na nr np nl nc nz ni ne flag_ng nu kp no om pk pw ps pa pg py pe ph pl pt pr qa ro ru rw " +302"sh kn lc vc ws sm st flag_sa sn rs sc sl sg sk si sb so za kr es lk sd sr sz se ch sy tw tj tz th tl " +303"tg to tt tn tr flag_tm flag_tm ug ua ae gb us vi uy uz vu va ve vn wf eh ye zm zw re ax ta io bq cx " +304"cc gg im yt nf pn bl pm gs tk bv hm sj um ic ea cp dg as aq vg ck cw eu gf tf gp mq mp sx ss tc "305}306}307};308};309function isObject(variable) {310return typeof variable === 'object';311};312function getOptions(options) {313var default_options = getDefaultOptions();314if (options && options['filters']) {315var filters = default_options.filters;316$.each(options['filters'], function(filter, data) {317if (!isObject(data) || $.isEmptyObject(data)) {318delete filters[filter];319return;320}321$.each(data, function(key, val) {322filters[filter][key] = val;323});324});325options['filters'] = filters;326}327return $.extend({}, default_options, options);328};329330var saveSelection, restoreSelection;331if (window.getSelection && document.createRange) {332saveSelection = function(el) {333var sel = window.getSelection && window.getSelection();334if (sel && sel.rangeCount > 0) {335var range = sel.getRangeAt(0);336var preSelectionRange = range.cloneRange();337preSelectionRange.selectNodeContents(el);338preSelectionRange.setEnd(range.startContainer, range.startOffset);339return preSelectionRange.toString().length;340}341};342343restoreSelection = function(el, sel) {344var charIndex = 0, range = document.createRange();345range.setStart(el, 0);346range.collapse(true);347var nodeStack = [el], node, foundStart = false, stop = false;348349while (!stop && (node = nodeStack.pop())) {350if (node.nodeType == 3) {351var nextCharIndex = charIndex + node.length;352if (!foundStart && sel >= charIndex && sel <= nextCharIndex) {353range.setStart(node, sel - charIndex);354range.setEnd(node, sel - charIndex);355stop = true;356}357charIndex = nextCharIndex;358} else {359var i = node.childNodes.length;360while (i--) {361nodeStack.push(node.childNodes[i]);362}363}364}365366sel = window.getSelection();367sel.removeAllRanges();368sel.addRange(range);369}370} else if (document.selection && document.body.createTextRange) {371saveSelection = function(el) {372var selectedTextRange = document.selection.createRange(),373preSelectionTextRange = document.body.createTextRange();374preSelectionTextRange.moveToElementText(el);375preSelectionTextRange.setEndPoint("EndToStart", selectedTextRange);376var start = preSelectionTextRange.text.length;377return start + selectedTextRange.text.length;378};379380restoreSelection = function(el, sel) {381var textRange = document.body.createTextRange();382textRange.moveToElementText(el);383textRange.collapse(true);384textRange.moveEnd("character", sel);385textRange.moveStart("character", sel);386textRange.select();387};388}389390391var uniRegexp;392function unicodeTo(str, template) {393return str.replace(uniRegexp, function(unicodeChar) {394var map = emojione[(emojioneSupportMode === 0 ? 'jsecapeMap' : 'jsEscapeMap')];395if (typeof unicodeChar !== 'undefined' && unicodeChar in map) {396return getTemplate(template, map[unicodeChar]);397}398return unicodeChar;399});400}401function htmlFromText(str, self) {402str = str403.replace(/&/g, '&')404.replace(/</g, '<')405.replace(/>/g, '>')406.replace(/"/g, '"')407.replace(/'/g, ''')408.replace(/`/g, '`')409.replace(/(?:\r\n|\r|\n)/g, '\n')410.replace(/(\n+)/g, '<div>$1</div>')411.replace(/\n/g, '<br/>')412.replace(/<br\/><\/div>/g, '</div>');413if (self.shortnames) {414str = emojione.shortnameToUnicode(str);415}416return unicodeTo(str, self.emojiTemplate)417.replace(/\t/g, ' ')418.replace(/ /g, ' ');419}420function textFromHtml(str, self) {421str = str422.replace(/<img[^>]*alt="([^"]+)"[^>]*>/ig, '$1')423.replace(/\n|\r/g, '')424.replace(/<br[^>]*>/ig, '\n')425.replace(/(?:<(?:div|p|ol|ul|li|pre|code|object)[^>]*>)+/ig, '<div>')426.replace(/(?:<\/(?:div|p|ol|ul|li|pre|code|object)>)+/ig, '</div>')427.replace(/\n<div><\/div>/ig, '\n')428.replace(/<div><\/div>\n/ig, '\n')429.replace(/(?:<div>)+<\/div>/ig, '\n')430.replace(/([^\n])<\/div><div>/ig, '$1\n')431.replace(/(?:<\/div>)+/ig, '</div>')432.replace(/([^\n])<\/div>([^\n])/ig, '$1\n$2')433.replace(/<\/div>/ig, '')434.replace(/([^\n])<div>/ig, '$1\n')435.replace(/\n<div>/ig, '\n')436.replace(/<div>\n/ig, '\n\n')437.replace(/<(?:[^>]+)?>/g, '')438.replace(new RegExp(invisibleChar, 'g'), '')439.replace(/ /g, ' ')440.replace(/</g, '<')441.replace(/>/g, '>')442.replace(/"/g, '"')443.replace(/'/g, "'")444.replace(/`/g, '`')445.replace(/&/g, '&');446447switch (self.saveEmojisAs) {448case 'image':449str = unicodeTo(str, self.emojiTemplate);450break;451case 'shortname':452str = emojione.toShort(str);453}454return str;455}456function calcButtonPosition() {457var self = this,458offset = self.editor[0].offsetWidth - self.editor[0].clientWidth,459current = parseInt(self.button.css('marginRight'));460if (current !== offset) {461self.button.css({marginRight: offset});462if (self.floatingPicker) {463self.picker.css({right: parseInt(self.picker.css('right')) - current + offset});464}465}466}467function lazyLoading() {468var self = this;469if (!self.sprite && self.lasyEmoji[0]) {470var pickerTop = self.picker.offset().top,471pickerBottom = pickerTop + self.picker.height() + 20;472self.lasyEmoji.each(function() {473var e = $(this), top = e.offset().top;474if (top > pickerTop && top < pickerBottom) {475e.attr("src", e.data("src")).removeClass("lazy-emoji");476}477})478self.lasyEmoji = self.lasyEmoji.filter(".lazy-emoji");479}480}481function selector (prefix, skip_dot) {482return (skip_dot ? '' : '.') + css_class + (prefix ? ("-" + prefix) : "");483}484function div(prefix) {485var parent = $('<div/>', isObject(prefix) ? prefix : {"class" : selector(prefix, true)});486$.each(slice.call(arguments).slice(1), function(i, child) {487if ($.isFunction(child)) {488child = child.call(parent);489}490if (child) {491$(child).appendTo(parent);492}493});494return parent;495}496function getRecent () {497return localStorage.getItem("recent_emojis") || "";498}499function updateRecent(self) {500var emojis = getRecent();501if (!self.recent || self.recent !== emojis) {502if (emojis.length) {503var skinnable = self.scrollArea.is(".skinnable"),504scrollTop, height;505506if (!skinnable) {507scrollTop = self.scrollArea.scrollTop();508height = self.recentCategory.is(":visible") ? self.recentCategory.height() : 0;509}510511var items = shortnameTo(emojis, self.emojiBtnTemplate, true).split('|').join('');512self.recentCategory.children(".emojibtn").remove();513$(items).insertAfter(self.recentCategory.children("h1"));514515516self.recentCategory.children(".emojibtn").on("click", function() {517self.trigger("emojibtn.click", $(this));518});519520self.recentFilter.show();521522if (!skinnable) {523self.recentCategory.show();524525var height2 = self.recentCategory.height();526527if (height !== height2) {528self.scrollArea.scrollTop(scrollTop + height2 - height);529}530}531} else {532if (self.recentFilter.hasClass("active")) {533self.recentFilter.removeClass("active").next().addClass("active");534}535self.recentCategory.hide();536self.recentFilter.hide();537}538self.recent = emojis;539}540};541function setRecent(self, emoji) {542var recent = getRecent();543var emojis = recent.split("|");544545var index = emojis.indexOf(emoji);546if (index !== -1) {547emojis.splice(index, 1);548}549emojis.unshift(emoji);550551if (emojis.length > 9) {552emojis.pop();553}554555localStorage.setItem("recent_emojis", emojis.join("|"));556557updateRecent(self);558};559// see https://github.com/Modernizr/Modernizr/blob/master/feature-detects/storage/localstorage.js560function supportsLocalStorage () {561var test = 'test';562try {563localStorage.setItem(test, test);564localStorage.removeItem(test);565return true;566} catch(e) {567return false;568}569}570function init(self, source, options) {571//calcElapsedTime('init', function() {572options = getOptions(options);573self.sprite = options.sprite && emojioneSupportMode < 3;574self.inline = options.inline === null ? source.is("INPUT") : options.inline;575self.shortnames = options.shortnames;576self.saveEmojisAs = options.saveEmojisAs;577self.standalone = options.standalone;578self.emojiTemplate = '<img alt="{alt}" class="emojione' + (self.sprite ? '-{uni}" src="' + blankImg + '"/>' : 'emoji" src="{img}"/>');579self.emojiTemplateAlt = self.sprite ? '<i class="emojione-{uni}"/>' : '<img class="emojioneemoji" src="{img}"/>';580self.emojiBtnTemplate = '<i class="emojibtn" role="button" data-name="{name}">' + self.emojiTemplateAlt + '</i>';581self.recentEmojis = options.recentEmojis && supportsLocalStorage();582583var pickerPosition = options.pickerPosition;584self.floatingPicker = pickerPosition === 'top' || pickerPosition === 'bottom';585586var sourceValFunc = source.is("TEXTAREA") || source.is("INPUT") ? "val" : "text",587editor, button, picker, tones, filters, filtersBtns, emojisList, categories, scrollArea,588app = div({589"class" : css_class + ((self.standalone) ? " " + css_class + "-standalone " : " ") + (source.attr("class") || ""),590role: "application"591},592editor = self.editor = div("editor").attr({593contenteditable: (self.standalone) ? false : true,594placeholder: options["placeholder"] || source.data("placeholder") || source.attr("placeholder") || "",595tabindex: 0596}),597button = self.button = div('button',598div('button-open'),599div('button-close')600).attr('title', options.buttonTitle),601picker = self.picker = div('picker',602div('wrapper',603filters = div('filters'),604scrollArea = div('scroll-area',605emojisList = div('emojis-list'),606tones = div('tones',607function() {608if (options.tones) {609this.addClass(selector('tones-' + options.tonesStyle, true));610for (var i = 0; i <= 5; i++) {611this.append($("<i/>", {612"class": "btn-tone btn-tone-" + i + (!i ? " active" : ""),613"data-skin": i,614role: "button"615}));616}617}618}619)620)621)622).addClass(selector('picker-position-' + options.pickerPosition, true))623.addClass(selector('filters-position-' + options.filtersPosition, true))624.addClass('hidden')625);626627editor.data(source.data());628629$.each(options.attributes, function(attr, value) {630editor.attr(attr, value);631});632633$.each(options.filters, function(filter, params) {634var skin = 0;635if (filter === 'recent' && !self.recentEmojis) {636return;637}638if (filter !== 'tones') {639$("<i/>", {640"class": selector("filter", true) + " " + selector("filter-" + filter, true),641"data-filter": filter,642title: params.title643})644.wrapInner(shortnameTo(params.icon, self.emojiTemplateAlt))645.appendTo(filters);646} else if (options.tones) {647skin = 5;648} else {649return;650}651do {652var category = div('category').attr({name: filter, "data-tone": skin}).appendTo(emojisList),653items = params.emoji.replace(/[\s,;]+/g, '|');654if (skin > 0) {655category.hide();656items = items.split('|').join('_tone' + skin + '|') + '_tone' + skin;657}658659if (filter === 'recent') {660items = getRecent();661}662663items = shortnameTo(items,664self.sprite ?665'<i class="emojibtn" role="button" data-name="{name}"><i class="emojione-{uni}"></i></i>' :666'<i class="emojibtn" role="button" data-name="{name}"><img class="emojioneemoji lazy-emoji" data-src="{img}"/></i>',667true).split('|').join('');668669category.html(items);670$('<h1/>').text(params.title).prependTo(category);671} while (--skin > 0);672});673674options.filters = null;675if (!self.sprite) {676self.lasyEmoji = emojisList.find(".lazy-emoji");677}678679filtersBtns = filters.find(selector("filter"));680filtersBtns.eq(0).addClass("active");681categories = emojisList.find(selector("category"));682683self.recentFilter = filtersBtns.filter('[data-filter="recent"]');684self.recentCategory = categories.filter("[name=recent]");685686self.scrollArea = scrollArea;687688if (options.container) {689$(options.container).wrapInner(app);690} else {691app.insertAfter(source);692}693694if (options.hideSource) {695source.hide();696}697698self.setText(source[sourceValFunc]());699source[sourceValFunc](self.getText());700calcButtonPosition.apply(self);701702// if in standalone mode and no value is set, initialise with a placeholder703if (self.standalone && !self.getText().length) {704var placeholder = $(source).data("emoji-placeholder") || options.emojiPlaceholder;705self.setText(placeholder);706editor.addClass("has-placeholder");707}708709// attach() must be called before any .on() methods !!!710// 1) attach() stores events into possibleEvents{},711// 2) .on() calls bindEvent() and stores handlers into eventStorage{},712// 3) bindEvent() finds events in possibleEvents{} and bind founded via jQuery.on()713// 4) attached events via jQuery.on() calls trigger()714// 5) trigger() calls handlers stored into eventStorage{}715716attach(self, emojisList.find(".emojibtn"), {click: "emojibtn.click"});717attach(self, window, {resize: "!resize"});718attach(self, tones.children(), {click: "tone.click"});719attach(self, [picker, button], {mousedown: "!mousedown"}, editor);720attach(self, button, {click: "button.click"});721attach(self, editor, {paste :"!paste"}, editor);722attach(self, editor, ["focus", "blur"], function() { return self.stayFocused ? false : editor; });723attach(self, picker, {mousedown: "picker.mousedown", mouseup: "picker.mouseup", click: "picker.click",724keyup: "picker.keyup", keydown: "picker.keydown", keypress: "picker.keypress"});725attach(self, editor, ["mousedown", "mouseup", "click", "keyup", "keydown", "keypress"]);726attach(self, picker.find(".emojionearea-filter"), {click: "filter.click"});727728var noListenScroll = false;729scrollArea.on('scroll', function () {730if (!noListenScroll) {731lazyLoading.call(self);732if (scrollArea.is(":not(.skinnable)")) {733var item = categories.eq(0), scrollTop = scrollArea.offset().top;734categories.each(function (i, e) {735if ($(e).offset().top - scrollTop >= 10) {736return false;737}738item = $(e);739});740var filter = filtersBtns.filter('[data-filter="' + item.attr("name") + '"]');741if (filter[0] && !filter.is(".active")) {742filtersBtns.removeClass("active");743filter.addClass("active");744}745}746}747});748749self.on("@filter.click", function(filter) {750var isActive = filter.is(".active");751if (scrollArea.is(".skinnable")) {752if (isActive) return;753tones.children().eq(0).click();754}755noListenScroll = true;756if (!isActive) {757filtersBtns.filter(".active").removeClass("active");758filter.addClass("active");759}760var headerOffset = categories.filter('[name="' + filter.data('filter') + '"]').offset().top,761scroll = scrollArea.scrollTop(),762offsetTop = scrollArea.offset().top;763scrollArea.stop().animate({764scrollTop: headerOffset + scroll - offsetTop - 2765}, 200, 'swing', function () {766lazyLoading.call(self);767noListenScroll = false;768});769})770771.on("@picker.show", function() {772if (self.recentEmojis) {773updateRecent(self);774}775lazyLoading.call(self);776})777778.on("@tone.click", function(tone) {779tones.children().removeClass("active");780var skin = tone.addClass("active").data("skin");781if (skin) {782scrollArea.addClass("skinnable");783categories.hide().filter("[data-tone=" + skin + "]").show();784if (filtersBtns.eq(0).is('.active[data-filter="recent"]')) {785filtersBtns.eq(0).removeClass("active").next().addClass("active");786}787} else {788scrollArea.removeClass("skinnable");789categories.hide().filter("[data-tone=0]").show();790filtersBtns.eq(0).click();791}792lazyLoading.call(self);793})794795.on("@button.click", function(button) {796if (button.is(".active")) {797self.hidePicker();798} else {799self.showPicker();800}801})802803.on("@!paste", function(editor, event) {804805var pasteText = function(text) {806var caretID = "caret-" + (new Date()).getTime();807var html = htmlFromText(text, self);808pasteHtmlAtCaret(html);809pasteHtmlAtCaret('<i id="' + caretID +'"></i>');810editor.scrollTop(editorScrollTop);811var caret = $("#" + caretID),812top = caret.offset().top - editor.offset().top,813height = editor.height();814if (editorScrollTop + top >= height || editorScrollTop > top) {815editor.scrollTop(editorScrollTop + top - 2 * height/3);816}817caret.remove();818self.stayFocused = false;819calcButtonPosition.apply(self);820trigger(self, 'paste', [editor, text, html]);821}822823if (event.originalEvent.clipboardData) {824var text = event.originalEvent.clipboardData.getData('text/plain');825pasteText(text);826827if (event.preventDefault){828event.preventDefault();829} else {830event.stop();831};832833event.returnValue = false;834event.stopPropagation();835return false;836}837838self.stayFocused = true;839// insert invisible character for fix caret position840pasteHtmlAtCaret('<span>' + invisibleChar + '</span>');841842var sel = saveSelection(editor[0]),843editorScrollTop = editor.scrollTop(),844clipboard = $("<div/>", {contenteditable: true})845.css({position: "fixed", left: "-999px", width: "1px", height: "1px", top: "20px", overflow: "hidden"})846.appendTo($("BODY"))847.focus();848849window.setTimeout(function() {850editor.focus();851restoreSelection(editor[0], sel);852var text = textFromHtml(clipboard.html().replace(/\r\n|\n|\r/g, '<br>'), self);853clipboard.remove();854pasteText(text);855}, 200);856})857858.on("@emojibtn.click", function(emojibtn) {859editor.removeClass("has-placeholder");860if (!app.is(".focused")) {861editor.focus();862}863if (self.standalone) {864editor.html(shortnameTo(emojibtn.data("name"), self.emojiTemplate));865self.trigger("blur");866} else {867saveSelection(editor[0]);868pasteHtmlAtCaret(shortnameTo(emojibtn.data("name"), self.emojiTemplate));869}870871if (self.recentEmojis) {872setRecent(self, emojibtn.data("name"));873}874})875876.on("@!resize @keyup @emojibtn.click", calcButtonPosition)877878.on("@!mousedown", function(editor, event) {879if (!app.is(".focused")) {880editor.focus();881}882event.preventDefault();883return false;884})885886.on("@change", function() {887var html = self.editor.html().replace(/<\/?(?:div|span|p)[^>]*>/ig, '');888// clear input: chrome adds <br> when contenteditable is empty889if (!html.length || /^<br[^>]*>$/i.test(html)) {890self.editor.html(self.content = '');891}892source[sourceValFunc](self.getText());893})894895.on("@focus", function() {896app.addClass("focused");897})898899.on("@blur", function() {900app.removeClass("focused");901902if (options.hidePickerOnBlur) {903self.hidePicker();904}905906var content = self.editor.html();907if (self.content !== content) {908self.content = content;909trigger(self, 'change', [self.editor]);910source.blur().trigger("change");911} else {912source.blur();913}914});915916if (options.shortcuts) {917self.on("@keydown", function(_, e) {918if (!e.ctrlKey) {919if (e.which == 9) {920e.preventDefault();921button.click();922}923else if (e.which == 27) {924e.preventDefault();925if (button.is(".active")) {926self.hidePicker();927}928}929}930});931}932933if (isObject(options.events) && !$.isEmptyObject(options.events)) {934$.each(options.events, function(event, handler) {935self.on(event.replace(/_/g, '.'), handler);936});937}938939if (options.autocomplete) {940var autocomplete = function() {941var textcompleteOptions = {942maxCount: options.textcomplete.maxCount,943placement: options.textcomplete.placement944};945946if (options.shortcuts) {947textcompleteOptions.onKeydown = function (e, commands) {948if (!e.ctrlKey && e.which == 13) {949return commands.KEY_ENTER;950}951};952}953954var map = $.map(emojione.emojioneList, function (_, emoji) {955return !options.autocompleteTones ? /_tone[12345]/.test(emoji) ? null : emoji : emoji;956});957map.sort();958editor.textcomplete([959{960id: css_class,961match: /\B(:[\-+\w]*)$/,962search: function (term, callback) {963callback($.map(map, function (emoji) {964return emoji.indexOf(term) === 0 ? emoji : null;965}));966},967template: function (value) {968return shortnameTo(value, self.emojiTemplate) + " " + value.replace(/:/g, '');969},970replace: function (value) {971return shortnameTo(value, self.emojiTemplate);972},973cache: true,974index: 1975}976], textcompleteOptions);977978if (options.textcomplete.placement) {979// Enable correct positioning for textcomplete980if ($(editor.data('textComplete').option.appendTo).css("position") == "static") {981$(editor.data('textComplete').option.appendTo).css("position", "relative");982}983}984};985if ($.fn.textcomplete) {986autocomplete();987} else {988$.getScript("https://cdn.rawgit.com/yuku-t/jquery-textcomplete/v1.3.4/dist/jquery.textcomplete.js",989autocomplete);990}991}992993if (self.inline) {994app.addClass(selector('inline', true));995self.on("@keydown", function(_, e) {996if (e.which == 13) {997e.preventDefault();998}999});1000}10011002if (/firefox/i.test(navigator.userAgent)) {1003// disabling resize images on Firefox1004document.execCommand("enableObjectResizing", false, false);1005}10061007//}, self.id === 1); // calcElapsedTime()1008};1009var emojioneVersion = window.emojioneVersion || '2.1.4';1010var cdn = {1011defaultBase: "https://cdnjs.cloudflare.com/ajax/libs/emojione/",1012base: null,1013isLoading: false1014};1015function loadEmojione(options) {10161017function detectVersion(emojione) {1018var version = emojione.cacheBustParam;1019if (!isObject(emojione['jsEscapeMap'])) return '1.5.2';1020if (version === "?v=1.2.4") return '2.0.0';1021if (version === "?v=2.0.1") return '2.1.0'; // v2.0.1 || v2.1.01022if (version === "?v=2.1.1") return '2.1.1';1023if (version === "?v=2.1.2") return '2.1.2';1024if (version === "?v=2.1.3") return '2.1.3';1025if (version === "?v=2.1.4") return '2.1.4';1026if (version === "?v=2.2.7") return '2.2.7';1027return '2.2.7';1028}10291030function getSupportMode(version) {1031switch (version) {1032case '1.5.2': return 0;1033case '2.0.0': return 1;1034case '2.1.0':1035case '2.1.1': return 2;1036case '2.1.2': return 3;1037case '2.1.3':1038case '2.1.4':1039case '2.2.7':1040default: return 4;1041}1042}1043options = getOptions(options);10441045if (!cdn.isLoading) {1046if (!emojione || getSupportMode(detectVersion(emojione)) < 2) {1047cdn.isLoading = true;1048$.getScript(cdn.defaultBase + emojioneVersion + "/lib/js/emojione.min.js", function () {1049emojione = window.emojione;1050emojioneVersion = detectVersion(emojione);1051emojioneSupportMode = getSupportMode(emojioneVersion);1052cdn.base = cdn.defaultBase + emojioneVersion + "/assets";1053if (options.sprite) {1054var sprite = cdn.base + "/sprites/emojione.sprites.css";1055if (document.createStyleSheet) {1056document.createStyleSheet(sprite);1057} else {1058$('<link/>', {rel: 'stylesheet', href: sprite}).appendTo('head');1059}1060}1061while (readyCallbacks.length) {1062readyCallbacks.shift().call();1063}1064cdn.isLoading = false;1065});1066} else {1067emojioneVersion = detectVersion(emojione);1068emojioneSupportMode = getSupportMode(emojioneVersion);1069cdn.base = cdn.defaultBase + emojioneVersion + "/assets";1070}1071}10721073emojioneReady(function() {1074if (options.useInternalCDN) {1075emojione.imagePathPNG = cdn.base + "/png/";1076emojione.imagePathSVG = cdn.base + "/svg/";1077emojione.imagePathSVGSprites = cdn.base + "/sprites/emojione.sprites.svg";1078emojione.imageType = options.imageType;1079}10801081uniRegexp = new RegExp("<object[^>]*>.*?<\/object>|<span[^>]*>.*?<\/span>|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|(" + emojione.unicodeRegexp + ")", "gi");1082});1083};1084var EmojioneArea = function(element, options) {1085var self = this;1086loadEmojione(options);1087eventStorage[self.id = ++unique] = {};1088possibleEvents[self.id] = {};1089emojioneReady(function() {1090init(self, element, options);1091});1092};1093function bindEvent(self, event) {1094event = event.replace(/^@/, '');1095var id = self.id;1096if (possibleEvents[id][event]) {1097$.each(possibleEvents[id][event], function(i, ev) {1098// ev[0] = element1099// ev[1] = event1100// ev[2] = target1101$.each($.isArray(ev[0]) ? ev[0] : [ev[0]], function(i, el) {1102$(el).on(ev[1], function() {1103var args = slice.call(arguments),1104target = $.isFunction(ev[2]) ? ev[2].apply(self, [event].concat(args)) : ev[2];1105if (target) {1106trigger(self, event, [target].concat(args));1107}1108});1109});1110});1111possibleEvents[id][event] = null;1112}1113}11141115EmojioneArea.prototype.on = function(events, handler) {1116if (events && $.isFunction(handler)) {1117var self = this;1118$.each(events.toLowerCase().split(' '), function(i, event) {1119bindEvent(self, event);1120(eventStorage[self.id][event] || (eventStorage[self.id][event] = [])).push(handler);1121});1122}1123return this;1124};11251126EmojioneArea.prototype.off = function(events, handler) {1127if (events) {1128var id = this.id;1129$.each(events.toLowerCase().replace(/_/g, '.').split(' '), function(i, event) {1130if (eventStorage[id][event] && !/^@/.test(event)) {1131if (handler) {1132$.each(eventStorage[id][event], function(j, fn) {1133if (fn === handler) {1134eventStorage[id][event] = eventStorage[id][event].splice(j, 1);1135}1136});1137} else {1138eventStorage[id][event] = [];1139}1140}1141});1142}1143return this;1144};11451146EmojioneArea.prototype.trigger = function() {1147var args = slice.call(arguments),1148call_args = [this].concat(args.slice(0,1));1149call_args.push(args.slice(1));1150return trigger.apply(this, call_args);1151};11521153EmojioneArea.prototype.setFocus = function () {1154var self = this;1155emojioneReady(function () {1156self.editor.focus();1157});1158return self;1159};11601161EmojioneArea.prototype.setText = function (str) {1162var self = this;1163emojioneReady(function () {1164self.editor.html(htmlFromText(str, self));1165self.content = self.editor.html();1166trigger(self, 'change', [self.editor]);1167calcButtonPosition.apply(self);1168});1169return self;1170}11711172EmojioneArea.prototype.getText = function() {1173return textFromHtml(this.editor.html(), this);1174}11751176EmojioneArea.prototype.showPicker = function () {1177var self = this;1178if (self._sh_timer) {1179window.clearTimeout(self._sh_timer);1180}1181self.picker.removeClass("hidden");1182self._sh_timer = window.setTimeout(function() {1183self.button.addClass("active");1184}, 50);1185trigger(self, "picker.show", [self.picker]);1186return self;1187}11881189EmojioneArea.prototype.hidePicker = function () {1190var self = this;1191if (self._sh_timer) {1192window.clearTimeout(self._sh_timer);1193}1194self.button.removeClass("active");1195self._sh_timer = window.setTimeout(function() {1196self.picker.addClass("hidden");1197}, 500);1198trigger(self, "picker.hide", [self.picker]);1199return self;1200}12011202$.fn.emojioneArea = function(options) {1203return this.each(function() {1204if (!!this.emojioneArea) return this.emojioneArea;1205$.data(this, 'emojioneArea', this.emojioneArea = new EmojioneArea($(this), options));1206return this.emojioneArea;1207});1208};12091210$.fn.emojioneArea.defaults = getDefaultOptions();12111212}) (document, window, jQuery);121312141215