新版订单消耗系统

emojionearea.js 36KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  1. /*!
  2. * EmojioneArea v2.0.1
  3. * https://github.com/mervick/emojionearea
  4. * Copyright Andrey Izman and other contributors
  5. * Released under the MIT license
  6. * Date: 2016-03-18T21:32Z
  7. */
  8. (function(document, window, $) {
  9. 'use strict';
  10. var unique = 0;
  11. var eventStorage = {};
  12. var emojione = window.emojione;
  13. var readyCallbacks = [];
  14. function emojioneReady (fn) {
  15. if (emojione) {
  16. fn();
  17. } else {
  18. readyCallbacks.push(fn);
  19. }
  20. };
  21. var blankImg = 'data:image/gif;base64,R0lGODlhAQABAJH/AP///wAAAMDAwAAAACH5BAEAAAIALAAAAAABAAEAAAICVAEAOw==';
  22. var setInterval = window.setInterval;
  23. var clearInterval = window.clearInterval;
  24. function trigger(self, event, args) {
  25. var result = true, j = 1;
  26. if (event) {
  27. event = event.toLowerCase();
  28. do {
  29. var _event = j==1 ? '@' + event : event;
  30. if (eventStorage[self.id][_event] && eventStorage[self.id][_event].length) {
  31. $.each(eventStorage[self.id][_event], function (i, fn) {
  32. return result = fn.apply(self, args|| []) !== false;
  33. });
  34. }
  35. } while (result && !!j--);
  36. }
  37. return result;
  38. }
  39. var slice = [].slice;
  40. function attach(self, element, events, target) {
  41. target = target || function (event, callerEvent) { return $(callerEvent.currentTarget) };
  42. $.each($.isArray(element) ? element : [element], function(i, el) {
  43. $.each(events, function(event, handler) {
  44. $(el).on(event = $.isArray(events) ? handler : event, function() {
  45. var _target = $.isFunction(target) ? target.apply(self, [event].concat(slice.call(arguments))) : target;
  46. if (_target) {
  47. trigger(self, handler, [_target].concat(slice.call(arguments)));
  48. }
  49. });
  50. });
  51. });
  52. }
  53. var emojioneList = [];
  54. var emojioneVersion = '1.5.2';
  55. var emojioneSupportMode = 0;
  56. function getTemplate(template, unicode, shortname) {
  57. return template
  58. .replace('{name}', shortname || '')
  59. .replace('{img}', emojione.imagePathPNG + (emojioneSupportMode !== 1 ? unicode.toUpperCase() : unicode) + '.png'/* + emojione.cacheBustParam*/)
  60. .replace('{uni}', emojioneSupportMode < 1 ? unicode.toUpperCase() : unicode)
  61. .replace('{alt}', emojione.convert(unicode));
  62. }
  63. function shortnameTo(str, template) {
  64. return str.replace(/:?[\w_]+:?/g, function(shortname) {
  65. shortname = ":" + shortname.replace(/:$/,'').replace(/^:/,'') + ":";
  66. if (shortname in emojioneList) {
  67. return getTemplate(template, emojioneList[shortname][emojioneList[shortname].length-1], shortname);
  68. }
  69. return shortname;
  70. });
  71. };
  72. function pasteHtmlAtCaret(html) {
  73. var sel, range;
  74. if (window.getSelection) {
  75. sel = window.getSelection();
  76. if (sel.getRangeAt && sel.rangeCount) {
  77. range = sel.getRangeAt(0);
  78. range.deleteContents();
  79. var el = document.createElement("div");
  80. el.innerHTML = html;
  81. var frag = document.createDocumentFragment(), node, lastNode;
  82. while ( (node = el.firstChild) ) {
  83. lastNode = frag.appendChild(node);
  84. }
  85. range.insertNode(frag);
  86. if (lastNode) {
  87. range = range.cloneRange();
  88. range.setStartAfter(lastNode);
  89. range.collapse(true);
  90. sel.removeAllRanges();
  91. sel.addRange(range);
  92. }
  93. }
  94. } else if (document.selection && document.selection.type != "Control") {
  95. document.selection.createRange().pasteHTML(html);
  96. }
  97. }
  98. var default_options = {
  99. template : "<editor/><filters/><tabs/>",
  100. dir : "ltr",
  101. spellcheck : false,
  102. autocomplete : "off",
  103. autocorrect : "off",
  104. autocapitalize : "off",
  105. placeholder : null,
  106. container : null,
  107. hideSource : true,
  108. autoHideFilters : false,
  109. shortnames : false,
  110. useSprite : true,
  111. filters: {
  112. people: {
  113. icon: "yum",
  114. emoji: "grinning,grin,joy,smiley,smile,sweat_smile,laughing,innocent,smiling_imp,imp,wink,blush," +
  115. "relaxed,yum,relieved,heart_eyes,sunglasses,smirk,neutral_face,expressionless,unamused,sweat," +
  116. "pensive,confused,confounded,kissing,kissing_heart,kissing_smiling_eyes,kissing_closed_eyes," +
  117. "stuck_out_tongue,stuck_out_tongue_winking_eye,stuck_out_tongue_closed_eyes,disappointed,worried," +
  118. "angry,rage,cry,persevere,triumph,disappointed_relieved,frowning,anguished,fearful,weary," +
  119. "sleepy,tired_face,grimacing,sob,open_mouth,hushed,cold_sweat,scream,astonished,flushed," +
  120. "sleeping,dizzy_face,no_mouth,mask,slight_frown,slight_smile,smile_cat,joy_cat,smiley_cat," +
  121. "heart_eyes_cat,smirk_cat,kissing_cat,pouting_cat,crying_cat_face,scream_cat,footprints," +
  122. "bust_in_silhouette,busts_in_silhouette,levitate,spy,baby,boy,girl,man,woman,family," +
  123. "family_mwg,family_mwgb,family_mwbb,family_mwgg,family_wwb,family_wwg,family_wwgb,family_wwbb," +
  124. "family_wwgg,family_mmb,family_mmg,family_mmgb,family_mmbb,family_mmgg,couple,two_men_holding_hands," +
  125. "two_women_holding_hands,dancers,bride_with_veil,person_with_blond_hair,man_with_gua_pi_mao," +
  126. "man_with_turban,older_man,older_woman,cop,construction_worker,princess,guardsman,angel," +
  127. "santa,ghost,japanese_ogre,japanese_goblin,poop,skull,alien,space_invader,bow," +
  128. "information_desk_person,no_good,ok_woman,raising_hand,person_with_pouting_face,person_frowning," +
  129. "massage,haircut,couple_with_heart,couple_ww,couple_mm,couplekiss,kiss_ww,kiss_mm,raised_hands," +
  130. "clap,ear,eye,eyes,nose,lips,kiss,tongue,nail_care,wave,thumbsup,thumbsdown," +
  131. "point_up,point_up_2,point_down,point_left,point_right,ok_hand,v,punch,fist,raised_hand," +
  132. "muscle,open_hands,writing_hand,hand_splayed,middle_finger,vulcan,pray"
  133. },
  134. nature: {
  135. icon: "whale",
  136. emoji: "seedling,evergreen_tree,deciduous_tree,palm_tree,cactus,tulip,cherry_blossom,rose,hibiscus," +
  137. "sunflower,blossom,bouquet,ear_of_rice,herb,four_leaf_clover,maple_leaf,fallen_leaf,leaves," +
  138. "mushroom,chestnut,rat,mouse2,mouse,hamster,ox,water_buffalo,cow2,cow,tiger2,leopard," +
  139. "tiger,chipmunk,rabbit2,rabbit,cat2,cat,racehorse,horse,ram,sheep,goat,rooster,chicken," +
  140. "baby_chick,hatching_chick,hatched_chick,bird,penguin,elephant,dromedary_camel,camel,boar,pig2," +
  141. "pig,pig_nose,dog2,poodle,dog,wolf,bear,koala,panda_face,monkey_face,see_no_evil,hear_no_evil," +
  142. "speak_no_evil,monkey,dragon,dragon_face,crocodile,snake,turtle,frog,whale2,whale,dolphin," +
  143. "octopus,fish,tropical_fish,blowfish,shell,snail,bug,ant,bee,beetle,spider,spider_web,feet," +
  144. "zap,fire,crescent_moon,sunny,partly_sunny,cloud,cloud_rain,cloud_snow,cloud_lightning,cloud_tornado," +
  145. "droplet,sweat_drops,umbrella,fog,dash,snowflake,star2,star,stars,sunrise_over_mountains,sunrise," +
  146. "rainbow,ocean,volcano,milky_way,mount_fuji,japan,globe_with_meridians,earth_africa,earth_americas," +
  147. "earth_asia,new_moon,waxing_crescent_moon,first_quarter_moon,waxing_gibbous_moon,full_moon," +
  148. "waning_gibbous_moon,last_quarter_moon,waning_crescent_moon,new_moon_with_face,full_moon_with_face," +
  149. "first_quarter_moon_with_face,last_quarter_moon_with_face,sun_with_face,wind_blowing_face"
  150. },
  151. food_drink: {
  152. icon: "cherries",
  153. emoji: "tomato,eggplant,corn,sweet_potato,hot_pepper,grapes,melon,watermelon,tangerine,lemon," +
  154. "banana,pineapple,apple,green_apple,pear,peach,cherries,strawberry,hamburger,pizza,meat_on_bone," +
  155. "poultry_leg,rice_cracker,rice_ball,rice,curry,ramen,spaghetti,bread,fries,dango,oden,sushi," +
  156. "fried_shrimp,fish_cake,icecream,shaved_ice,ice_cream,doughnut,cookie,chocolate_bar,candy," +
  157. "lollipop,custard,honey_pot,cake,bento,stew,egg,fork_and_knife,tea,coffee,sake,wine_glass," +
  158. "cocktail,tropical_drink,beer,beers,baby_bottle"
  159. },
  160. celebration: {
  161. icon: "tada",
  162. emoji: "ribbon,gift,birthday,jack_o_lantern,christmas_tree,tanabata_tree,bamboo,rice_scene," +
  163. "fireworks,sparkler,tada,confetti_ball,balloon,dizzy,sparkles,boom,mortar_board,crown," +
  164. "reminder_ribbon,military_medal,dolls,flags,wind_chime,crossed_flags,izakaya_lantern,ring," +
  165. "heart,broken_heart,love_letter,two_hearts,revolving_hearts,heartbeat,heartpulse,sparkling_heart," +
  166. "cupid,gift_heart,heart_decoration,purple_heart,yellow_heart,green_heart,blue_heart"
  167. },
  168. activity: {
  169. icon: "trophy",
  170. emoji: "runner,walking,dancer,lifter,golfer,rowboat,swimmer,surfer,bath,snowboarder,ski," +
  171. "snowman,bicyclist,mountain_bicyclist,motorcycle,race_car,horse_racing,tent,fishing_pole_and_fish," +
  172. "soccer,basketball,football,baseball,tennis,rugby_football,golf,trophy,medal,running_shirt_with_sash," +
  173. "checkered_flag,musical_keyboard,guitar,violin,saxophone,trumpet,musical_note,notes,musical_score," +
  174. "headphones,microphone,performing_arts,ticket,tophat,circus_tent,clapper,film_frames,tickets," +
  175. "art,dart,8ball,bowling,slot_machine,game_die,video_game,flower_playing_cards,black_joker," +
  176. "mahjong,carousel_horse,ferris_wheel,roller_coaster"
  177. },
  178. travel: {
  179. icon: "rocket",
  180. emoji: "railway_car,mountain_railway,steam_locomotive,train,monorail,bullettrain_side," +
  181. "bullettrain_front,train2,metro,light_rail,station,tram,railway_track,bus,oncoming_bus," +
  182. "trolleybus,minibus,ambulance,fire_engine,police_car,oncoming_police_car,rotating_light,taxi," +
  183. "oncoming_taxi,red_car,oncoming_automobile,blue_car,truck,articulated_lorry,tractor,bike," +
  184. "motorway,busstop,fuelpump,construction,vertical_traffic_light,traffic_light,rocket,helicopter," +
  185. "airplane,airplane_small,airplane_departure,airplane_arriving,seat,anchor,ship,cruise_ship," +
  186. "motorboat,speedboat,sailboat,aerial_tramway,mountain_cableway,suspension_railway," +
  187. "passport_control,customs,baggage_claim,left_luggage,yen,euro,pound,dollar,bellhop,bed," +
  188. "couch,fork_knife_plate,shopping_bags,statue_of_liberty,moyai,foggy,tokyo_tower,fountain," +
  189. "european_castle,japanese_castle,classical_building,stadium,mountain_snow,camping,beach," +
  190. "desert,island,park,cityscape,city_sunset,city_dusk,night_with_stars,bridge_at_night,house," +
  191. "homes,house_with_garden,house_abandoned,contruction_site,office,department_store,factory," +
  192. "post_office,european_post_office,hospital,bank,hotel,love_hotel,wedding,church," +
  193. "convenience_store,school,map"
  194. },
  195. objects_symbols: {
  196. icon: "paperclips",
  197. emoji: "watch,iphone,calling,computer,desktop,keyboard,trackball,printer,alarm_clock,clock," +
  198. "hourglass_flowing_sand,hourglass,camera,camera_with_flash,video_camera,movie_camera,projector," +
  199. "tv,microphone2,level_slider,control_knobs,radio,pager,joystick,telephone_receiver,telephone," +
  200. "fax,minidisc,floppy_disk,cd,dvd,vhs,battery,electric_plug,bulb,flashlight,candle,satellite," +
  201. "satellite_orbital,credit_card,money_with_wings,moneybag,gem,closed_umbrella,pouch,purse," +
  202. "handbag,briefcase,school_satchel,lipstick,eyeglasses,dark_sunglasses,womans_hat,sandal," +
  203. "high_heel,boot,mans_shoe,athletic_shoe,bikini,dress,kimono,womans_clothes,shirt,necktie," +
  204. "jeans,door,shower,bathtub,toilet,barber,syringe,pill,microscope,telescope,crystal_ball," +
  205. "wrench,knife,dagger,nut_and_bolt,hammer,tools,oil,bomb,smoking,gun,bookmark,newspaper," +
  206. "newspaper2,thermometer,label,key,key2,envelope,envelope_with_arrow,incoming_envelope,email," +
  207. "inbox_tray,outbox_tray,package,postal_horn,postbox,mailbox_closed,mailbox,mailbox_with_no_mail," +
  208. "mailbox_with_mail,page_facing_up,page_with_curl,bookmark_tabs,wastebasket,notepad_spiral," +
  209. "chart_with_upwards_trend,chart_with_downwards_trend,bar_chart,date,calendar,calendar_spiral," +
  210. "ballot_box,low_brightness,high_brightness,compression,frame_photo,scroll,clipboard,book," +
  211. "notebook,notebook_with_decorative_cover,ledger,closed_book,green_book,blue_book,orange_book," +
  212. "books,card_index,dividers,card_box,link,paperclip,paperclips,pushpin,scissors," +
  213. "triangular_ruler,round_pushpin,straight_ruler,triangular_flag_on_post,flag_white,flag_black," +
  214. "hole,file_folder,open_file_folder,file_cabinet,black_nib,pencil2,pen_ballpoint,pen_fountain," +
  215. "paintbrush,crayon,pencil,lock_with_ink_pen,closed_lock_with_key,lock,unlock,mega,loudspeaker," +
  216. "speaker,sound,loud_sound,mute,zzz,bell,no_bell,cross_heavy,om_symbol,dove,thought_balloon," +
  217. "speech_balloon,anger_right,children_crossing,shield,mag,mag_right,speaking_head," +
  218. "sleeping_accommodation,no_entry_sign,no_entry,name_badge,no_pedestrians,do_not_litter," +
  219. "no_bicycles,non_potable_water,no_mobile_phones,underage,sparkle,eight_spoked_asterisk," +
  220. "negative_squared_cross_mark,white_check_mark,eight_pointed_black_star,vibration_mode," +
  221. "mobile_phone_off,vs,a,b,ab,cl,o2,sos,id,parking,wc,cool,free,new,ng,ok,up,atm," +
  222. "aries,taurus,gemini,cancer,leo,virgo,libra,scorpius,sagittarius,capricorn,aquarius," +
  223. "pisces,restroom,mens,womens,baby_symbol,wheelchair,potable_water,no_smoking," +
  224. "put_litter_in_its_place,arrow_forward,arrow_backward,arrow_up_small,arrow_down_small," +
  225. "fast_forward,rewind,arrow_double_up,arrow_double_down,arrow_right,arrow_left,arrow_up," +
  226. "arrow_down,arrow_upper_right,arrow_lower_right,arrow_lower_left,arrow_upper_left,arrow_up_down," +
  227. "left_right_arrow,arrows_counterclockwise,arrow_right_hook,leftwards_arrow_with_hook," +
  228. "arrow_heading_up,arrow_heading_down,twisted_rightwards_arrows,repeat,repeat_one,hash," +
  229. "zero,one,two,three,four,five,six,seven,eight,nine,keycap_ten,1234,abc,abcd,capital_abcd," +
  230. "information_source,signal_strength,cinema,symbols,heavy_plus_sign,heavy_minus_sign,wavy_dash," +
  231. "heavy_division_sign,heavy_multiplication_x,heavy_check_mark,arrows_clockwise,tm,copyright," +
  232. "registered,currency_exchange,heavy_dollar_sign,curly_loop,loop,part_alternation_mark," +
  233. "exclamation,question,grey_exclamation,grey_question,bangbang,interrobang,x,o,100,end," +
  234. "back,on,top,soon,cyclone,m,ophiuchus,six_pointed_star,beginner,trident,warning," +
  235. "hotsprings,rosette,recycle,anger,diamond_shape_with_a_dot_inside,spades,clubs,hearts," +
  236. "diamonds,ballot_box_with_check,white_circle,black_circle,radio_button,red_circle," +
  237. "large_blue_circle,small_red_triangle,small_red_triangle_down,small_orange_diamond," +
  238. "small_blue_diamond,large_orange_diamond,large_blue_diamond,black_small_square," +
  239. "white_small_square,black_large_square,white_large_square,black_medium_square,white_medium_square," +
  240. "black_medium_small_square,white_medium_small_square,black_square_button,white_square_button," +
  241. "clock1,clock2,clock3,clock4,clock5,clock6,clock7,clock8,clock9,clock10,clock11," +
  242. "clock12,clock130,clock230,clock330,clock430,clock530,clock630,clock730,clock830,clock930," +
  243. "clock1030,clock1130,clock1230"
  244. },
  245. flags: {
  246. icon: "triangular_flag_on_post",
  247. emoji: "au,at,be,br,ca,flag_cl,cn,co,dk,fi,fr,de,hk,in,flag_id,ie,il,it,jp,kr,mo," +
  248. "my,mx,nl,nz,no,ph,pl,pt,pr,ru,flag_sa,sg,za,es,se,ch,tr,gb,us,ae,vn,af,al,dz," +
  249. "ad,ao,ai,ag,ar,am,aw,ac,az,bs,bh,bd,bb,by,bz,bj,bm,bt,bo,ba,bw,bn,bg,bf,bi," +
  250. "kh,cm,cv,ky,cf,km,flag_cd,cg,td,cr,ci,hr,cu,cy,cz,dj,dm,do,tl,ec,eg,sv,gq,er," +
  251. "ee,et,fk,fo,fj,pf,ga,gm,ge,gh,gi,gr,gl,gd,gu,gt,gn,gw,gy,ht,hn,hu,is,ir,iq,jm," +
  252. "je,jo,kz,ke,ki,xk,kw,kg,la,lv,lb,ls,lr,ly,li,lt,lu,mk,mg,mw,mv,ml,mt,mh,mr,mu," +
  253. "fm,md,mc,mn,me,ms,ma,mz,mm,na,nr,np,nc,ni,ne,flag_ng,nu,kp,om,pk,pw,ps,pa,pg," +
  254. "py,pe,qa,ro,rw,sh,kn,lc,vc,ws,sm,st,sn,rs,sc,sl,sk,si,sb,so,lk,sd,sr,sz,sy,tw,tj," +
  255. "tz,th,tg,to,tt,tn,flag_tm,flag_tv,vi,ug,ua,uy,uz,vu,va,ve,wf,eh,ye,zm,zw"
  256. }
  257. }
  258. };
  259. function getOptions(options) {
  260. options = $.extend({}, default_options, options);
  261. if (emojioneSupportMode > 0) {
  262. options.filters.people.emoji = options.filters.people.emoji
  263. .replace(",writing_hand,", ",");
  264. options.filters.travel.emoji = options.filters.travel.emoji
  265. .replace(",contruction_site,", ",construction_site,");
  266. options.filters.objects_symbols.emoji = options.filters.objects_symbols.emoji
  267. .replace(",keycap_ten,", ",ten,")
  268. .replace(",cross_heavy,", ",cross,");
  269. }
  270. return options;
  271. }
  272. var saveSelection, restoreSelection;
  273. if (window.getSelection && document.createRange) {
  274. saveSelection = function(el) {
  275. var range = window.getSelection().getRangeAt(0);
  276. var preSelectionRange = range.cloneRange();
  277. preSelectionRange.selectNodeContents(el);
  278. preSelectionRange.setEnd(range.startContainer, range.startOffset);
  279. return preSelectionRange.toString().length;
  280. };
  281. restoreSelection = function(el, sel) {
  282. var charIndex = 0, range = document.createRange();
  283. range.setStart(el, 0);
  284. range.collapse(true);
  285. var nodeStack = [el], node, foundStart = false, stop = false;
  286. while (!stop && (node = nodeStack.pop())) {
  287. if (node.nodeType == 3) {
  288. var nextCharIndex = charIndex + node.length;
  289. if (!foundStart && sel >= charIndex && sel <= nextCharIndex) {
  290. range.setStart(node, sel - charIndex);
  291. range.setEnd(node, sel - charIndex);
  292. stop = true;
  293. }
  294. charIndex = nextCharIndex;
  295. } else {
  296. var i = node.childNodes.length;
  297. while (i--) {
  298. nodeStack.push(node.childNodes[i]);
  299. }
  300. }
  301. }
  302. sel = window.getSelection();
  303. sel.removeAllRanges();
  304. sel.addRange(range);
  305. }
  306. } else if (document.selection && document.body.createTextRange) {
  307. saveSelection = function(el) {
  308. var selectedTextRange = document.selection.createRange(),
  309. preSelectionTextRange = document.body.createTextRange();
  310. preSelectionTextRange.moveToElementText(el);
  311. preSelectionTextRange.setEndPoint("EndToStart", selectedTextRange);
  312. var start = preSelectionTextRange.text.length;
  313. return [start, start + selectedTextRange.text.length];
  314. };
  315. restoreSelection = function(el, sel) {
  316. var textRange = document.body.createTextRange();
  317. textRange.moveToElementText(el);
  318. textRange.collapse(true);
  319. textRange.moveEnd("character", sel[1]);
  320. textRange.moveStart("character", sel[0]);
  321. textRange.select();
  322. };
  323. }
  324. var uniRegexp = 0;
  325. var cdn_base = "https://cdnjs.cloudflare.com/ajax/libs/emojione/";
  326. function detectSupportMode() {
  327. return (typeof emojione['jsEscapeMap']).toLowerCase() === 'object' ? emojione.cacheBustParam === "?v=1.2.4" ? 2 : 1 : 0;
  328. }
  329. if (!emojione) {
  330. $.getScript(cdn_base + emojioneVersion + "/lib/js/emojione.min.js", function () {
  331. emojione = window.emojione;
  332. emojioneSupportMode = detectSupportMode();
  333. cdn_base += emojioneVersion + "/assets";
  334. var sprite = cdn_base +"/sprites/emojione.sprites.css";
  335. if (document.createStyleSheet) {
  336. document.createStyleSheet(sprite);
  337. } else {
  338. $('<link/>', {rel: 'stylesheet', href: sprite}).appendTo('head');
  339. }
  340. while (readyCallbacks.length) {
  341. readyCallbacks.shift().call();
  342. }
  343. });
  344. } else {
  345. emojioneSupportMode = detectSupportMode();
  346. cdn_base += (emojioneSupportMode > 0 ? emojioneSupportMode > 1 ? '2.0.0' : '2.1.1' : '1.5.2') + "/assets";
  347. }
  348. emojioneReady(function() {
  349. emojione.imagePathPNG = cdn_base + "/png/";
  350. emojione.imagePathSVG = cdn_base + "/svg/";
  351. emojione.imagePathSVGSprites = cdn_base + "/sprites/emojione.sprites.svg";
  352. $.each(emojione.emojioneList, function (shortname, keys) {
  353. // fix shortnames for emojione v1.5.0
  354. emojioneList[shortname.replace('-', '_')] = keys;
  355. });
  356. uniRegexp = new RegExp("<object[^>]*>.*?<\/object>|<span[^>]*>.*?<\/span>|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|("+
  357. emojione.unicodeRegexp+")", "gi");
  358. });
  359. function unicodeTo(str, template) {
  360. return str.replace(uniRegexp, function(unicodeChar) {
  361. var map = emojione[(emojioneSupportMode < 1 ? 'jsecapeMap' : 'jsEscapeMap')];
  362. if (typeof unicodeChar !== 'undefined' && unicodeChar in map) {
  363. return getTemplate(template, map[unicodeChar]);
  364. }
  365. return unicodeChar;
  366. });
  367. }
  368. function htmlFromText(str, self) {
  369. str = str
  370. .replace(/</g, '&lt;').replace(/>/g, '&gt;')
  371. .replace(/(?:\r\n|\r|\n)/g, '\n')
  372. .replace(/(\n+)/g, '<div>$1</div>')
  373. .replace(/\n/g, '<br/>')
  374. .replace(/<br\/><\/div>/g, '</div>');
  375. if (self.shortnames) {
  376. str = emojione.shortnameToUnicode(str);
  377. }
  378. return unicodeTo(str,
  379. '<img alt="{alt}" class="emojione' + (self.sprite ? '-{uni}" src="' + blankImg + '">' : '" src="{img}">'))
  380. .replace(/\t/g, '&nbsp;&nbsp;&nbsp;&nbsp;')
  381. .replace(/ /g, '&nbsp;&nbsp;');
  382. }
  383. function textFromHtml(str, self) {
  384. str = str
  385. .replace(/<img[^>]*alt="([^"]+)"[^>]*>/ig, '$1')
  386. .replace(/\n|\r/g, '')
  387. .replace(/<br[^>]*>/ig, '\n')
  388. .replace(/(?:<(?:div|p|ol|ul|li|pre|code|object)[^>]*>)+/ig, '<div>')
  389. .replace(/(?:<\/(?:div|p|ol|ul|li|pre|code|object)>)+/ig, '</div>')
  390. .replace(/\n<div><\/div>/ig, '\n')
  391. .replace(/<div><\/div>\n/ig, '\n')
  392. .replace(/(?:<div>)+<\/div>/ig, '\n')
  393. .replace(/([^\n])<\/div><div>/ig, '$1\n')
  394. .replace(/(?:<\/div>)+/ig, '</div>')
  395. .replace(/([^\n])<\/div>([^\n])/ig, '$1\n$2')
  396. .replace(/<\/div>/ig, '')
  397. .replace(/([^\n])<div>/ig, '$1\n')
  398. .replace(/\n<div>/ig, '\n')
  399. .replace(/<div>\n/ig, '\n\n')
  400. .replace(/<(?:[^>]+)?>/g, '')
  401. .replace(/&nbsp;/g, ' ')
  402. .replace(/\x20\x20/g, '&nbsp; ')
  403. .replace(/\x20\x20/g, ' &nbsp;');
  404. return self && self.shortnames ? emojione.toShort(str) : str;
  405. }
  406. function init(self, source, options) {
  407. options = getOptions(options);
  408. var sourceValFunc = source.is("TEXTAREA") || source.is("INPUT") ? "val" : "text",
  409. app = options.template,
  410. stayFocused = false,
  411. container = !!options.container ? $(options.container) : false,
  412. editor, filters, tabs, scrollArea, filtersBtns, filtersArrowLeft, filtersArrowRight,
  413. filtersWidth, scrollLeft = 0, scrollAreaWidth = 0, filterWidth,
  414. resizeHandler = function() {
  415. var width = filters.width();
  416. if (width !== filtersWidth) {
  417. filtersWidth = width;
  418. trigger(self, 'resize', [editor]);
  419. }
  420. }, resizeHandlerID;
  421. self.sprite = options.useSprite;
  422. self.shortnames = options.shortnames;
  423. for (var el = ["editor", "filters", "tabs"], i=0; i<3; i++) {
  424. app = app.replace(new RegExp('<' + el[i] + '/?>' ,'i'), '<div class="emojionearea-' + el[i] + '"></div>');
  425. }
  426. app = $('<div/>', {"class" : source.attr("class"), role: "application"}).addClass("emojionearea").html(app);
  427. editor = self.editor = app.find(".emojionearea-editor")
  428. .attr({
  429. contenteditable: true,
  430. placeholder: options["placeholder"] || source.data("placeholder") || source.attr("placeholder") || "",
  431. tabindex: 0
  432. });
  433. for (var attr = ["dir", "spellcheck", "autocomplete", "autocorrect", "autocapitalize"], j=0; j<5; j++) {
  434. editor.attr(attr[j], options[attr[j]]);
  435. }
  436. filters = app.find(".emojionearea-filters");
  437. if (options.autoHideFilters) {
  438. filters.hide();
  439. }
  440. tabs = app.find(".emojionearea-tabs");
  441. $.each(options.filters, function(filter, params) {
  442. $("<i/>", {"class": "emojionearea-filter", "data-filter": filter})
  443. .wrapInner(shortnameTo(params.icon, self.sprite ? '<i class="emojione-{uni}"/>' : '<img class="emojione" src="{img}"/>'))
  444. .appendTo(filters);
  445. $("<div/>", {"class": "emojionearea-tab emojionearea-tab-" + filter}).hide()
  446. .data("items", shortnameTo(params.emoji, '<i class="emojibtn" role="button"><' +
  447. (self.sprite ? 'i class="emojione-{uni}"' : 'img class="emojione" src="{img}"') +
  448. ' data-name="{name}"/></i>'))
  449. .appendTo(tabs);
  450. });
  451. filters.wrapInner('<div class="emojionearea-filters-scroll"/>');
  452. filtersArrowLeft = $('<i class="emojionearea-filter-arrow-left"/>', {role: "button"}).appendTo(filters);
  453. filtersArrowRight = $('<i class="emojionearea-filter-arrow-right"/>', {role: "button"}).appendTo(filters);
  454. filtersBtns = filters.find(".emojionearea-filter");
  455. scrollArea = filters.children(".emojionearea-filters-scroll");
  456. if (!!container) {
  457. container.wrapInner(app);
  458. } else {
  459. app.insertAfter(source);
  460. }
  461. if (options.hideSource) {
  462. source.hide();
  463. }
  464. self.setText(source[sourceValFunc]());
  465. attach(self, [filters, tabs], {mousedown: "area.mousedown"}, editor);
  466. attach(self, editor, ["paste"], editor);
  467. attach(self, editor, ["focus", "blur"], function() { return !!stayFocused ? false : editor; });
  468. attach(self, [editor, filters, tabs], ["mousedown", "mouseup", "click", "keyup", "keydown"], editor);
  469. attach(self, filters.find(".emojionearea-filter"), {click: "filter.click"});
  470. attach(self, filtersArrowLeft, {click: "arrowLeft.click"});
  471. attach(self, filtersArrowRight, {click: "arrowRight.click"});
  472. function scrollFilters() {
  473. if (!scrollAreaWidth) {
  474. $.each(filtersBtns, function (i, e) {
  475. scrollAreaWidth += $(e).outerWidth(true);
  476. });
  477. filterWidth = filtersBtns.eq(0).outerWidth(true);
  478. }
  479. if (scrollAreaWidth > filtersWidth) {
  480. filtersArrowRight.addClass("active");
  481. filtersArrowLeft.addClass("active");
  482. if (scrollLeft + scrollAreaWidth <= filtersWidth) {
  483. scrollLeft = filtersWidth - scrollAreaWidth;
  484. filtersArrowRight.removeClass("active");
  485. } else if (scrollLeft >= 0) {
  486. scrollLeft = 0;
  487. filtersArrowLeft.removeClass("active");
  488. }
  489. scrollArea.css("left", scrollLeft);
  490. } else {
  491. if (scrollLeft !== 0) {
  492. scrollLeft = 0;
  493. scrollArea.css("left", scrollLeft);
  494. }
  495. filtersArrowRight.removeClass("active");
  496. filtersArrowLeft.removeClass("active");
  497. }
  498. }
  499. self.on("@filter.click", function(element) {
  500. if (element.is(".active")) {
  501. element.removeClass("active");
  502. tabs.children().hide();
  503. } else {
  504. filtersBtns.filter(".active").removeClass("active");
  505. element.addClass("active");
  506. var i, timer, tab = tabs.children().hide()
  507. .filter(".emojionearea-tab-" + element.data("filter")).show(),
  508. items = tab.data("items"),
  509. event = {click: "emojibtn.click"};
  510. if (items) {
  511. tab.data("items", false);
  512. items = items.split(',');
  513. if (self.sprite) {
  514. tab.html(items.join(''));
  515. attach(self, tab.find(".emojibtn"), event);
  516. } else {
  517. timer = setInterval(function () {
  518. for (i = 0; i < 20 && items.length; i++) {
  519. tab.append(items.shift());
  520. attach(self, tab.find(".emojibtn").not(".handled").addClass("handled"), event);
  521. }
  522. if (!items.length) clearInterval(timer);
  523. }, 5);
  524. }
  525. }
  526. }
  527. })
  528. .on("@resize", function() {
  529. scrollFilters();
  530. })
  531. .on("@arrowLeft.click", function() {
  532. scrollLeft += filterWidth;
  533. scrollFilters();
  534. })
  535. .on("@arrowRight.click", function() {
  536. scrollLeft -= filterWidth;
  537. scrollFilters();
  538. })
  539. .on("@paste", function(element) {
  540. stayFocused = true;
  541. pasteHtmlAtCaret('<span> </span>');
  542. var sel = saveSelection(element[0]),
  543. editorScrollTop = element.scrollTop(),
  544. clipboard = $("<div/>", {contenteditable: true})
  545. .css({position: "fixed", left: "-999px", width: "1px", height: "1px", top: "20px", overflow: "hidden"})
  546. .appendTo($("BODY"))
  547. .focus();
  548. window.setTimeout(function() {
  549. var caretID = "caret-" + (new Date()).getTime();
  550. element.focus();
  551. restoreSelection(element[0], sel);
  552. pasteHtmlAtCaret(htmlFromText(textFromHtml(clipboard.html().replace(/\r\n|\n|\r/g, '<br>'), self), self));
  553. clipboard.remove();
  554. pasteHtmlAtCaret('<i id="' + caretID +'"></i>');
  555. element.scrollTop(editorScrollTop);
  556. var caret = $("#" + caretID),
  557. top = caret.offset().top - element.offset().top,
  558. height = element.height();
  559. if (editorScrollTop + top >= height || editorScrollTop > top) {
  560. element.scrollTop(editorScrollTop + top - 2 * height/3);
  561. }
  562. caret.remove();
  563. stayFocused = false;
  564. }, 200);
  565. })
  566. .on("@emojibtn.click", function(element) {
  567. saveSelection(editor[0]);
  568. pasteHtmlAtCaret(shortnameTo(element.children().data("name"),
  569. '<img alt="{alt}" class="emojione' + (self.sprite ? '-{uni}" src="'+blankImg+'">' : '" src="{img}">')));
  570. })
  571. .on("@area.mousedown", function(element, event) {
  572. if (!options.autoHideFilters && !app.is(".focused")) {
  573. element.focus();
  574. }
  575. event.preventDefault();
  576. return false;
  577. })
  578. .on("@change", function(element) {
  579. var html = element.html().replace(/<\/?(?:div|span|p)[^>]*>/ig, '');
  580. // clear input, fix: chrome add <br> on contenteditable is empty
  581. if (!html.length || /^<br[^>]*>$/i.test(html)) {
  582. self.setText('', false);
  583. }
  584. source[sourceValFunc](self.getText());
  585. })
  586. .on("@focus", function() {
  587. resizeHandler();
  588. resizeHandlerID = setInterval(resizeHandler, 500);
  589. app.addClass("focused");
  590. if (options.autoHideFilters) {
  591. filters.slideDown(400);
  592. }
  593. })
  594. .on("@blur", function(element) {
  595. scrollLeft = 0;
  596. scrollFilters();
  597. app.removeClass("focused");
  598. clearInterval(resizeHandlerID);
  599. if (options.autoHideFilters) {
  600. filters.slideUp(400);
  601. }
  602. filtersBtns.filter(".active").removeClass("active");
  603. tabs.children().hide();
  604. var content = element.html();
  605. if (self.content !== content) {
  606. self.content = content;
  607. trigger(self, 'change', [editor]);
  608. source.blur().trigger("change");
  609. } else {
  610. source.blur();
  611. }
  612. });
  613. };
  614. var EmojioneArea = function(element, options) {
  615. var self = this;
  616. eventStorage[self.id = ++unique] = {};
  617. emojioneReady(function() {
  618. init(self, element, options);
  619. });
  620. };
  621. EmojioneArea.prototype.on = function(events, handler) {
  622. if (events && $.isFunction(handler)) {
  623. var id = this.id;
  624. $.each(events.toLowerCase().split(' '), function(i, event) {
  625. (eventStorage[id][event] || (eventStorage[id][event] = [])).push(handler);
  626. });
  627. }
  628. return this;
  629. };
  630. EmojioneArea.prototype.off = function(events, handler) {
  631. if (events) {
  632. var id = this.id;
  633. $.each(events.toLowerCase().split(' '), function(i, event) {
  634. if (eventStorage[id][event] && !/^@/.test(event)) {
  635. if (handler) {
  636. $.each(eventStorage[id][event], function(j, fn) {
  637. if (fn === handler) {
  638. eventStorage[id][event] = eventStorage[id][event].splice(j, 1);
  639. }
  640. });
  641. } else {
  642. eventStorage[id][event] = [];
  643. }
  644. }
  645. });
  646. }
  647. return this;
  648. };
  649. EmojioneArea.prototype.setText = function (str) {
  650. var self = this, args = arguments;
  651. emojioneReady(function () {
  652. self.editor.html(htmlFromText(str, self));
  653. self.content = self.editor.html();
  654. if (args.length === 1) {
  655. trigger(self, 'change', [self.editor]);
  656. }
  657. });
  658. }
  659. EmojioneArea.prototype.getText = function() {
  660. return textFromHtml(this.editor.html(), this);
  661. }
  662. $.fn.emojioneArea = function(options) {
  663. return this.each(function() {
  664. if (!!this.emojioneArea) return this.emojioneArea;
  665. return this.emojioneArea = new EmojioneArea($(this), options);
  666. });
  667. };
  668. }) (document, window, jQuery);