chat 0.0.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +47 -22
  4. data/Rakefile +27 -1
  5. data/app/assets/config/chat_manifest.js +2 -0
  6. data/app/assets/javascripts/chat.js +16 -0
  7. data/app/assets/javascripts/chat/cable.js +13 -0
  8. data/app/assets/javascripts/chat/channels/message.coffee +75 -0
  9. data/app/assets/javascripts/chat/channels/notification.coffee +44 -0
  10. data/app/assets/javascripts/chat/channels/status.coffee +13 -0
  11. data/app/assets/javascripts/chat/emojionearea.min.js +1 -0
  12. data/app/assets/javascripts/chat/messages.coffee +44 -0
  13. data/app/assets/stylesheets/chat.css +15 -0
  14. data/app/assets/stylesheets/chat/chat.sass +25 -0
  15. data/app/assets/stylesheets/chat/checkbox.sass +80 -0
  16. data/app/assets/stylesheets/chat/emojionearea.min.css +1 -0
  17. data/app/assets/stylesheets/chat/header.sass +50 -0
  18. data/app/assets/stylesheets/chat/launch.sass +26 -0
  19. data/app/assets/stylesheets/chat/list.sass +45 -0
  20. data/app/assets/stylesheets/chat/message_form.sass +50 -0
  21. data/app/assets/stylesheets/chat/new.sass +53 -0
  22. data/app/assets/stylesheets/chat/transcript.sass +76 -0
  23. data/app/channels/chat/messages_channel.rb +11 -0
  24. data/app/channels/chat/notification_channel.rb +10 -0
  25. data/app/channels/chat/status_channel.rb +12 -0
  26. data/app/controllers/chat/application_controller.rb +5 -0
  27. data/app/controllers/chat/conversations_controller.rb +30 -0
  28. data/app/controllers/chat/messages_controller.rb +28 -0
  29. data/app/helpers/chat/application_helper.rb +62 -0
  30. data/app/jobs/chat/application_job.rb +5 -0
  31. data/app/jobs/chat/message_relay_job.rb +40 -0
  32. data/app/jobs/chat/notification_relay_job.rb +11 -0
  33. data/app/jobs/chat/status_relay_job.rb +9 -0
  34. data/app/mailers/chat/application_mailer.rb +6 -0
  35. data/app/models/chat/application_record.rb +3 -0
  36. data/app/models/chat/conversation.rb +9 -0
  37. data/app/models/chat/dot_command.rb +26 -0
  38. data/app/models/chat/dot_command/gif.rb +17 -0
  39. data/app/models/chat/dot_command/leave.rb +16 -0
  40. data/app/models/chat/dot_command/shrug.rb +27 -0
  41. data/app/models/chat/dot_command/validator.rb +23 -0
  42. data/app/models/chat/message.rb +29 -0
  43. data/app/models/chat/session.rb +10 -0
  44. data/app/views/chat/_chat.html.haml +14 -0
  45. data/app/views/chat/conversations/_index.html.haml +11 -0
  46. data/app/views/chat/conversations/_new.html.haml +10 -0
  47. data/app/views/chat/conversations/_show.html.haml +9 -0
  48. data/app/views/chat/conversations/create.js.erb +21 -0
  49. data/app/views/chat/conversations/show.js.erb +12 -0
  50. data/app/views/chat/messages/_message.haml +13 -0
  51. data/app/views/layouts/chat/application.html.erb +14 -0
  52. data/config/routes.rb +5 -0
  53. data/lib/chat.rb +29 -3
  54. data/lib/chat/engine.rb +5 -0
  55. data/lib/chat/user.rb +51 -0
  56. data/lib/chat/version.rb +1 -1
  57. data/lib/generators/chat/install/install_generator.rb +68 -0
  58. data/lib/generators/chat/install/templates/add_chat_to_users.rb +9 -0
  59. data/lib/generators/chat/install/templates/chat.rb +11 -0
  60. data/lib/generators/chat/install/templates/create_chat.rb +29 -0
  61. data/lib/tasks/chat_tasks.rake +4 -0
  62. metadata +296 -16
  63. data/.gitignore +0 -9
  64. data/Gemfile +0 -4
  65. data/LICENSE.txt +0 -21
  66. data/bin/console +0 -14
  67. data/bin/setup +0 -8
  68. data/chat.gemspec +0 -22
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3adb97d2c92c6e3b15eb9ccac6d510c46f5663a6
4
- data.tar.gz: 9d0f5bba612617f79dab6c65595ee2ca4aed81d8
3
+ metadata.gz: 6bcdf0fb7ca57a7f9a8e9c8be615fc159f088842
4
+ data.tar.gz: ecffe773589c5a3eec5c0d3eb60bf4cc8b0bf381
5
5
  SHA512:
6
- metadata.gz: 06f1b20cb5aa5b12d394ff54b9fdd79845e7116964a0ea85ab99a5570f616d7a115d470db6437ba02497499678f3a8f955563c00778e68e3da79279944082c89
7
- data.tar.gz: c3ef4022f16441ea5059b96a89c4252f8d4c9853818d6d03cf7435e56fe6bcc876a9043d5f2bab6c21eb852d79730e9fb4c16fad286aeb14940cfb1b42f27271
6
+ metadata.gz: a9a9b349a7d5a088d991da1120af2ad9c706dbbe1489a487f10c9b2921bbd3766acd30be7928bbd9ee482df1900a6182492fe78f86374799f5ce9e41f8106fea
7
+ data.tar.gz: e891fd403f4c3756fe340f9d2259c9e835bf059dd967516a01e8907a6a16768e9da758478401ce1076d9063580d5458ff1f584ebc1a43cfcb4768ab66fd16e55
@@ -0,0 +1,20 @@
1
+ Copyright 2016 npezza93
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,40 +1,65 @@
1
1
  # Chat
2
-
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/chat`. To experiment with that code, run `bin/console` for an interactive prompt.
4
-
5
- TODO: Delete this and the text above, and describe your gem
6
-
7
- ## Installation
8
-
9
- Add this line to your application's Gemfile:
2
+ Simple Rails chat plugin that allows users to talk to one or more people at a
3
+ time that leverages ActionCable.
4
+
5
+ ## Getting Started
6
+
7
+ #### Prerequisites
8
+ 1. This gem relies on ActionCable therefore Rails 5.0.0 is a minimum.
9
+ 1. For help setting up ActionCable when coming from an older version of Rails, view
10
+ [this](https://github.com/npezza93/chat/wiki/Setting-up-ActionCable).
11
+ 1. An authentication system must be setup before installing `chat`, like
12
+ Devise, Clearance, or your own custom solution. The generator will only run
13
+ unless a users table exists.
14
+ 1. Chat assumes that a `current_user` view helper
15
+ method exists.
16
+ 1. Your connection should be identified by `current_user`. You can learn
17
+ more about how to set this up by reading
18
+ [here](http://edgeguides.rubyonrails.org/action_cable_overview.html#server-side-components-connections).
19
+
20
+ #### Installation
21
+ Add Chat to your application's Gemfile:
10
22
 
11
23
  ```ruby
