From 357a12f78e83a2bd29a04a56c137c8a6c53c026c Mon Sep 17 00:00:00 2001 From: Sam Date: Fri, 5 Dec 2014 17:19:17 +1100 Subject: [PATCH] FEATURE: work-in-progress emoji selector toolbar item --- .../discourse/controllers/composer.js.es6 | 4 +- .../discourse/lib/Markdown.Editor.js | 45 ++++++++---- .../javascripts/discourse/models/composer.js | 9 +++ app/assets/javascripts/pagedown_custom.js | 2 + plugins/emoji/assets/javascripts/emoji.js.erb | 73 +++++++++++++++++++ plugins/emoji/assets/stylesheets/emoji.css | 43 +++++++++++ 6 files changed, 158 insertions(+), 18 deletions(-) diff --git a/app/assets/javascripts/discourse/controllers/composer.js.es6 b/app/assets/javascripts/discourse/controllers/composer.js.es6 index 9e2e43e8c..9ff339ace 100644 --- a/app/assets/javascripts/discourse/controllers/composer.js.es6 +++ b/app/assets/javascripts/discourse/controllers/composer.js.es6 @@ -73,9 +73,9 @@ export default DiscourseController.extend({ if (c) { c.updateDraftStatus(); } }, - appendText: function(text) { + appendText: function(text, opts) { var c = this.get('model'); - if (c) { c.appendText(text); } + if (c) { c.appendText(text, undefined , opts); } }, appendBlockAtCursor: function(text) { diff --git a/app/assets/javascripts/discourse/lib/Markdown.Editor.js b/app/assets/javascripts/discourse/lib/Markdown.Editor.js index 589d213cf..c72465724 100644 --- a/app/assets/javascripts/discourse/lib/Markdown.Editor.js +++ b/app/assets/javascripts/discourse/lib/Markdown.Editor.js @@ -1439,6 +1439,19 @@ })); buttons.heading = makeButton("wmd-heading-button", getString("heading"), bindCommand("doHeading")); buttons.hr = makeButton("wmd-hr-button", getString("hr"), bindCommand("doHorizontalRule")); + + // If we have any buttons to append, do it! + if (typeof PagedownCustom != "undefined") { + var appendButtons = PagedownCustom.appendButtons + if (appendButtons && (appendButtons.length > 0)) { + for (var i=0; i< appendButtons.length; i++) { + var b = appendButtons[i]; + makeButton(b.id, b.description, b.execute) + } + } + } + + //makeSpacer(3); //buttons.undo = makeButton("wmd-undo-button", getString("undo"), null); //buttons.undo.execute = function (manager) { if (manager) manager.undo(); }; @@ -1450,23 +1463,23 @@ //buttons.redo = makeButton("wmd-redo-button", redoTitle, null); //buttons.redo.execute = function (manager) { if (manager) manager.redo(); }; - if (helpOptions) { - var helpButton = document.createElement("li"); - var helpButtonImage = document.createElement("span"); - helpButton.appendChild(helpButtonImage); - helpButton.className = "wmd-button wmd-help-button"; - helpButton.id = "wmd-help-button" + postfix; - helpButton.isHelp = true; - helpButton.style.right = "0px"; - helpButton.title = getString("help"); - helpButton.onclick = helpOptions.handler; + // if (helpOptions) { + // var helpButton = document.createElement("li"); + // var helpButtonImage = document.createElement("span"); + // helpButton.appendChild(helpButtonImage); + // helpButton.className = "wmd-button wmd-help-button"; + // helpButton.id = "wmd-help-button" + postfix; + // helpButton.isHelp = true; + // helpButton.style.right = "0px"; + // helpButton.title = getString("help"); + // helpButton.onclick = helpOptions.handler; + // + // setupButton(helpButton, true); + // buttonRow.appendChild(helpButton); + // buttons.help = helpButton; + // } - setupButton(helpButton, true); - buttonRow.appendChild(helpButton); - buttons.help = helpButton; - } - - setUndoRedoButtonStates(); + // setUndoRedoButtonStates(); } function setUndoRedoButtonStates() { diff --git a/app/assets/javascripts/discourse/models/composer.js b/app/assets/javascripts/discourse/models/composer.js index ad6d1c3a2..312ab7dd0 100644 --- a/app/assets/javascripts/discourse/models/composer.js +++ b/app/assets/javascripts/discourse/models/composer.js @@ -302,6 +302,15 @@ Discourse.Composer = Discourse.Model.extend({ } } + if(opts && opts.space){ + if(before.length > 0 && !before[before.length-1].match(/\s/)){ + before = before + " "; + } + if(after.length > 0 && !after[0].match(/\s/)){ + after = " " + after; + } + } + this.set('reply', before + text + after); }, diff --git a/app/assets/javascripts/pagedown_custom.js b/app/assets/javascripts/pagedown_custom.js index 9c862739e..e435ebf16 100644 --- a/app/assets/javascripts/pagedown_custom.js +++ b/app/assets/javascripts/pagedown_custom.js @@ -10,6 +10,8 @@ window.PagedownCustom = { } ], + appendButtons: [], + customActions: { "doBlockquote": function(chunk, postProcessing, oldDoBlockquote) { diff --git a/plugins/emoji/assets/javascripts/emoji.js.erb b/plugins/emoji/assets/javascripts/emoji.js.erb index 147f91ca3..1d881fe94 100644 --- a/plugins/emoji/assets/javascripts/emoji.js.erb +++ b/plugins/emoji/assets/javascripts/emoji.js.erb @@ -49,6 +49,28 @@ ":-$" : 'blush' }; + var groups = [ + { + name: "emoticons", + icons: ["smile","smiley","grinning","blush","relaxed","wink","heart_eyes","kissing_heart","kissing_closed_eyes","kissing","kissing_smiling_eyes","stuck_out_tongue_winking_eye","stuck_out_tongue_closed_eyes","stuck_out_tongue","flushed","grin","pensive","relieved","unamused","disappointed","persevere","cry","joy","sob","sleepy","disappointed_relieved","cold_sweat","sweat_smile","sweat","weary","tired_face","fearful","scream","angry","rage","triumph","confounded","laughing","yum","mask","sunglasses","sleeping","dizzy_face","astonished","worried","frowning","anguished","smiling_imp","imp","open_mouth","grimacing","neutral_face","confused","hushed","no_mouth","innocent","smirk","expressionless","man_with_gua_pi_mao","man_with_turban","cop","construction_worker","guardsman","baby","boy","girl","man","woman","older_man","older_woman","person_with_blond_hair","angel","princess","smiley_cat","smile_cat","heart_eyes_cat","kissing_cat","smirk_cat","scream_cat","crying_cat_face","joy_cat","pouting_cat","japanese_ogre","japanese_goblin","see_no_evil","hear_no_evil","speak_no_evil","skull","alien","poop","fire","sparkles","star2","dizzy","boom","anger","sweat_drops","droplet","zzz","dash","ear","eyes","nose","tongue","lips","thumbsup","thumbsdown","ok_hand","punch","fist","v","wave","raised_hand","open_hands","point_up_2","point_down","point_right","point_left","raised_hands","pray","point_up","clap","muscle","walking","runner","dancer","couple","family","two_men_holding_hands","two_women_holding_hands","couplekiss","couple_with_heart","dancers","ok_woman","no_good","information_desk_person","raising_hand","massage","haircut","nail_care","bride_with_veil","person_with_pouting_face","person_frowning","bow","tophat","crown","womans_hat","athletic_shoe","mans_shoe","sandal","high_heel","boot","shirt","necktie","womans_clothes","dress","running_shirt_with_sash","jeans","kimono","bikini","briefcase","handbag","pouch","purse","eyeglasses","ribbon","closed_umbrella","lipstick","yellow_heart","blue_heart","purple_heart","green_heart","heart","broken_heart","heartpulse","heartbeat","two_hearts","sparkling_heart","revolving_hearts","cupid","love_letter","kiss","ring","gem","bust_in_silhouette","busts_in_silhouette","speech_balloon","footprints","thought_balloon"] + }, + { + name: "nature", + icons: ["dog","wolf","cat","mouse","hamster","rabbit","frog","tiger","koala","bear","pig","pig_nose","cow","boar","monkey_face","monkey","horse","sheep","elephant","panda_face","penguin","bird","baby_chick","hatched_chick","hatching_chick","chicken","snake","turtle","bug","bee","ant","beetle","snail","octopus","shell","tropical_fish","fish","dolphin","whale","whale2","cow2","ram","rat","water_buffalo","tiger2","rabbit2","dragon","racehorse","goat","rooster","dog2","pig2","mouse2","ox","dragon_face","blowfish","crocodile","camel","dromedary_camel","leopard","cat2","poodle","feet","bouquet","cherry_blossom","tulip","four_leaf_clover","rose","sunflower","hibiscus","maple_leaf","leaves","fallen_leaf","herb","ear_of_rice","mushroom","cactus","palm_tree","evergreen_tree","deciduous_tree","chestnut","seedling","blossom","globe_with_meridians","sun_with_face","full_moon_with_face","new_moon_with_face","new_moon","waxing_crescent_moon","first_quarter_moon","waxing_gibbous_moon","full_moon","waning_gibbous_moon","last_quarter_moon","waning_crescent_moon","last_quarter_moon_with_face","first_quarter_moon_with_face","crescent_moon","earth_africa","earth_americas","earth_asia","volcano","milky_way","stars","star","sunny","partly_sunny","cloud","zap","umbrella","snowflake","snowman","cyclone","foggy","rainbow","ocean"] + }, + { + name: "objects", + icons: ["dog","wolf","cat","mouse","hamster","rabbit","frog","tiger","koala","bear","pig","pig_nose","cow","boar","monkey_face","monkey","horse","sheep","elephant","panda_face","penguin","bird","baby_chick","hatched_chick","hatching_chick","chicken","snake","turtle","bug","bee","ant","beetle","snail","octopus","shell","tropical_fish","fish","dolphin","whale","whale2","cow2","ram","rat","water_buffalo","tiger2","rabbit2","dragon","racehorse","goat","rooster","dog2","pig2","mouse2","ox","dragon_face","blowfish","crocodile","camel","dromedary_camel","leopard","cat2","poodle","feet","bouquet","cherry_blossom","tulip","four_leaf_clover","rose","sunflower","hibiscus","maple_leaf","leaves","fallen_leaf","herb","ear_of_rice","mushroom","cactus","palm_tree","evergreen_tree","deciduous_tree","chestnut","seedling","blossom","globe_with_meridians","sun_with_face","full_moon_with_face","new_moon_with_face","new_moon","waxing_crescent_moon","first_quarter_moon","waxing_gibbous_moon","full_moon","waning_gibbous_moon","last_quarter_moon","waning_crescent_moon","last_quarter_moon_with_face","first_quarter_moon_with_face","crescent_moon","earth_africa","earth_americas","earth_asia","volcano","milky_way","stars","star","sunny","partly_sunny","cloud","zap","umbrella","snowflake","snowman","cyclone","foggy","rainbow","ocean"] + }, + { + name: "places", + icons: ["house","house_with_garden","school","office","post_office","hospital","bank","convenience_store","love_hotel","hotel","wedding","church","department_store","european_post_office","city_sunset","city_dusk","japanese_castle","european_castle","tent","factory","tokyo_tower","japan","mount_fuji","sunrise_over_mountains","sunrise","night_with_stars","statue_of_liberty","bridge_at_night","carousel_horse","ferris_wheel","fountain","roller_coaster","ship","sailboat","speedboat","rowboat","anchor","rocket","airplane","seat","helicopter","steam_locomotive","tram","station","mountain_railway","train2","bullettrain_side","bullettrain_front","light_rail","metro","monorail","train","railway_car","trolleybus","bus","oncoming_bus","blue_car","oncoming_automobile","red_car","taxi","oncoming_taxi","articulated_lorry","truck","rotating_light","police_car","oncoming_police_car","fire_engine","ambulance","minibus","bike","aerial_tramway","suspension_railway","mountain_cableway","tractor","barber","busstop","ticket","vertical_traffic_light","traffic_light","warning","construction","beginner","fuelpump","izakaya_lantern","slot_machine","hotsprings","moyai","circus_tent","performing_arts","round_pushpin","triangular_flag_on_post","cn","us","in","jp","br","ru","de","ng","gb","fr","mx","kr","id","ph","eg","vn","tr","it","es","ca","pl","ar","co","ir","za","my","pk","au","th","ma","tw","nl","ua","sa","ke","ve","pe","ro","cl","uz","bd","kz","be","se","cz","sd","hu","pt","ch","at","tz"] + }, + { + name: "symbols", + icons: ["hash","one","two","three","four","five","six","seven","eight","nine","zero","keycap_ten","1234","symbols","arrow_up","arrow_down","arrow_left","arrow_right","capital_abcd","abcd","abc","arrow_upper_right","arrow_upper_left","arrow_lower_right","arrow_lower_left","left_right_arrow","arrow_up_down","arrows_counterclockwise","arrow_backward","arrow_forward","arrow_up_small","arrow_down_small","leftwards_arrow_with_hook","arrow_right_hook","information_source","rewind","fast_forward","arrow_double_up","arrow_double_down","arrow_heading_down","arrow_heading_up","ok","twisted_rightwards_arrows","repeat","repeat_one","new","up","cool","free","ng","signal_strength","cinema","koko","u6307","u7a7a","u6e80","u5408","u7981","ideograph_advantage","u5272","u55b6","u6709","u7121","restroom","mens","womens","baby_symbol","wc","potable_water","put_litter_in_its_place","parking","wheelchair","no_smoking","u6708","u7533","sa","m","passport_control","baggage_claim","left_luggage","customs","accept","secret","congratulations","cl","sos","id","no_entry_sign","underage","no_mobile_phones","do_not_litter","non-potable_water","no_bicycles","no_pedestrians","children_crossing","no_entry","eight_spoked_asterisk","sparkle","negative_squared_cross_mark","white_check_mark","eight_pointed_black_star","heart_decoration","vs","vibration_mode","mobile_phone_off","a","b","ab","o2","diamond_shape_with_a_dot_inside","loop","recycle","aries","taurus","gemini","cancer","leo","virgo","libra","scorpius","sagittarius","capricorn","aquarius","pisces","ophiuchus","six_pointed_star","atm","chart","heavy_dollar_sign","currency_exchange","copyright","registered","tm","part_alternation_mark","wavy_dash","top","end","back","on","soon","x","o","exclamation","question","grey_exclamation","grey_question","bangbang","interrobang","arrows_clockwise","clock12","clock1230","clock1","clock130","clock2","clock230","clock3","clock330","clock4","clock430","clock5","clock530","clock6","clock7","clock8","clock9","clock10","clock11","clock630","clock730","clock830","clock930","clock1030","clock1130","heavy_multiplication_x","heavy_plus_sign","heavy_minus_sign","heavy_division_sign","spades","hearts","clubs","diamonds","white_flower","100","heavy_check_mark","ballot_box_with_check","radio_button","link","curly_loop","trident","black_square_button","white_square_button","black_medium_square","white_medium_square","black_medium_small_square","white_medium_small_square","black_small_square","white_small_square","small_red_triangle","white_large_square","black_large_square","black_circle","white_circle","red_circle","large_blue_circle","small_red_triangle_down","large_orange_diamond","large_blue_diamond","small_orange_diamond","small_blue_diamond"] + }]; + function checkPrev(prev) { if (prev && prev.length) { var lastToken = prev[prev.length-1]; @@ -115,6 +137,55 @@ } }); + var renderPage = Handlebars.compile( + "" + + "{{#each this}}"+ + "{{#each this}}" + + "" + + "{{/each}}" + + "{{/each}}"+ + "
"); + + var closeSelector = function(){ + $('.emoji-modal, .emoji-modal-wrapper').remove(); + }; + + var showSelector = function(){ + + $('body').append('
'); + + $('.emoji-modal-wrapper').click(function(){ + closeSelector(); + }); + + var rows = []; + var row = []; + var icons = groups[0].icons; + + for(var i=0; i<50; i++){ + if(row.length === 10){ + rows.push(row); + row = []; + } + row.push({src: urlFor(icons[i]), title: icons[i]}); + } + rows.push(row); + + $('body').append('
' + renderPage(rows) + '
'); + + var composerController = Discourse.__container__.lookup('controller:composer'); + $('.emoji-page a').click(function(){ + composerController.appendText(":" + $(this).attr('title') + ":", {space: true}); + closeSelector(); + }); + }; + + window.PagedownCustom.appendButtons.push({ + id: 'wmd-emoji-button', + description: I18n.t("composer.emoji"), + execute: showSelector + }); + // TODO: Make this a proper ES6 import var ComposerView = (Discourse && Discourse.ComposerView) || (typeof require !== "undefined" && require('discourse/views/composer').default); if (ComposerView) { @@ -136,6 +207,7 @@ ""); var toSearch = emoji.concat(Object.keys(_extendedEmoji)); + $('#wmd-input').autocomplete({ template: template, key: ":", @@ -183,4 +255,5 @@ } Discourse.Markdown.whiteListTag('img', 'class', 'emoji'); + }).call(this); diff --git a/plugins/emoji/assets/stylesheets/emoji.css b/plugins/emoji/assets/stylesheets/emoji.css index a7e070e28..31b70bf84 100644 --- a/plugins/emoji/assets/stylesheets/emoji.css +++ b/plugins/emoji/assets/stylesheets/emoji.css @@ -3,3 +3,46 @@ body img.emoji { height: 20px; vertical-align: middle; } + +#wmd-emoji-button:before { + content: "\f118"; +} + +.emoji-modal { + z-index: 10000; + position: fixed; + margin-left: -195px; + margin-top: -100px; + left: 50%; + top: 50%; + background-color: white; +} + +.emoji-page td { + border: 1px solid #eee; +} + +.emoji-page a { + padding: 8px; + display: block; +} + +.emoji-page a:hover { + background-color: rgb(210, 236, 252); +} + +.emoji-page { + border-collapse: collapse; + margin: 3px; +} + +.emoji-modal-wrapper { + z-index: 9999; + position: fixed; + left: 0; + top: 0; + width: 100%; + height: 100%; + opacity: 0.8; + background-color: black; +}