12
24
  gem 'chat'
13
25
  ```
14
26
 
15
27
  And then execute:
28
+ ```bash
29
+ ❯ bundle
30
+ ```
16
31
 
17
- $ bundle
18
-
19
- Or install it yourself as:
32
+ Run the installer to setup migrations and helpers and then migrate:
33
+ ```bash
34
+ rails generate chat:install
35
+ ❯ rails db:migrate
36
+ ```
20
37
 
21
- $ gem install chat
38
+ Require chat in your app/assets/javascripts/application.js file:
22
39
 
23
- ## Usage
40
+ ```
41
+ //= require chat
42
+ ```
24
43
 
25
- TODO: Write usage instructions here
44
+ Require chat in your app/assets/stylesheets/application.css file
26
45
 
27
- ## Development
46
+ ```
47
+ *= require chat
48
+ ```
28
49
 
29
- After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
50
+ Finally the following line to your application.html.erb file or any view file
51
+ you'd like Chat available from:
52
+ ```html
53
+ <!-- background is the background color of the launch fab -->
54
+ <!-- color is the icon color on the launch fab. Can be light or dark -->
55
+ <%= render_chat(background, color) %>
56
+ ```
30
57
 
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
58
+ ### Dot Commands
32
59
 
33
60
  ## Contributing
34
-
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/npezza93/chat.
36
-
61
+ Contribution directions go here.
37
62
 
38
63
  ## License
39
-
40
- The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
64
+ The gem is available as open source under the terms of the
65
+ [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile CHANGED
@@ -1,2 +1,28 @@
1
+ begin
2
+ require "bundler/setup"
3
+ rescue LoadError
4
+ puts "You must `gem install bundler` and `bundle install` to run rake tasks"
5
+ end
6
+
7
+ require "rdoc/task"
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = "rdoc"
11
+ rdoc.title = "Chat"
12
+ rdoc.options << "--line-numbers"
13
+ rdoc.rdoc_files.include("README.md")
14
+ rdoc.rdoc_files.include("lib/**/*.rb")
15
+ end
16
+
1
17
  require "bundler/gem_tasks"
2
- task :default => :spec
18
+
19
+ require "rake/testtask"
20
+
21
+ Rake::TestTask.new(:test) do |t|
22
+ t.libs << "lib"
23
+ t.libs << "test"
24
+ t.pattern = "test/**/*_test.rb"
25
+ t.verbose = false
26
+ end
27
+
28
+ task default: :test
@@ -0,0 +1,2 @@
1
+ //= link_directory ../javascripts/chat .js
2
+ //= link_directory ../stylesheets/chat .css
@@ -0,0 +1,16 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file. JavaScript code in this file should be added after the last require_* statement.
9
+ //
10
+ // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require jquery
14
+ //= require jquery_ujs
15
+ //= require jquery-fileupload/basic
16
+ //= require_tree './chat'
@@ -0,0 +1,13 @@
1
+ // Action Cable provides the framework to deal with WebSockets in Rails.
2
+ // You can generate new channels where WebSocket features live using the rails generate channel command.
3
+ //
4
+ //= require action_cable
5
+ //= require_self
6
+ //= require_tree ./channels
7
+
8
+ (function() {
9
+ this.App || (this.App = {});
10
+
11
+ App.cable = ActionCable.createConsumer();
12
+
13
+ }).call(this);
@@ -0,0 +1,75 @@
1
+ App.chat_message =
2
+ App.cable.subscriptions.create 'Chat::MessagesChannel',
3
+ collection: -> $("[data-channel='messages']")
4
+
5
+ connected: ->
6
+ @followCurrentChat()
7
+
8
+ received: (data) ->
9
+ @collection().append @generateMessage(data)
10
+ height = $('.chat__transcript').prop('scrollHeight')
11
+ $('.chat__transcript').animate { scrollTop: height }, 'slow'
12
+
13
+ followCurrentChat: ->
14
+ if chatId = @current_chat()
15
+ @perform 'follow', chat_id: chatId
16
+ else
17
+ @perform 'unfollow'
18
+
19
+ current_user: ->
20
+ if @collection().length > 0
21
+ @collection().data().currentUser
22
+
23
+ current_chat: ->
24
+ if @collection().length > 0
25
+ @collection().data().currentChat
26
+
27
+ div: ->
28
+ document.createElement('div')
29
+
30
+ flex: ->
31
+ element = @div()
32
+ element.classList += 'chat__flex'
33
+ element.outerHTML
34
+
35
+ text_message_container: ->
36
+ element = @div()
37
+ element.classList += 'chat__message'
38
+ element
39
+
40
+ image_message_container: ->
41
+ element = @div()
42
+ element.classList += 'chat__image-message'
43
+ element
44
+
45
+ image_message: (data) ->
46
+ element = @image_message_container()
47
+ if data.user == @current_user()
48
+ element.classList += ' current'
49
+ element.innerHTML = data.message
50
+ element.outerHTML
51
+
52
+ message: (data) ->
53
+ element = @div()
54
+ element.classList += 'text'
55
+ if data.user == @current_user()
56
+ element.classList += ' right'
57
+ else
58
+ element.classList += ' left'
59
+ element.innerHTML = data.message
60
+ element.outerHTML
61
+
62
+ text_message: (data) ->
63
+ msg = [data.avatar, @message(data), @flex()]
64
+ msg = msg.reverse() if data.user == @current_user()
65
+
66
+ message = @text_message_container()
67
+ message.innerHTML = msg.join('')
68
+ message.outerHTML
69
+
70
+
71
+ generateMessage: (data) ->
72
+ if data.image
73
+ @image_message(data)
74
+ else
75
+ @text_message(data)
@@ -0,0 +1,44 @@
1
+ App.chat_notification =
2
+ App.cable.subscriptions.create "Chat::NotificationChannel",
3
+ connected: ->
4
+ @perform 'follow', user_id: @current_user()
5
+
6
+ disconnected: ->
7
+
8
+ received: (data) ->
9
+ if @current_chat() != data.chat_id || !@viewing_transcript()
10
+ @add_notification(data.chat_id)
11
+ $("#chat__show-#{data.chat_id}").addClass("chat__has_new_message")
12
+
13
+ current_user: ->
14
+ if $(".chat__launch").length > 0
15
+ $(".chat__launch").data().currentUser
16
+
17
+ current_chat: ->
18
+ App.chat_message.current_chat()
19
+
20
+ viewing_transcript: ->
21
+ $(".current_chat").css("display") == "flex"
22
+
23
+ add_notification: (id) ->
24
+ classes = "#chat .chat__settings, .chat__launch"
25
+ $(classes).addClass('chat__badge')
26
+ $(classes).attr('data-badge', @new_notification_count(id))
27
+
28
+ new_notification_count: (id) ->
29
+ @notification_count() + @notification_increment(id)
30
+
31
+ notification_count: ->
32
+ parseInt($("#chat .chat__settings").data('badge') || 0)
33
+
34
+ notification_increment: (id) ->
35
+ if $("#chat__show-#{id}").hasClass('chat__has_new_message')
36
+ 0
37
+ else
38
+ 1
39
+
40
+ decrement: ->
41
+ classes = "#chat .chat__settings, .chat__launch"
42
+ if @notification_count() == 1
43
+ $(classes).removeClass('chat__badge')
44
+ $(classes).attr('data-badge', @notification_count() - 1)
@@ -0,0 +1,13 @@
1
+ App.chat_status =
2
+ App.cable.subscriptions.create "Chat::StatusChannel",
3
+ connected: ->
4
+ @perform 'online', user_id: App.chat_notification.current_user()
5
+
6
+ disconnected: ->
7
+ @perform 'unsubscribed', user_id: App.chat_notification.current_user()
8
+
9
+ received: (data) ->
10
+ label = $("label[for='conversation_user_ids_#{data.user_id}'] .chat__status")
11
+ label.removeClass("offline")
12
+ label.removeClass("online")
13
+ label.addClass(data.status)
@@ -0,0 +1 @@
1
+ !function(a,b,c){"use strict";function i(a){g?a():h.push(a)}function o(a,b,d){var f=!0,g=1;if(b){b=b.toLowerCase();do{var h=1==g?"@"+b:b;e[a.id][h]&&e[a.id][h].length&&c.each(e[a.id][h],function(b,c){return f=c.apply(a,d||[])!==!1})}while(f&&g--)}return f}function p(a,b,d,e){e=e||function(a,b){return c(b.currentTarget)},c.each(d,function(g,h){g=c.isArray(d)?h:g,(f[a.id][h]||(f[a.id][h]=[])).push([b,g,e])})}function q(a,b,c){var e,d=g.imageType;return e="svg"==d?g.imagePathSVG:g.imagePathPNG,a.replace("{name}",c||"").replace("{img}",e+(m<2?b.toUpperCase():b)+"."+d).replace("{uni}",b).replace("{alt}",g.convert(b))}function r(a,b,c){return a.replace(/:?\+?[\w_\-]+:?/g,function(a){a=":"+a.replace(/:$/,"").replace(/^:/,"")+":";var d=g.emojioneList[a];return d?(m>3&&(d=d.unicode),q(b,d[d.length-1],a)):c?"":a})}function s(c){var d,e;if(b.getSelection){if(d=b.getSelection(),d.getRangeAt&&d.rangeCount){e=d.getRangeAt(0),e.deleteContents();var f=a.createElement("div");f.innerHTML=c;for(var h,i,g=a.createDocumentFragment();h=f.firstChild;)i=g.appendChild(h);e.insertNode(g),i&&(e=e.cloneRange(),e.setStartAfter(i),e.collapse(!0),d.removeAllRanges(),d.addRange(e))}}else a.selection&&"Control"!=a.selection.type&&a.selection.createRange().pasteHTML(c)}function u(a){return"object"==typeof a}function v(a){var b=t();if(a&&a.filters){var d=b.filters;c.each(a.filters,function(a,b){return!u(b)||c.isEmptyObject(b)?void delete d[a]:void c.each(b,function(b,c){d[a][b]=c})}),a.filters=d}return c.extend({},b,a)}function z(a,b){return a.replace(y,function(a){var c=g[0===m?"jsecapeMap":"jsEscapeMap"];return"undefined"!=typeof a&&a in c?q(b,c[a]):a})}function A(a,b){return a=a.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#x27;").replace(/`/g,"&#x60;").replace(/(?:\r\n|\r|\n)/g,"\n").replace(/(\n+)/g,"<div>$1</div>").replace(/\n/g,"<br/>").replace(/<br\/><\/div>/g,"</div>"),b.shortnames&&(a=g.shortnameToUnicode(a)),z(a,b.emojiTemplate).replace(/\t/g,"&nbsp;&nbsp;&nbsp;&nbsp;").replace(/ /g,"&nbsp;&nbsp;")}function B(a,b){switch(a=a.replace(/<img[^>]*alt="([^"]+)"[^>]*>/gi,"$1").replace(/\n|\r/g,"").replace(/<br[^>]*>/gi,"\n").replace(/(?:<(?:div|p|ol|ul|li|pre|code|object)[^>]*>)+/gi,"<div>").replace(/(?:<\/(?:div|p|ol|ul|li|pre|code|object)>)+/gi,"</div>").replace(/\n<div><\/div>/gi,"\n").replace(/<div><\/div>\n/gi,"\n").replace(/(?:<div>)+<\/div>/gi,"\n").replace(/([^\n])<\/div><div>/gi,"$1\n").replace(/(?:<\/div>)+/gi,"</div>").replace(/([^\n])<\/div>([^\n])/gi,"$1\n$2").replace(/<\/div>/gi,"").replace(/([^\n])<div>/gi,"$1\n").replace(/\n<div>/gi,"\n").replace(/<div>\n/gi,"\n\n").replace(/<(?:[^>]+)?>/g,"").replace(new RegExp(n,"g"),"").replace(/&nbsp;/g," ").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&#x27;/g,"'").replace(/&#x60;/g,"`").replace(/&amp;/g,"&"),b.saveEmojisAs){case"image":a=z(a,b.emojiTemplate);break;case"shortname":a=g.toShort(a)}return a}function C(){var a=this,b=a.editor[0].offsetWidth-a.editor[0].clientWidth,c=parseInt(a.button.css("marginRight"));c!==b&&(a.button.css({marginRight:b}),a.floatingPicker&&a.picker.css({right:parseInt(a.picker.css("right"))-c+b}))}function D(){var a=this;if(!a.sprite&&a.lasyEmoji[0]){var b=a.picker.offset().top,d=b+a.picker.height()+20;a.lasyEmoji.each(function(){var a=c(this),e=a.offset().top;e>b&&e<d&&a.attr("src",a.data("src")).removeClass("lazy-emoji")}),a.lasyEmoji=a.lasyEmoji.filter(".lazy-emoji")}}function E(a,b){return(b?"":".")+l+(a?"-"+a:"")}function F(a){var b=c("<div/>",u(a)?a:{class:E(a,!0)});return c.each(k.call(arguments).slice(1),function(a,d){c.isFunction(d)&&(d=d.call(b)),d&&c(d).appendTo(b)}),b}function G(){return localStorage.getItem("recent_emojis")||""}function H(a){var b=G();if(!a.recent||a.recent!==b){if(b.length){var e,f,d=a.scrollArea.is(".skinnable");d||(e=a.scrollArea.scrollTop(),f=a.recentCategory.is(":visible")?a.recentCategory.height():0);var g=r(b,a.emojiBtnTemplate,!0).split("|").join("");if(a.recentCategory.children(".emojibtn").remove(),c(g).insertAfter(a.recentCategory.children("h1")),a.recentCategory.children(".emojibtn").on("click",function(){a.trigger("emojibtn.click",c(this))}),a.recentFilter.show(),!d){a.recentCategory.show();var h=a.recentCategory.height();f!==h&&a.scrollArea.scrollTop(e+h-f)}}else a.recentFilter.hasClass("active")&&a.recentFilter.removeClass("active").next().addClass("active"),a.recentCategory.hide(),a.recentFilter.hide();a.recent=b}}function I(a,b){var c=G(),d=c.split("|"),e=d.indexOf(b);e!==-1&&d.splice(e,1),d.unshift(b),d.length>9&&d.pop(),localStorage.setItem("recent_emojis",d.join("|")),H(a)}function J(){var a="test";try{return localStorage.setItem(a,a),localStorage.removeItem(a),!0}catch(a){return!1}}function K(d,e,f){f=v(f),d.sprite=f.sprite&&m<3,d.inline=null===f.inline?e.is("INPUT"):f.inline,d.shortnames=f.shortnames,d.saveEmojisAs=f.saveEmojisAs,d.standalone=f.standalone,d.emojiTemplate='<img alt="{alt}" class="emojione'+(d.sprite?'-{uni}" src="'+j+'"/>':'emoji" src="{img}"/>'),d.emojiTemplateAlt=d.sprite?'<i class="emojione-{uni}"/>':'<img class="emojioneemoji" src="{img}"/>',d.emojiBtnTemplate='<i class="emojibtn" role="button" data-name="{name}">'+d.emojiTemplateAlt+"</i>",d.recentEmojis=f.recentEmojis&&J();var h=f.pickerPosition;d.floatingPicker="top"===h||"bottom"===h;var k,q,t,y,z,K,L,M,N,O,i=e.is("TEXTAREA")||e.is("INPUT")?"val":"text",P=F({class:l+(d.standalone?" "+l+"-standalone ":" ")+(e.attr("class")||""),role:"application"},k=d.editor=F("editor").attr({contenteditable:!d.standalone,placeholder:f.placeholder||e.data("placeholder")||e.attr("placeholder")||"",tabindex:0}),N=d.bar=F("bar"),q=d.button=F("button",F("button-open"),F("button-close")).attr("title",f.buttonTitle),t=d.picker=F("picker",F("wrapper",z=F("filters"),O=F("scroll-area",L=F("emojis-list"),y=F("tones",function(){if(f.tones){this.addClass(E("tones-"+f.tonesStyle,!0));for(var a=0;a<=5;a++)this.append(c("<i/>",{class:"btn-tone btn-tone-"+a+(a?"":" active"),"data-skin":a,role:"button"}))}})))).addClass(E("picker-position-"+f.pickerPosition,!0)).addClass(E("filters-position-"+f.filtersPosition,!0)).addClass("hidden"));if(k.data(e.data()),c.each(f.attributes,function(a,b){k.attr(a,b)}),c.each(f.filters,function(a,b){var e=0;if("recent"!==a||d.recentEmojis){if("tones"!==a)c("<i/>",{class:E("filter",!0)+" "+E("filter-"+a,!0),"data-filter":a,title:b.title}).wrapInner(r(b.icon,d.emojiTemplateAlt)).appendTo(z);else{if(!f.tones)return;e=5}do{var g=F("category").attr({name:a,"data-tone":e}).appendTo(L),h=b.emoji.replace(/[\s,;]+/g,"|");e>0&&(g.hide(),h=h.split("|").join("_tone"+e+"|")+"_tone"+e),"recent"===a&&(h=G()),h=r(h,d.sprite?'<i class="emojibtn" role="button" data-name="{name}"><i class="emojione-{uni}"></i></i>':'<i class="emojibtn" role="button" data-name="{name}"><img class="emojioneemoji lazy-emoji" data-src="{img}"/></i>',!0).split("|").join(""),g.html(h),c("<h1/>").text(b.title).prependTo(g)}while(--e>0)}}),f.filters=null,d.sprite||(d.lasyEmoji=L.find(".lazy-emoji")),K=z.find(E("filter")),K.eq(0).addClass("active"),M=L.find(E("category")),d.recentFilter=K.filter('[data-filter="recent"]'),d.recentCategory=M.filter("[name=recent]"),d.scrollArea=O,f.container?c(f.container).wrapInner(P):P.insertAfter(e),f.hideSource&&e.hide(),d.setText(e[i]()),e[i](d.getText()),C.apply(d),d.standalone&&!d.getText().length){var Q=c(e).data("emoji-placeholder")||f.emojiPlaceholder;d.setText(Q),k.addClass("has-placeholder")}p(d,L.find(".emojibtn"),{click:"emojibtn.click"}),p(d,b,{resize:"!resize"}),p(d,y.children(),{click:"tone.click"}),p(d,[t,q],{mousedown:"!mousedown"},k),p(d,q,{click:"button.click"}),p(d,k,{paste:"!paste"},k),p(d,k,["focus","blur"],function(){return!d.stayFocused&&k}),p(d,t,{mousedown:"picker.mousedown",mouseup:"picker.mouseup",click:"picker.click",keyup:"picker.keyup",keydown:"picker.keydown",keypress:"picker.keypress"}),p(d,k,["mousedown","mouseup","click","keyup","keydown","keypress"]),p(d,t.find(".emojionearea-filter"),{click:"filter.click"});var R=!1;if(O.on("scroll",function(){if(!R&&(D.call(d),O.is(":not(.skinnable)"))){var a=M.eq(0),b=O.offset().top;M.each(function(d,e){return!(c(e).offset().top-b>=10)&&void(a=c(e))});var e=K.filter('[data-filter="'+a.attr("name")+'"]');e[0]&&!e.is(".active")&&(K.removeClass("active"),e.addClass("active"))}}),d.on("@filter.click",function(a){var b=a.is(".active");if(O.is(".skinnable")){if(b)return;y.children().eq(0).click()}R=!0,b||(K.filter(".active").removeClass("active"),a.addClass("active"));var c=M.filter('[name="'+a.data("filter")+'"]').offset().top,e=O.scrollTop(),f=O.offset().top;O.stop().animate({scrollTop:c+e-f-2},200,"swing",function(){D.call(d),R=!1})}).on("@picker.show",function(){d.recentEmojis&&H(d),D.call(this)}).on("@tone.click",function(a){y.children().removeClass("active");var b=a.addClass("active").data("skin");b?(O.addClass("skinnable"),M.hide().filter("[data-tone="+b+"]").show(),K.eq(0).is('.active[data-filter="recent"]')&&K.eq(0).removeClass("active").next().addClass("active")):(O.removeClass("skinnable"),M.hide().filter("[data-tone=0]").show(),K.eq(0).click()),D.call(d)}).on("@button.click",function(a){a.is(".active")?d.hidePicker():d.showPicker()}).on("@!paste",function(a,e){var f=function(b){var e="caret-"+(new Date).getTime(),f=A(b,d);s(f),s('<i id="'+e+'"></i>'),a.scrollTop(i);var g=c("#"+e),h=g.offset().top-a.offset().top,j=a.height();(i+h>=j||i>h)&&a.scrollTop(i+h-2*j/3),g.remove(),d.stayFocused=!1,C.apply(d),o(d,"paste",[a,b,f])};if(e.originalEvent.clipboardData){var g=e.originalEvent.clipboardData.getData("text/plain");return f(g),e.preventDefault?e.preventDefault():e.stop(),e.returnValue=!1,e.stopPropagation(),!1}d.stayFocused=!0,s("<span>"+n+"</span>");var h=w(a[0]),i=a.scrollTop(),j=c("<div/>",{contenteditable:!0}).css({position:"fixed",left:"-999px",width:"1px",height:"1px",top:"20px",overflow:"hidden"}).appendTo(c("BODY")).focus();b.setTimeout(function(){a.focus(),x(a[0],h);var b=B(j.html().replace(/\r\n|\n|\r/g,"<br>"),d);j.remove(),f(b)},200)}).on("@emojibtn.click",function(a){k.removeClass("has-placeholder"),P.is(".focused")||k.focus(),d.standalone?(k.html(r(a.data("name"),d.emojiTemplate)),d.trigger("blur")):(w(k[0]),s(r(a.data("name"),d.emojiTemplate))),d.recentEmojis&&I(d,a.data("name"))}).on("@!resize @keyup @emojibtn.click",C).on("@!mousedown",function(a,b){return P.is(".focused")||a.focus(),b.preventDefault(),!1}).on("@change",function(){var a=d.editor.html().replace(/<\/?(?:div|span|p)[^>]*>/gi,"");a.length&&!/^<br[^>]*>$/i.test(a)||d.editor.html(d.content=""),e[i](d.getText())}).on("@focus",function(){P.addClass("focused")}).on("@blur",function(){P.removeClass("focused"),f.hidePickerOnBlur&&d.hidePicker();var a=d.editor.html();d.content!==a?(d.content=a,o(d,"change",[d.editor]),e.blur().trigger("change")):e.blur()}),f.shortcuts&&d.on("@keydown",function(a,b){b.ctrlKey||(9==b.which?(b.preventDefault(),q.click()):27==b.which&&(b.preventDefault(),q.is(".active")&&d.hidePicker()))}),u(f.events)&&!c.isEmptyObject(f.events)&&c.each(f.events,function(a,b){d.on(a.replace(/_/g,"."),b)}),f.autocomplete){var S=function(){var a={maxCount:f.textcomplete.maxCount,placement:f.textcomplete.placement};f.shortcuts&&(a.onKeydown=function(a,b){if(!a.ctrlKey&&13==a.which)return b.KEY_ENTER});var b=c.map(g.emojioneList,function(a,b){return f.autocompleteTones?b:/_tone[12345]/.test(b)?null:b});b.sort(),k.textcomplete([{id:l,match:/\B(:[\-+\w]*)$/,search:function(a,d){d(c.map(b,function(b){return 0===b.indexOf(a)?b:null}))},template:function(a){return r(a,d.emojiTemplate)+" "+a.replace(/:/g,"")},replace:function(a){return r(a,d.emojiTemplate)},cache:!0,index:1}],a),f.textcomplete.placement&&"static"==k.data("textComplete").option.appendTo.css("position")&&k.data("textComplete").option.appendTo.css("position","relative")};c.fn.textcomplete?S():c.getScript("https://cdn.rawgit.com/yuku-t/jquery-textcomplete/v1.3.4/dist/jquery.textcomplete.js",S)}d.inline&&(P.addClass(E("inline",!0)),d.on("@keydown",function(a,b){13==b.which&&b.preventDefault()})),/firefox/i.test(navigator.userAgent)&&a.execCommand("enableObjectResizing",!1,!1)}function N(d){function e(a){var b=a.cacheBustParam;return u(a.jsEscapeMap)?"?v=1.2.4"===b?"2.0.0":"?v=2.0.1"===b?"2.1.0":"?v=2.1.1"===b?"2.1.1":"?v=2.1.2"===b?"2.1.2":"?v=2.1.3"===b?"2.1.3":"2.1.4":"1.5.2"}function f(a){switch(a){case"1.5.2":return 0;case"2.0.0":return 1;case"2.1.0":case"2.1.1":return 2;case"2.1.2":return 3;case"2.1.3":case"2.1.4":default:return 4}}d=v(d),M.isLoading||(!g||f(e(g))<2?(M.isLoading=!0,c.getScript(M.defaultBase+L+"/lib/js/emojione.min.js",function(){if(g=b.emojione,L=e(g),m=f(L),M.base=M.defaultBase+L+"/assets",d.sprite){var i=M.base+"/sprites/emojione.sprites.css";a.createStyleSheet?a.createStyleSheet(i):c("<link/>",{rel:"stylesheet",href:i}).appendTo("head")}for(;h.length;)h.shift().call();M.isLoading=!1})):(L=e(g),m=f(L),M.base=M.defaultBase+L+"/assets")),i(function(){d.useInternalCDN&&(g.imagePathPNG=M.base+"/png/",g.imagePathSVG=M.base+"/svg/",g.imagePathSVGSprites=M.base+"/sprites/emojione.sprites.svg",g.imageType=d.imageType),y=new RegExp("<object[^>]*>.*?</object>|<span[^>]*>.*?</span>|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|("+g.unicodeRegexp+")","gi")})}function P(a,b){b=b.replace(/^@/,"");var d=a.id;f[d][b]&&(c.each(f[d][b],function(d,e){c.each(c.isArray(e[0])?e[0]:[e[0]],function(d,f){c(f).on(e[1],function(){var d=k.call(arguments),f=c.isFunction(e[2])?e[2].apply(a,[b].concat(d)):e[2];f&&o(a,b,[f].concat(d))})})}),f[d][b]=null)}var w,x,d=0,e={},f={},g=b.emojione,h=[],j="data:image/gif;base64,R0lGODlhAQABAJH/AP///wAAAMDAwAAAACH5BAEAAAIALAAAAAABAAEAAAICVAEAOw==",k=[].slice,l="emojionearea",m=0,n="&#8203;",t=function(){return c.fn.emojioneArea&&c.fn.emojioneArea.defaults?c.fn.emojioneArea.defaults:{attributes:{dir:"ltr",spellcheck:!1,autocomplete:"off",autocorrect:"off",autocapitalize:"off"},placeholder:null,emojiPlaceholder:":smiley:",container:null,hideSource:!0,shortnames:!0,sprite:!0,pickerPosition:"top",filtersPosition:"top",hidePickerOnBlur:!0,buttonTitle:"Use the TAB key to insert emoji faster",tones:!0,tonesStyle:"bullet",inline:null,saveEmojisAs:"unicode",shortcuts:!0,autocomplete:!0,autocompleteTones:!1,standalone:!1,useInternalCDN:!0,imageType:"png",recentEmojis:!0,textcomplete:{maxCount:15,placement:null},filters:{tones:{title:"Diversity",emoji:"santa runner surfer swimmer lifter ear nose point_up_2 point_down point_left point_right punch wave ok_hand thumbsup thumbsdown clap open_hands boy girl man woman cop bride_with_veil person_with_blond_hair man_with_gua_pi_mao man_with_turban older_man grandma baby construction_worker princess angel information_desk_person guardsman dancer nail_care massage haircut muscle spy hand_splayed middle_finger vulcan no_good ok_woman bow raising_hand raised_hands person_frowning person_with_pouting_face pray rowboat bicyclist mountain_bicyclist walking bath metal point_up basketball_player fist raised_hand v writing_hand"},recent:{icon:"clock3",title:"Recent",emoji:""},smileys_people:{icon:"yum",title:"Smileys & People",emoji:"grinning grimacing grin joy smiley smile sweat_smile laughing innocent wink blush slight_smile upside_down relaxed yum relieved heart_eyes kissing_heart kissing kissing_smiling_eyes kissing_closed_eyes stuck_out_tongue_winking_eye stuck_out_tongue_closed_eyes stuck_out_tongue money_mouth nerd sunglasses hugging smirk no_mouth neutral_face expressionless unamused rolling_eyes thinking flushed disappointed worried angry rage pensive confused slight_frown frowning2 persevere confounded tired_face weary triumph open_mouth scream fearful cold_sweat hushed frowning anguished cry disappointed_relieved sleepy sweat sob dizzy_face astonished zipper_mouth mask thermometer_face head_bandage sleeping zzz poop smiling_imp imp japanese_ogre japanese_goblin skull ghost alien robot smiley_cat smile_cat joy_cat heart_eyes_cat smirk_cat kissing_cat scream_cat crying_cat_face pouting_cat raised_hands clap wave thumbsup thumbsdown punch fist v ok_hand raised_hand open_hands muscle pray point_up point_up_2 point_down point_left point_right middle_finger hand_splayed metal vulcan writing_hand nail_care lips tongue ear nose eye eyes bust_in_silhouette busts_in_silhouette speaking_head baby boy girl man woman person_with_blond_hair older_man older_woman man_with_gua_pi_mao man_with_turban cop construction_worker guardsman spy santa angel princess bride_with_veil walking runner dancer dancers couple two_men_holding_hands two_women_holding_hands bow information_desk_person no_good ok_woman raising_hand person_with_pouting_face person_frowning haircut massage couple_with_heart couple_ww couple_mm couplekiss kiss_ww kiss_mm family family_mwg family_mwgb family_mwbb family_mwgg family_wwb family_wwg family_wwgb family_wwbb family_wwgg family_mmb family_mmg family_mmgb family_mmbb family_mmgg womans_clothes shirt jeans necktie dress bikini kimono lipstick kiss footprints high_heel sandal boot mans_shoe athletic_shoe womans_hat tophat helmet_with_cross mortar_board crown school_satchel pouch purse handbag briefcase eyeglasses dark_sunglasses ring closed_umbrella"},animals_nature:{icon:"hamster",title:"Animals & Nature",emoji:"dog cat mouse hamster rabbit bear panda_face koala tiger lion_face cow pig pig_nose frog octopus monkey_face see_no_evil hear_no_evil speak_no_evil monkey chicken penguin bird baby_chick hatching_chick hatched_chick wolf boar horse unicorn bee bug snail beetle ant spider scorpion crab snake turtle tropical_fish fish blowfish dolphin whale whale2 crocodile leopard tiger2 water_buffalo ox cow2 dromedary_camel camel elephant goat ram sheep racehorse pig2 rat mouse2 rooster turkey dove dog2 poodle cat2 rabbit2 chipmunk feet dragon dragon_face cactus christmas_tree evergreen_tree deciduous_tree palm_tree seedling herb shamrock four_leaf_clover bamboo tanabata_tree leaves fallen_leaf maple_leaf ear_of_rice hibiscus sunflower rose tulip blossom cherry_blossom bouquet mushroom chestnut jack_o_lantern shell spider_web earth_americas earth_africa earth_asia full_moon waning_gibbous_moon last_quarter_moon waning_crescent_moon new_moon waxing_crescent_moon first_quarter_moon waxing_gibbous_moon new_moon_with_face full_moon_with_face first_quarter_moon_with_face last_quarter_moon_with_face sun_with_face crescent_moon star star2 dizzy sparkles comet sunny white_sun_small_cloud partly_sunny white_sun_cloud white_sun_rain_cloud cloud cloud_rain thunder_cloud_rain cloud_lightning zap fire boom snowflake cloud_snow snowman2 snowman wind_blowing_face dash cloud_tornado fog umbrella2 umbrella droplet sweat_drops ocean"},food_drink:{icon:"pizza",title:"Food & Drink",emoji:"green_apple apple pear tangerine lemon banana watermelon grapes strawberry melon cherries peach pineapple tomato eggplant hot_pepper corn sweet_potato honey_pot bread cheese poultry_leg meat_on_bone fried_shrimp egg hamburger fries hotdog pizza spaghetti taco burrito ramen stew fish_cake sushi bento curry rice_ball rice rice_cracker oden dango shaved_ice ice_cream icecream cake birthday custard candy lollipop chocolate_bar popcorn doughnut cookie beer beers wine_glass cocktail tropical_drink champagne sake tea coffee baby_bottle fork_and_knife fork_knife_plate"},activity:{icon:"basketball",title:"Activity",emoji:"soccer basketball football baseball tennis volleyball rugby_football 8ball golf golfer ping_pong badminton hockey field_hockey cricket ski skier snowboarder ice_skate bow_and_arrow fishing_pole_and_fish rowboat swimmer surfer bath basketball_player lifter bicyclist mountain_bicyclist horse_racing levitate trophy running_shirt_with_sash medal military_medal reminder_ribbon rosette ticket tickets performing_arts art circus_tent microphone headphones musical_score musical_keyboard saxophone trumpet guitar violin clapper video_game space_invader dart game_die slot_machine bowling"},travel_places:{icon:"rocket",title:"Travel & Places",emoji:"red_car taxi blue_car bus trolleybus race_car police_car ambulance fire_engine minibus truck articulated_lorry tractor motorcycle bike rotating_light oncoming_police_car oncoming_bus oncoming_automobile oncoming_taxi aerial_tramway mountain_cableway suspension_railway railway_car train monorail bullettrain_side bullettrain_front light_rail mountain_railway steam_locomotive train2 metro tram station helicopter airplane_small airplane airplane_departure airplane_arriving sailboat motorboat speedboat ferry cruise_ship rocket satellite_orbital seat anchor construction fuelpump busstop vertical_traffic_light traffic_light checkered_flag ship ferris_wheel roller_coaster carousel_horse construction_site foggy tokyo_tower factory fountain rice_scene mountain mountain_snow mount_fuji volcano japan camping tent park motorway railway_track sunrise sunrise_over_mountains desert beach island city_sunset city_dusk cityscape night_with_stars bridge_at_night milky_way stars sparkler fireworks rainbow homes european_castle japanese_castle stadium statue_of_liberty house house_with_garden house_abandoned office department_store post_office european_post_office hospital bank hotel convenience_store school love_hotel wedding classical_building church mosque synagogue kaaba shinto_shrine"},objects:{icon:"bulb",title:"Objects",emoji:"watch iphone calling computer keyboard desktop printer mouse_three_button trackball joystick compression minidisc floppy_disk cd dvd vhs camera camera_with_flash video_camera movie_camera projector film_frames telephone_receiver telephone pager fax tv radio microphone2 level_slider control_knobs stopwatch timer alarm_clock clock hourglass_flowing_sand hourglass satellite battery electric_plug bulb flashlight candle wastebasket oil money_with_wings dollar yen euro pound moneybag credit_card gem scales wrench hammer hammer_pick tools pick nut_and_bolt gear chains gun bomb knife dagger crossed_swords shield smoking skull_crossbones coffin urn amphora crystal_ball prayer_beads barber alembic telescope microscope hole pill syringe thermometer label bookmark toilet shower bathtub key key2 couch sleeping_accommodation bed door bellhop frame_photo map beach_umbrella moyai shopping_bags balloon flags ribbon gift confetti_ball tada dolls wind_chime crossed_flags izakaya_lantern envelope envelope_with_arrow incoming_envelope e-mail love_letter postbox mailbox_closed mailbox mailbox_with_mail mailbox_with_no_mail package postal_horn inbox_tray outbox_tray scroll page_with_curl bookmark_tabs bar_chart chart_with_upwards_trend chart_with_downwards_trend page_facing_up date calendar calendar_spiral card_index card_box ballot_box file_cabinet clipboard notepad_spiral file_folder open_file_folder dividers newspaper2 newspaper notebook closed_book green_book blue_book orange_book notebook_with_decorative_cover ledger books book link paperclip paperclips scissors triangular_ruler straight_ruler pushpin round_pushpin triangular_flag_on_post flag_white flag_black closed_lock_with_key lock unlock lock_with_ink_pen pen_ballpoint pen_fountain black_nib pencil pencil2 crayon paintbrush mag mag_right"},symbols:{icon:"heartpulse",title:"Symbols",emoji:"heart yellow_heart green_heart blue_heart purple_heart broken_heart heart_exclamation two_hearts revolving_hearts heartbeat heartpulse sparkling_heart cupid gift_heart heart_decoration peace cross star_and_crescent om_symbol wheel_of_dharma star_of_david six_pointed_star menorah yin_yang orthodox_cross place_of_worship ophiuchus aries taurus gemini cancer leo virgo libra scorpius sagittarius capricorn aquarius pisces id atom u7a7a u5272 radioactive biohazard mobile_phone_off vibration_mode u6709 u7121 u7533 u55b6 u6708 eight_pointed_black_star vs accept white_flower ideograph_advantage secret congratulations u5408 u6e80 u7981 a b ab cl o2 sos no_entry name_badge no_entry_sign x o anger hotsprings no_pedestrians do_not_litter no_bicycles non-potable_water underage no_mobile_phones exclamation grey_exclamation question grey_question bangbang interrobang 100 low_brightness high_brightness trident fleur-de-lis part_alternation_mark warning children_crossing beginner recycle u6307 chart sparkle eight_spoked_asterisk negative_squared_cross_mark white_check_mark diamond_shape_with_a_dot_inside cyclone loop globe_with_meridians m atm sa passport_control customs baggage_claim left_luggage wheelchair no_smoking wc parking potable_water mens womens baby_symbol restroom put_litter_in_its_place cinema signal_strength koko ng ok up cool new free zero one two three four five six seven eight nine ten 1234 arrow_forward pause_button play_pause stop_button record_button track_next track_previous fast_forward rewind twisted_rightwards_arrows repeat repeat_one arrow_backward arrow_up_small arrow_down_small arrow_double_up arrow_double_down arrow_right arrow_left arrow_up arrow_down arrow_upper_right arrow_lower_right arrow_lower_left arrow_upper_left arrow_up_down left_right_arrow arrows_counterclockwise arrow_right_hook leftwards_arrow_with_hook arrow_heading_up arrow_heading_down hash asterisk information_source abc abcd capital_abcd symbols musical_note notes wavy_dash curly_loop heavy_check_mark arrows_clockwise heavy_plus_sign heavy_minus_sign heavy_division_sign heavy_multiplication_x heavy_dollar_sign currency_exchange copyright registered tm end back on top soon ballot_box_with_check radio_button white_circle black_circle red_circle large_blue_circle small_orange_diamond small_blue_diamond large_orange_diamond large_blue_diamond small_red_triangle black_small_square white_small_square black_large_square white_large_square small_red_triangle_down black_medium_square white_medium_square black_medium_small_square white_medium_small_square black_square_button white_square_button speaker sound loud_sound mute mega loudspeaker bell no_bell black_joker mahjong spades clubs hearts diamonds flower_playing_cards thought_balloon anger_right speech_balloon clock1 clock2 clock3 clock4 clock5 clock6 clock7 clock8 clock9 clock10 clock11 clock12 clock130 clock230 clock330 clock430 clock530 clock630 clock730 clock830 clock930 clock1030 clock1130 clock1230 eye_in_speech_bubble"},flags:{icon:"flag_gb",title:"Flags",emoji:"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 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 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 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 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 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 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 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 "}}}};b.getSelection&&a.createRange?(w=function(a){var c=b.getSelection&&b.getSelection();if(c&&c.rangeCount>0){var d=c.getRangeAt(0),e=d.cloneRange();return e.selectNodeContents(a),e.setEnd(d.startContainer,d.startOffset),e.toString().length}},x=function(c,d){var e=0,f=a.createRange();f.setStart(c,0),f.collapse(!0);for(var h,g=[c],i=!1,j=!1;!j&&(h=g.pop());)if(3==h.nodeType){var k=e+h.length;!i&&d>=e&&d<=k&&(f.setStart(h,d-e),f.setEnd(h,d-e),j=!0),e=k}else for(var l=h.childNodes.length;l--;)g.push(h.childNodes[l]);d=b.getSelection(),d.removeAllRanges(),d.addRange(f)}):a.selection&&a.body.createTextRange&&(w=function(b){var c=a.selection.createRange(),d=a.body.createTextRange();d.moveToElementText(b),d.setEndPoint("EndToStart",c);var e=d.text.length;return e+c.text.length},x=function(b,c){var d=a.body.createTextRange();d.moveToElementText(b),d.collapse(!0),d.moveEnd("character",c),d.moveStart("character",c),d.select()});var y,L=b.emojioneVersion||"2.1.4",M={defaultBase:"https://cdnjs.cloudflare.com/ajax/libs/emojione/",base:null,isLoading:!1},O=function(a,b){var c=this;N(b),e[c.id=++d]={},f[c.id]={},i(function(){K(c,a,b)})};O.prototype.on=function(a,b){if(a&&c.isFunction(b)){var d=this;c.each(a.toLowerCase().split(" "),function(a,c){P(d,c),(e[d.id][c]||(e[d.id][c]=[])).push(b)})}return this},O.prototype.off=function(a,b){if(a){var d=this.id;c.each(a.toLowerCase().replace(/_/g,".").split(" "),function(a,f){e[d][f]&&!/^@/.test(f)&&(b?c.each(e[d][f],function(a,c){c===b&&(e[d][f]=e[d][f].splice(a,1))}):e[d][f]=[])})}return this},O.prototype.trigger=function(){var a=k.call(arguments),b=[this].concat(a.slice(0,1));return b.push(a.slice(1)),o.apply(this,b)},O.prototype.setFocus=function(){var a=this;return i(function(){a.editor.focus()}),a},O.prototype.setText=function(a){var b=this;return i(function(){b.editor.html(A(a,b)),b.content=b.editor.html(),o(b,"change",[b.editor]),C.apply(b)}),b},O.prototype.getText=function(){return B(this.editor.html(),this)},O.prototype.showPicker=function(){var a=this;return a._sh_timer&&b.clearTimeout(a._sh_timer),a.picker.removeClass("hidden"),a._sh_timer=b.setTimeout(function(){a.button.addClass("active")},50),o(a,"picker.show",[a.picker]),a},O.prototype.hidePicker=function(){var a=this;return a._sh_timer&&b.clearTimeout(a._sh_timer),a.button.removeClass("active"),a._sh_timer=b.setTimeout(function(){a.picker.addClass("hidden")},500),o(a,"picker.hide",[a.picker]),a},c.fn.emojioneArea=function(a){return this.each(function(){return this.emojioneArea?this.emojioneArea:(c.data(this,"emojioneArea",this.emojioneArea=new O(c(this),a)),this.emojioneArea)})},c.fn.emojioneArea.defaults=t()}(document,window,jQuery);
@@ -0,0 +1,44 @@
1
+ event =
2
+ if typeof(Turbolinks) == "undefined"
3
+ 'DOMContentLoaded'
4
+ else
5
+ 'turbolinks:load'
6
+
7
+ document.addEventListener event, ->
8
+ $('.chat__launch').click ->
9
+ $('#chat').addClass('active')
10
+ show_chats()
11
+ return
12
+
13
+ $('.chat__close').click ->
14
+ $('#chat').removeClass('active')
15
+ return
16
+
17
+ $('.chat__settings').click ->
18
+ show_chats()
19
+ return
20
+
21
+ $(document).on 'click', '.chat__start-new', (e) ->
22
+ e.preventDefault()
23
+ $('.chat__list').css('display', 'none')
24
+ $('.new_conversation').css('display', 'flex')
25
+ return
26
+
27
+ $(document).on 'click', '.chat__insert-image', ->
28
+ $(".new_message input[type='file']").click()
29
+ return
30
+
31
+ $(document).on 'keyup', '.new_message .emojionearea-editor', (e) ->
32
+ if e.keyCode == 13 && !e.shiftKey
33
+ $('.new_message textarea').val($('.new_message .emojionearea-editor').html())
34
+ $('.new_message').submit()
35
+ $('#message_text').prop('value', '')
36
+ el = $('.new_message textarea').emojioneArea()
37
+ el[0].emojioneArea.setText('')
38
+ return
39
+
40
+ show_chats = ->
41
+ $('.chat__list').css('display', 'flex')
42
+ $('.current_chat').css('display', 'none')
43
+ $('.new_conversation').css('display', 'none')
44
+ return
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
+ * files in this directory. Styles in this file should be added after the last require_* statement.
11
+ * It is generally better to create a new file per style scope.
12
+ *
13
+ *= require material_icons
14
+ *= require_tree ./chat
15
+ */
@@ -0,0 +1,25 @@
1
+ @import "https://fonts.googleapis.com/css?family=Lato:300&subset=latin-ext"
2
+
3
+ #chat
4
+ font-family: "Lato" !important
5
+ letter-spacing: 1.5px !important
6
+ width: 375px
7
+ height: 100%
8
+ position: fixed
9
+ right: 0
10
+ top: 0
11
+ opacity: 0
12
+ background: rgb(245, 245, 245)
13
+ visibility: hidden
14
+ transform: scale(0)
15
+ transform-origin: bottom right
16
+ transition: transform .3s ease-in-out, opacity .1s linear .15s
17
+ box-shadow: 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12), 0 2px 4px -1px rgba(0, 0, 0, 0.2)
18
+ @media (max-width: 450px)
19
+ width: 100%
20
+ &.active
21
+ visibility: visible
22
+ opacity: 1
23
+ transform: scale(1)
24
+ .chat__flex
25
+ flex: 1
@@ -0,0 +1,80 @@
1
+ .new_conversation
2
+ [type="checkbox"]:not(:checked), [type="checkbox"]:checked
3
+ position: absolute
4
+ left: -9999px
5
+ opacity: 0
6
+
7
+ [type="checkbox"] + label
8
+ position: relative
9
+ padding-left: 35px
10
+ cursor: pointer
11
+ display: inline-block
12
+ height: 25px
13
+ line-height: 25px
14
+ font-size: 1rem
15
+ -webkit-user-select: none
16
+ -moz-user-select: none
17
+ -khtml-user-select: none
18
+ -ms-user-select: none
19
+
20
+ [type="checkbox"] + label:before, [type="checkbox"]:not(.filled-in) + label:after
21
+ content: ''
22
+ position: absolute
23
+ top: -2px
24
+ left: 0
25
+ width: 21px
26
+ height: 21px
27
+ z-index: 0
28
+ border: 2px solid #5a5a5a
29
+ border-radius: 1px
30
+ margin-top: 2px
31
+ transition: .2s
32
+
33
+ [type="checkbox"]:not(.filled-in) + label:after
34
+ border: 0
35
+ -webkit-transform: scale(0)
36
+ transform: scale(0)
37
+
38
+ [type="checkbox"]:not(:checked):disabled + label:before
39
+ border: none
40
+ background-color: rgba(0, 0, 0, 0.26)
41
+
42
+ [type="checkbox"]:checked + label:before
43
+ top: -8px
44
+ left: -5px
45
+ width: 14px
46
+ height: 26px
47
+ border-top: 2px solid transparent
48
+ border-left: 2px solid transparent
49
+ border-right: 2px solid #26a69a
50
+ border-bottom: 2px solid #26a69a
51
+ -webkit-transform: rotate(40deg)
52
+ transform: rotate(40deg)
53
+ -webkit-backface-visibility: hidden
54
+ backface-visibility: hidden
55
+ -webkit-transform-origin: 100% 100%
56
+ transform-origin: 100% 100%
57
+
58
+ [type="checkbox"]:checked:disabled + label:before
59
+ border-right: 2px solid rgba(0, 0, 0, 0.26)
60
+ border-bottom: 2px solid rgba(0, 0, 0, 0.26)
61
+
62
+ [type="checkbox"]:indeterminate + label:before
63
+ top: -11px
64
+ left: -12px
65
+ width: 10px
66
+ height: 22px
67
+ border-top: none
68
+ border-left: none
69
+ border-right: 2px solid #e50000
70
+ border-bottom: none
71
+ -webkit-transform: rotate(90deg)
72
+ transform: rotate(90deg)
73
+ -webkit-backface-visibility: hidden
74
+ backface-visibility: hidden
75
+ -webkit-transform-origin: 100% 100%
76
+ transform-origin: 100% 100%
77
+
78
+ [type="checkbox"]:indeterminate:disabled + label:before
79
+ border-right: 2px solid rgba(0, 0, 0, 0.26)
80
+ background-color: transparent