wiser_chat 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +135 -0
- data/Rakefile +1 -0
- data/lib/generators/wiser_chat/install/install_generator.rb +41 -0
- data/lib/generators/wiser_chat/install/templates/controller.rb +67 -0
- data/lib/generators/wiser_chat/install/templates/events.rb +6 -0
- data/lib/generators/wiser_chat/install/templates/helper.rb +5 -0
- data/lib/generators/wiser_chat/install/templates/javascript.js +139 -0
- data/lib/generators/wiser_chat/install/templates/migration.rb +11 -0
- data/lib/generators/wiser_chat/install/templates/model.rb +3 -0
- data/lib/generators/wiser_chat/install/templates/moment.js +7 -0
- data/lib/generators/wiser_chat/install/templates/partial.html.haml +22 -0
- data/lib/generators/wiser_chat/install/templates/stylesheet.css +42 -0
- data/lib/generators/wiser_chat/install/templates/websocket.rb +6 -0
- data/lib/generators/wiser_chat/migration/migration_generator.rb +16 -0
- data/lib/generators/wiser_chat/migration/templates/migration.rb +12 -0
- data/lib/generators/wiser_chat.rb +12 -0
- data/lib/wiser_chat/engine.rb +7 -0
- data/lib/wiser_chat/version.rb +3 -0
- data/lib/wiser_chat.rb +7 -0
- data/wiser_chat.gemspec +25 -0
- metadata +96 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5b89eb85a0890d0b2e6ce8119ddaa0c125eef985
|
4
|
+
data.tar.gz: 6d2169b0537a9b8f1e4017300c95e127632e8154
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 819418813e49d78c21b72e0dc64502de0b80720a8b5de0b5d659ad6b382a446fa6b02ba144ec7b7abf2fc1c692764b3fe51ae3028cd477bd46ac113613a2c678
|
7
|
+
data.tar.gz: f22dda3f030e230429acbeb25f7972bcb902e859aadbe8628a3ed93990bd6e8d1a16f99f6118346cad44f089ad0ec0514b8ed2e830d5ea3324d55f9efcf7da29
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Kenneth John Balgos
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
# WiserChat
|
2
|
+
|
3
|
+
Awesome chat on fire!
|
4
|
+
|
5
|
+
## Requirements
|
6
|
+
|
7
|
+
_WiserChat_ only support Rails >= 3.2 with jQuery.
|
8
|
+
|
9
|
+
The following items are required:
|
10
|
+
|
11
|
+
- Redis should be installed in the server, please see [http://redis.io](http://redis.io).
|
12
|
+
- `User` model should be available and it should have a `name` method that returns the user name for the chat.
|
13
|
+
- WiserChat should be used only when there's a user logged in - `current_user` method should be available.
|
14
|
+
|
15
|
+
|
16
|
+
## Setup
|
17
|
+
|
18
|
+
### Gem Installation
|
19
|
+
|
20
|
+
Include the following lines in your `Gemfile`:
|
21
|
+
|
22
|
+
gem 'redis', '3.2.0'
|
23
|
+
gem 'websocket-rails', '~> 0.7.0'
|
24
|
+
gem 'wiser_chat', '~> 0.1.0'
|
25
|
+
|
26
|
+
Then run:
|
27
|
+
|
28
|
+
bundle install
|
29
|
+
|
30
|
+
After installing the gems, you're now ready to install WiserChat by running this command:
|
31
|
+
|
32
|
+
bundle exec generate wiser_chat:install
|
33
|
+
|
34
|
+
The install command will generate the necessary files as well as the migration for the database. Now, run the migration to create the database table:
|
35
|
+
|
36
|
+
bundle exec rake db:migrate
|
37
|
+
|
38
|
+
Lastly, remove the Rack::Lock middleware by adding this line at the end of your `development.rb` file:
|
39
|
+
|
40
|
+
config.middleware.delete Rack::Lock
|
41
|
+
|
42
|
+
## Usage
|
43
|
+
|
44
|
+
### Important: Run the websocket
|
45
|
+
|
46
|
+
WiserChat will use websocket and redis, you need to start the websocket server:
|
47
|
+
|
48
|
+
bundle exec rake websocket_rails:start_server
|
49
|
+
|
50
|
+
The websocket logs will be available at `log/websocket_rails.log` and `log/websocket_rails_server.log`.
|
51
|
+
|
52
|
+
### Rendering the chat box
|
53
|
+
|
54
|
+
You can always use this helper method in your view:
|
55
|
+
|
56
|
+
= wiser_chat(@channel_name)
|
57
|
+
|
58
|
+
You need to specify the `@channel_name` to group the chat conversations. You can have different channels in different pages, but you cannot have multiple channels in a single page.
|
59
|
+
|
60
|
+
Channel name is very sensitive, use alpha-numeric characters only. In other words, do not use any special characters in your channel name.
|
61
|
+
|
62
|
+
### Stylesheet
|
63
|
+
|
64
|
+
Include the `wiser_chat` stylesheet into your `app/assets/stylesheets/application.css`:
|
65
|
+
|
66
|
+
*= require wiser_chat
|
67
|
+
|
68
|
+
By default, the chat box will be hidden and you need to toggle the `#wiser-chat` element to display it. But you can create a link with `toggle_chat` class to add a display control for the chat box.
|
69
|
+
|
70
|
+
= link_to "Chat", "#", class: "toggle_chat"
|
71
|
+
|
72
|
+
However, you can always customize it or event create your own appearance by editing the `app/assets/stylesheets/wiser_chat.css`.
|
73
|
+
|
74
|
+
## Capistrano
|
75
|
+
|
76
|
+
You need to run the websocket in your server and adding the codes below will make it easier for you to do it using the capistrano commands. Append this in your `deploy.rb` file:
|
77
|
+
|
78
|
+
set :stage, lambda{ config_name.split(':').last }
|
79
|
+
namespace :websocket do
|
80
|
+
desc 'Stop websocket deamon'
|
81
|
+
task :stop do
|
82
|
+
on roles(:app), in: :sequence, wait: 5 do
|
83
|
+
within current_path do
|
84
|
+
websocket_pid = current_path.join('tmp/pids/websocket_rails.pid')
|
85
|
+
if test("[ -f #{websocket_pid} ]") then
|
86
|
+
with rails_env: fetch(:stage) do
|
87
|
+
rake 'websocket_rails:stop_server'
|
88
|
+
end
|
89
|
+
else
|
90
|
+
info "WebsocketRails is not running, not need to be stopped."
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
desc 'Start websocket deamon'
|
97
|
+
task :start do
|
98
|
+
on roles(:app), in: :sequence, wait: 5 do
|
99
|
+
within current_path do
|
100
|
+
with rails_env: fetch(:stage) do
|
101
|
+
info 'Start WebsocketRails server'
|
102
|
+
rake 'websocket_rails:start_server'
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
After that, these capistrano commands will do the work:
|
110
|
+
|
111
|
+
bundle exec cap production websocket:start
|
112
|
+
|
113
|
+
You can also kill the websocket using this capistrano command:
|
114
|
+
|
115
|
+
bundle exec cap production websocket:stop
|
116
|
+
|
117
|
+
|
118
|
+
## Contributing
|
119
|
+
|
120
|
+
1. Fork it
|
121
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
122
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
123
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
124
|
+
5. Create new Pull Request
|
125
|
+
|
126
|
+
## Support
|
127
|
+
Open an issue in https://github.com/kennethjohnbalgos/wiser_chat if you need further support or want to report a bug.
|
128
|
+
|
129
|
+
## License
|
130
|
+
|
131
|
+
The MIT License (MIT) Copyright (c) 2015 iKennOnline
|
132
|
+
|
133
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
134
|
+
|
135
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'rails'
|
2
|
+
module WiserChat
|
3
|
+
module Generators
|
4
|
+
# Install generator that creates migration file from template
|
5
|
+
class InstallGenerator < Rails::Generators::Base
|
6
|
+
source_root File.expand_path("../templates", __FILE__)
|
7
|
+
|
8
|
+
class_option :js_manifest, :type => :string, :aliases => "-m", :default => 'application.js',
|
9
|
+
:desc => "Javascript manifest file to modify (or create)"
|
10
|
+
|
11
|
+
def create_events_initializer_file
|
12
|
+
timestamp = Time.now.strftime("%Y%m%d%H%M%S")
|
13
|
+
template 'events.rb', File.join('config', 'events.rb')
|
14
|
+
template 'websocket.rb', File.join('config', 'initializers', 'websocket_rails.rb')
|
15
|
+
template 'moment.js', File.join('app', 'assets', 'javascripts', 'jquery.moment.js')
|
16
|
+
template 'javascript.js', File.join('app', 'assets', 'javascripts', 'wiser_chat.js')
|
17
|
+
template 'stylesheet.css', File.join('app', 'assets', 'stylesheets', 'wiser_chat.css')
|
18
|
+
template 'partial.html.haml', File.join('app', 'views', 'layouts', '_wiser_chat.html.haml')
|
19
|
+
template 'model.rb', File.join('app', 'models', 'wiser_chat_message.rb')
|
20
|
+
template 'helper.rb', File.join('app', 'helpers', 'wiser_chat_helper.rb')
|
21
|
+
template 'controller.rb', File.join('app', 'controllers', 'wiser_chat_controller.rb')
|
22
|
+
template 'migration.rb', File.join('db', 'migrate', "#{timestamp}_create_wiser_chat_messages.rb")
|
23
|
+
end
|
24
|
+
|
25
|
+
def inject_websocket_rails_client
|
26
|
+
js_manifest = options[:js_manifest]
|
27
|
+
js_path = "app/assets/javascripts"
|
28
|
+
create_file("#{js_path}/#{js_manifest}") unless File.exists?("#{js_path}/#{js_manifest}")
|
29
|
+
append_to_file "#{js_path}/#{js_manifest}" do
|
30
|
+
out = ""
|
31
|
+
out << "\n"
|
32
|
+
out << "//= require jquery.moment"
|
33
|
+
out << "\n"
|
34
|
+
out << "//= require websocket_rails/main"
|
35
|
+
out << "\n"
|
36
|
+
out << "//= require wiser_chat"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
class WiserChatController < WebsocketRails::BaseController
|
2
|
+
include ActionView::Helpers::SanitizeHelper
|
3
|
+
|
4
|
+
def initialize_session
|
5
|
+
puts ""
|
6
|
+
puts "Session Initialized"
|
7
|
+
end
|
8
|
+
|
9
|
+
def client_connected
|
10
|
+
puts "Action: Client Connected"
|
11
|
+
end
|
12
|
+
|
13
|
+
def new_message
|
14
|
+
puts "Action: New Message"
|
15
|
+
@channel_name, @user = get_channel_and_user(message)
|
16
|
+
send_user_message(@channel_name, @user, message[:msg_body])
|
17
|
+
end
|
18
|
+
|
19
|
+
def new_user
|
20
|
+
puts "Action: New User"
|
21
|
+
@channel_name, @user = get_channel_and_user(message)
|
22
|
+
send_system_message(@channel_name, "#{@user.name} is now connected!")
|
23
|
+
add_channel_user(@channel_name, @user)
|
24
|
+
send_user_list(@channel_name)
|
25
|
+
end
|
26
|
+
|
27
|
+
def delete_user
|
28
|
+
puts "Action: Delete User"
|
29
|
+
@channel_name, @user = get_channel_and_user(connection_store[:user])
|
30
|
+
send_system_message(@channel_name, "#{@user.name} disconnected!")
|
31
|
+
remove_channel_user
|
32
|
+
send_user_list(@channel_name)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def send_user_message(channel_name, user, message_content)
|
38
|
+
msg = WiserChatMessage.create(user: user, channel: channel_name, content: message_content)
|
39
|
+
data = { user_id: user.id, user_name: user.name, msg_body: msg.content, channel: msg.channel }
|
40
|
+
WebsocketRails[channel_name].trigger "new_message", data
|
41
|
+
end
|
42
|
+
|
43
|
+
def send_system_message(channel_name, msg)
|
44
|
+
data = { user_id: 0, user_name: "System", msg_body: msg, channel: channel_name }
|
45
|
+
WebsocketRails[channel_name].trigger "system_message", data
|
46
|
+
end
|
47
|
+
|
48
|
+
def send_user_list(channel_name)
|
49
|
+
puts "Action: Broadcast user list for #{channel_name} channel"
|
50
|
+
all_users = connection_store.collect_all(:user)
|
51
|
+
channel_users = all_users.map{|u| u if u[:channel_name] == channel_name}.compact
|
52
|
+
WebsocketRails[channel_name].trigger "user_list", channel_users
|
53
|
+
end
|
54
|
+
|
55
|
+
def get_channel_and_user(data)
|
56
|
+
return data[:channel_name], User.find(data[:id])
|
57
|
+
end
|
58
|
+
|
59
|
+
def add_channel_user(channel_name, user)
|
60
|
+
connection_store[:user] = { id: user.id, name: user.name, channel_name: channel_name }
|
61
|
+
end
|
62
|
+
|
63
|
+
def remove_channel_user
|
64
|
+
connection_store[:user] = nil
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -0,0 +1,6 @@
|
|
1
|
+
WebsocketRails::EventMap.describe do
|
2
|
+
subscribe :client_connected, to: WiserChatController, with_method: :client_connected
|
3
|
+
subscribe :new_message, to: WiserChatController, with_method: :new_message
|
4
|
+
subscribe :new_user, to: WiserChatController, with_method: :new_user
|
5
|
+
subscribe :client_disconnected, to: WiserChatController, with_method: :delete_user
|
6
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
var chatHooks,
|
2
|
+
bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
3
|
+
|
4
|
+
$(function() {
|
5
|
+
$(document).ready(chatHooks);
|
6
|
+
$(document).on("page:load", chatHooks);
|
7
|
+
return $(document).on("click", ".toggle_chat", function(e) {
|
8
|
+
e.preventDefault();
|
9
|
+
$("#wiser-chat").slideToggle();
|
10
|
+
$('#wiser-chat #chat-content').scrollTop(999999);
|
11
|
+
return $("#wiser-chat #message").focus();
|
12
|
+
});
|
13
|
+
});
|
14
|
+
|
15
|
+
chatHooks = function() {
|
16
|
+
if ($("#wiser-chat").size() > 0) {
|
17
|
+
return window.chatController = new Chat.Controller($('#wiser-chat').data('uri'), true, $('#wiser-chat').data('channel'));
|
18
|
+
}
|
19
|
+
};
|
20
|
+
|
21
|
+
window.Chat = {};
|
22
|
+
|
23
|
+
Chat.User = (function() {
|
24
|
+
function User(id, name, channel_name) {
|
25
|
+
this.id = id;
|
26
|
+
this.name = name;
|
27
|
+
this.channel_name = channel_name;
|
28
|
+
this.serialize = bind(this.serialize, this);
|
29
|
+
}
|
30
|
+
|
31
|
+
User.prototype.serialize = function() {
|
32
|
+
return {
|
33
|
+
id: this.id,
|
34
|
+
name: this.name,
|
35
|
+
channel_name: this.channel_name
|
36
|
+
};
|
37
|
+
};
|
38
|
+
|
39
|
+
return User;
|
40
|
+
|
41
|
+
})();
|
42
|
+
|
43
|
+
Chat.Controller = (function() {
|
44
|
+
Controller.prototype.systemMessageTemplate = function(message) {
|
45
|
+
var html;
|
46
|
+
html = "<div class=\"message\" >\n <span class=\"system_message\">" + message.msg_body + "</span>\n</div>";
|
47
|
+
return $(html);
|
48
|
+
};
|
49
|
+
|
50
|
+
Controller.prototype.userMessageTemplate = function(message) {
|
51
|
+
var html;
|
52
|
+
html = "<div class=\"message\" >\n <span class=\"label label-default\">" + (moment().format('h:mm:ss a')) + "</span>\n <b>" + message.user_name + ":</b>\n " + message.msg_body + "\n</div>";
|
53
|
+
return $(html);
|
54
|
+
};
|
55
|
+
|
56
|
+
Controller.prototype.userListTemplate = function(userList) {
|
57
|
+
var i, len, user, userHtml;
|
58
|
+
userHtml = "";
|
59
|
+
for (i = 0, len = userList.length; i < len; i++) {
|
60
|
+
user = userList[i];
|
61
|
+
userHtml = userHtml + ("<li>" + user.name + "</li>");
|
62
|
+
}
|
63
|
+
return $(userHtml);
|
64
|
+
};
|
65
|
+
|
66
|
+
function Controller(url, useWebSockets, channelName) {
|
67
|
+
this.createGuestUser = bind(this.createGuestUser, this);
|
68
|
+
this.updateUserList = bind(this.updateUserList, this);
|
69
|
+
this.sendMessage = bind(this.sendMessage, this);
|
70
|
+
this.newMessage = bind(this.newMessage, this);
|
71
|
+
this.systemMessage = bind(this.systemMessage, this);
|
72
|
+
this.bindEvents = bind(this.bindEvents, this);
|
73
|
+
this.messageQueue = [];
|
74
|
+
this.dispatcher = new WebSocketRails(url, useWebSockets);
|
75
|
+
this.dispatcher.on_open = this.createGuestUser;
|
76
|
+
this.channel = this.dispatcher.subscribe(channelName);
|
77
|
+
this.bindEvents();
|
78
|
+
}
|
79
|
+
|
80
|
+
Controller.prototype.bindEvents = function() {
|
81
|
+
this.channel.bind('new_message', this.newMessage);
|
82
|
+
this.channel.bind('system_message', this.systemMessage);
|
83
|
+
this.channel.bind('user_list', this.updateUserList);
|
84
|
+
$('#wiser-chat #send').on('click', this.sendMessage);
|
85
|
+
return $('#wiser-chat #message').keypress(function(e) {
|
86
|
+
if (e.keyCode === 13) {
|
87
|
+
e.preventDefault();
|
88
|
+
if ($.trim($('#wiser-chat #message').val()) !== "") {
|
89
|
+
return $('#wiser-chat #send').click();
|
90
|
+
}
|
91
|
+
}
|
92
|
+
});
|
93
|
+
};
|
94
|
+
|
95
|
+
Controller.prototype.systemMessage = function(message) {
|
96
|
+
return this.appendMessage(message, true);
|
97
|
+
};
|
98
|
+
|
99
|
+
Controller.prototype.newMessage = function(message) {
|
100
|
+
return this.appendMessage(message, false);
|
101
|
+
};
|
102
|
+
|
103
|
+
Controller.prototype.sendMessage = function(event) {
|
104
|
+
var data, message;
|
105
|
+
event.preventDefault();
|
106
|
+
message = $('#wiser-chat #message').val();
|
107
|
+
data = {
|
108
|
+
id: this.user.id,
|
109
|
+
msg_body: message,
|
110
|
+
channel_name: this.channel.name
|
111
|
+
};
|
112
|
+
this.dispatcher.trigger('new_message', data);
|
113
|
+
return $('#wiser-chat #message').val('');
|
114
|
+
};
|
115
|
+
|
116
|
+
Controller.prototype.updateUserList = function(userList) {
|
117
|
+
return $('#wiser-chat #chat-users').html(this.userListTemplate(userList));
|
118
|
+
};
|
119
|
+
|
120
|
+
Controller.prototype.appendMessage = function(message, from_system) {
|
121
|
+
var messageTemplate;
|
122
|
+
if (from_system) {
|
123
|
+
messageTemplate = this.systemMessageTemplate(message);
|
124
|
+
} else {
|
125
|
+
messageTemplate = this.userMessageTemplate(message);
|
126
|
+
}
|
127
|
+
$('#wiser-chat #chat-messages').append(messageTemplate);
|
128
|
+
$('#wiser-chat #chat-content').scrollTop(999999);
|
129
|
+
return $('#wiser-chat #chat-messages .message').last().hide().fadeIn();
|
130
|
+
};
|
131
|
+
|
132
|
+
Controller.prototype.createGuestUser = function() {
|
133
|
+
this.user = new Chat.User($("#wiser-chat #name").data('id'), $("#wiser-chat #name").val(), this.channel.name);
|
134
|
+
return this.dispatcher.trigger('new_user', this.user.serialize());
|
135
|
+
};
|
136
|
+
|
137
|
+
return Controller;
|
138
|
+
|
139
|
+
})();
|
@@ -0,0 +1,7 @@
|
|
1
|
+
//! moment.js
|
2
|
+
//! version : 2.10.2
|
3
|
+
//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
|
4
|
+
//! license : MIT
|
5
|
+
//! momentjs.com
|
6
|
+
!function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.moment=b()}(this,function(){"use strict";function a(){return Ac.apply(null,arguments)}function b(a){Ac=a}function c(){return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1}}function d(a){return"[object Array]"===Object.prototype.toString.call(a)}function e(a){return"[object Date]"===Object.prototype.toString.call(a)||a instanceof Date}function f(a,b){var c,d=[];for(c=0;c<a.length;++c)d.push(b(a[c],c));return d}function g(a,b){return Object.prototype.hasOwnProperty.call(a,b)}function h(a,b){for(var c in b)g(b,c)&&(a[c]=b[c]);return g(b,"toString")&&(a.toString=b.toString),g(b,"valueOf")&&(a.valueOf=b.valueOf),a}function i(a,b,c,d){return ya(a,b,c,d,!0).utc()}function j(a){return null==a._isValid&&(a._isValid=!isNaN(a._d.getTime())&&a._pf.overflow<0&&!a._pf.empty&&!a._pf.invalidMonth&&!a._pf.nullInput&&!a._pf.invalidFormat&&!a._pf.userInvalidated,a._strict&&(a._isValid=a._isValid&&0===a._pf.charsLeftOver&&0===a._pf.unusedTokens.length&&void 0===a._pf.bigHour)),a._isValid}function k(a){var b=i(0/0);return null!=a?h(b._pf,a):b._pf.userInvalidated=!0,b}function l(a,b){var c,d,e;if("undefined"!=typeof b._isAMomentObject&&(a._isAMomentObject=b._isAMomentObject),"undefined"!=typeof b._i&&(a._i=b._i),"undefined"!=typeof b._f&&(a._f=b._f),"undefined"!=typeof b._l&&(a._l=b._l),"undefined"!=typeof b._strict&&(a._strict=b._strict),"undefined"!=typeof b._tzm&&(a._tzm=b._tzm),"undefined"!=typeof b._isUTC&&(a._isUTC=b._isUTC),"undefined"!=typeof b._offset&&(a._offset=b._offset),"undefined"!=typeof b._pf&&(a._pf=b._pf),"undefined"!=typeof b._locale&&(a._locale=b._locale),Cc.length>0)for(c in Cc)d=Cc[c],e=b[d],"undefined"!=typeof e&&(a[d]=e);return a}function m(b){l(this,b),this._d=new Date(+b._d),Dc===!1&&(Dc=!0,a.updateOffset(this),Dc=!1)}function n(a){return a instanceof m||null!=a&&g(a,"_isAMomentObject")}function o(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=b>=0?Math.floor(b):Math.ceil(b)),c}function p(a,b,c){var d,e=Math.min(a.length,b.length),f=Math.abs(a.length-b.length),g=0;for(d=0;e>d;d++)(c&&a[d]!==b[d]||!c&&o(a[d])!==o(b[d]))&&g++;return g+f}function q(){}function r(a){return a?a.toLowerCase().replace("_","-"):a}function s(a){for(var b,c,d,e,f=0;f<a.length;){for(e=r(a[f]).split("-"),b=e.length,c=r(a[f+1]),c=c?c.split("-"):null;b>0;){if(d=t(e.slice(0,b).join("-")))return d;if(c&&c.length>=b&&p(e,c,!0)>=b-1)break;b--}f++}return null}function t(a){var b=null;if(!Ec[a]&&"undefined"!=typeof module&&module&&module.exports)try{b=Bc._abbr,require("./locale/"+a),u(b)}catch(c){}return Ec[a]}function u(a,b){var c;return a&&(c="undefined"==typeof b?w(a):v(a,b),c&&(Bc=c)),Bc._abbr}function v(a,b){return null!==b?(b.abbr=a,Ec[a]||(Ec[a]=new q),Ec[a].set(b),u(a),Ec[a]):(delete Ec[a],null)}function w(a){var b;if(a&&a._locale&&a._locale._abbr&&(a=a._locale._abbr),!a)return Bc;if(!d(a)){if(b=t(a))return b;a=[a]}return s(a)}function x(a,b){var c=a.toLowerCase();Fc[c]=Fc[c+"s"]=Fc[b]=a}function y(a){return"string"==typeof a?Fc[a]||Fc[a.toLowerCase()]:void 0}function z(a){var b,c,d={};for(c in a)g(a,c)&&(b=y(c),b&&(d[b]=a[c]));return d}function A(b,c){return function(d){return null!=d?(C(this,b,d),a.updateOffset(this,c),this):B(this,b)}}function B(a,b){return a._d["get"+(a._isUTC?"UTC":"")+b]()}function C(a,b,c){return a._d["set"+(a._isUTC?"UTC":"")+b](c)}function D(a,b){var c;if("object"==typeof a)for(c in a)this.set(c,a[c]);else if(a=y(a),"function"==typeof this[a])return this[a](b);return this}function E(a,b,c){for(var d=""+Math.abs(a),e=a>=0;d.length<b;)d="0"+d;return(e?c?"+":"":"-")+d}function F(a,b,c,d){var e=d;"string"==typeof d&&(e=function(){return this[d]()}),a&&(Jc[a]=e),b&&(Jc[b[0]]=function(){return E(e.apply(this,arguments),b[1],b[2])}),c&&(Jc[c]=function(){return this.localeData().ordinal(e.apply(this,arguments),a)})}function G(a){return a.match(/\[[\s\S]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function H(a){var b,c,d=a.match(Gc);for(b=0,c=d.length;c>b;b++)d[b]=Jc[d[b]]?Jc[d[b]]:G(d[b]);return function(e){var f="";for(b=0;c>b;b++)f+=d[b]instanceof Function?d[b].call(e,a):d[b];return f}}function I(a,b){return a.isValid()?(b=J(b,a.localeData()),Ic[b]||(Ic[b]=H(b)),Ic[b](a)):a.localeData().invalidDate()}function J(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(Hc.lastIndex=0;d>=0&&Hc.test(a);)a=a.replace(Hc,c),Hc.lastIndex=0,d-=1;return a}function K(a,b,c){Yc[a]="function"==typeof b?b:function(a){return a&&c?c:b}}function L(a,b){return g(Yc,a)?Yc[a](b._strict,b._locale):new RegExp(M(a))}function M(a){return a.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,d,e){return b||c||d||e}).replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function N(a,b){var c,d=b;for("string"==typeof a&&(a=[a]),"number"==typeof b&&(d=function(a,c){c[b]=o(a)}),c=0;c<a.length;c++)Zc[a[c]]=d}function O(a,b){N(a,function(a,c,d,e){d._w=d._w||{},b(a,d._w,d,e)})}function P(a,b,c){null!=b&&g(Zc,a)&&Zc[a](b,c._a,c,a)}function Q(a,b){return new Date(Date.UTC(a,b+1,0)).getUTCDate()}function R(a){return this._months[a.month()]}function S(a){return this._monthsShort[a.month()]}function T(a,b,c){var d,e,f;for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),d=0;12>d;d++){if(e=i([2e3,d]),c&&!this._longMonthsParse[d]&&(this._longMonthsParse[d]=new RegExp("^"+this.months(e,"").replace(".","")+"$","i"),this._shortMonthsParse[d]=new RegExp("^"+this.monthsShort(e,"").replace(".","")+"$","i")),c||this._monthsParse[d]||(f="^"+this.months(e,"")+"|^"+this.monthsShort(e,""),this._monthsParse[d]=new RegExp(f.replace(".",""),"i")),c&&"MMMM"===b&&this._longMonthsParse[d].test(a))return d;if(c&&"MMM"===b&&this._shortMonthsParse[d].test(a))return d;if(!c&&this._monthsParse[d].test(a))return d}}function U(a,b){var c;return"string"==typeof b&&(b=a.localeData().monthsParse(b),"number"!=typeof b)?a:(c=Math.min(a.date(),Q(a.year(),b)),a._d["set"+(a._isUTC?"UTC":"")+"Month"](b,c),a)}function V(b){return null!=b?(U(this,b),a.updateOffset(this,!0),this):B(this,"Month")}function W(){return Q(this.year(),this.month())}function X(a){var b,c=a._a;return c&&-2===a._pf.overflow&&(b=c[_c]<0||c[_c]>11?_c:c[ad]<1||c[ad]>Q(c[$c],c[_c])?ad:c[bd]<0||c[bd]>24||24===c[bd]&&(0!==c[cd]||0!==c[dd]||0!==c[ed])?bd:c[cd]<0||c[cd]>59?cd:c[dd]<0||c[dd]>59?dd:c[ed]<0||c[ed]>999?ed:-1,a._pf._overflowDayOfYear&&($c>b||b>ad)&&(b=ad),a._pf.overflow=b),a}function Y(b){a.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+b)}function Z(a,b){var c=!0;return h(function(){return c&&(Y(a),c=!1),b.apply(this,arguments)},b)}function $(a,b){hd[a]||(Y(b),hd[a]=!0)}function _(a){var b,c,d=a._i,e=id.exec(d);if(e){for(a._pf.iso=!0,b=0,c=jd.length;c>b;b++)if(jd[b][1].exec(d)){a._f=jd[b][0]+(e[6]||" ");break}for(b=0,c=kd.length;c>b;b++)if(kd[b][1].exec(d)){a._f+=kd[b][0];break}d.match(Vc)&&(a._f+="Z"),sa(a)}else a._isValid=!1}function aa(b){var c=ld.exec(b._i);return null!==c?void(b._d=new Date(+c[1])):(_(b),void(b._isValid===!1&&(delete b._isValid,a.createFromInputFallback(b))))}function ba(a,b,c,d,e,f,g){var h=new Date(a,b,c,d,e,f,g);return 1970>a&&h.setFullYear(a),h}function ca(a){var b=new Date(Date.UTC.apply(null,arguments));return 1970>a&&b.setUTCFullYear(a),b}function da(a){return ea(a)?366:365}function ea(a){return a%4===0&&a%100!==0||a%400===0}function fa(){return ea(this.year())}function ga(a,b,c){var d,e=c-b,f=c-a.day();return f>e&&(f-=7),e-7>f&&(f+=7),d=za(a).add(f,"d"),{week:Math.ceil(d.dayOfYear()/7),year:d.year()}}function ha(a){return ga(a,this._week.dow,this._week.doy).week}function ia(){return this._week.dow}function ja(){return this._week.doy}function ka(a){var b=this.localeData().week(this);return null==a?b:this.add(7*(a-b),"d")}function la(a){var b=ga(this,1,4).week;return null==a?b:this.add(7*(a-b),"d")}function ma(a,b,c,d,e){var f,g,h=ca(a,0,1).getUTCDay();return h=0===h?7:h,c=null!=c?c:e,f=e-h+(h>d?7:0)-(e>h?7:0),g=7*(b-1)+(c-e)+f+1,{year:g>0?a:a-1,dayOfYear:g>0?g:da(a-1)+g}}function na(a){var b=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==a?b:this.add(a-b,"d")}function oa(a,b,c){return null!=a?a:null!=b?b:c}function pa(a){var b=new Date;return a._useUTC?[b.getUTCFullYear(),b.getUTCMonth(),b.getUTCDate()]:[b.getFullYear(),b.getMonth(),b.getDate()]}function qa(a){var b,c,d,e,f=[];if(!a._d){for(d=pa(a),a._w&&null==a._a[ad]&&null==a._a[_c]&&ra(a),a._dayOfYear&&(e=oa(a._a[$c],d[$c]),a._dayOfYear>da(e)&&(a._pf._overflowDayOfYear=!0),c=ca(e,0,a._dayOfYear),a._a[_c]=c.getUTCMonth(),a._a[ad]=c.getUTCDate()),b=0;3>b&&null==a._a[b];++b)a._a[b]=f[b]=d[b];for(;7>b;b++)a._a[b]=f[b]=null==a._a[b]?2===b?1:0:a._a[b];24===a._a[bd]&&0===a._a[cd]&&0===a._a[dd]&&0===a._a[ed]&&(a._nextDay=!0,a._a[bd]=0),a._d=(a._useUTC?ca:ba).apply(null,f),null!=a._tzm&&a._d.setUTCMinutes(a._d.getUTCMinutes()-a._tzm),a._nextDay&&(a._a[bd]=24)}}function ra(a){var b,c,d,e,f,g,h;b=a._w,null!=b.GG||null!=b.W||null!=b.E?(f=1,g=4,c=oa(b.GG,a._a[$c],ga(za(),1,4).year),d=oa(b.W,1),e=oa(b.E,1)):(f=a._locale._week.dow,g=a._locale._week.doy,c=oa(b.gg,a._a[$c],ga(za(),f,g).year),d=oa(b.w,1),null!=b.d?(e=b.d,f>e&&++d):e=null!=b.e?b.e+f:f),h=ma(c,d,e,g,f),a._a[$c]=h.year,a._dayOfYear=h.dayOfYear}function sa(b){if(b._f===a.ISO_8601)return void _(b);b._a=[],b._pf.empty=!0;var c,d,e,f,g,h=""+b._i,i=h.length,j=0;for(e=J(b._f,b._locale).match(Gc)||[],c=0;c<e.length;c++)f=e[c],d=(h.match(L(f,b))||[])[0],d&&(g=h.substr(0,h.indexOf(d)),g.length>0&&b._pf.unusedInput.push(g),h=h.slice(h.indexOf(d)+d.length),j+=d.length),Jc[f]?(d?b._pf.empty=!1:b._pf.unusedTokens.push(f),P(f,d,b)):b._strict&&!d&&b._pf.unusedTokens.push(f);b._pf.charsLeftOver=i-j,h.length>0&&b._pf.unusedInput.push(h),b._pf.bigHour===!0&&b._a[bd]<=12&&(b._pf.bigHour=void 0),b._a[bd]=ta(b._locale,b._a[bd],b._meridiem),qa(b),X(b)}function ta(a,b,c){var d;return null==c?b:null!=a.meridiemHour?a.meridiemHour(b,c):null!=a.isPM?(d=a.isPM(c),d&&12>b&&(b+=12),d||12!==b||(b=0),b):b}function ua(a){var b,d,e,f,g;if(0===a._f.length)return a._pf.invalidFormat=!0,void(a._d=new Date(0/0));for(f=0;f<a._f.length;f++)g=0,b=l({},a),null!=a._useUTC&&(b._useUTC=a._useUTC),b._pf=c(),b._f=a._f[f],sa(b),j(b)&&(g+=b._pf.charsLeftOver,g+=10*b._pf.unusedTokens.length,b._pf.score=g,(null==e||e>g)&&(e=g,d=b));h(a,d||b)}function va(a){if(!a._d){var b=z(a._i);a._a=[b.year,b.month,b.day||b.date,b.hour,b.minute,b.second,b.millisecond],qa(a)}}function wa(a){var b,c=a._i,e=a._f;return a._locale=a._locale||w(a._l),null===c||void 0===e&&""===c?k({nullInput:!0}):("string"==typeof c&&(a._i=c=a._locale.preparse(c)),n(c)?new m(X(c)):(d(e)?ua(a):e?sa(a):xa(a),b=new m(X(a)),b._nextDay&&(b.add(1,"d"),b._nextDay=void 0),b))}function xa(b){var c=b._i;void 0===c?b._d=new Date:e(c)?b._d=new Date(+c):"string"==typeof c?aa(b):d(c)?(b._a=f(c.slice(0),function(a){return parseInt(a,10)}),qa(b)):"object"==typeof c?va(b):"number"==typeof c?b._d=new Date(c):a.createFromInputFallback(b)}function ya(a,b,d,e,f){var g={};return"boolean"==typeof d&&(e=d,d=void 0),g._isAMomentObject=!0,g._useUTC=g._isUTC=f,g._l=d,g._i=a,g._f=b,g._strict=e,g._pf=c(),wa(g)}function za(a,b,c,d){return ya(a,b,c,d,!1)}function Aa(a,b){var c,e;if(1===b.length&&d(b[0])&&(b=b[0]),!b.length)return za();for(c=b[0],e=1;e<b.length;++e)b[e][a](c)&&(c=b[e]);return c}function Ba(){var a=[].slice.call(arguments,0);return Aa("isBefore",a)}function Ca(){var a=[].slice.call(arguments,0);return Aa("isAfter",a)}function Da(a){var b=z(a),c=b.year||0,d=b.quarter||0,e=b.month||0,f=b.week||0,g=b.day||0,h=b.hour||0,i=b.minute||0,j=b.second||0,k=b.millisecond||0;this._milliseconds=+k+1e3*j+6e4*i+36e5*h,this._days=+g+7*f,this._months=+e+3*d+12*c,this._data={},this._locale=w(),this._bubble()}function Ea(a){return a instanceof Da}function Fa(a,b){F(a,0,0,function(){var a=this.utcOffset(),c="+";return 0>a&&(a=-a,c="-"),c+E(~~(a/60),2)+b+E(~~a%60,2)})}function Ga(a){var b=(a||"").match(Vc)||[],c=b[b.length-1]||[],d=(c+"").match(qd)||["-",0,0],e=+(60*d[1])+o(d[2]);return"+"===d[0]?e:-e}function Ha(b,c){var d,f;return c._isUTC?(d=c.clone(),f=(n(b)||e(b)?+b:+za(b))-+d,d._d.setTime(+d._d+f),a.updateOffset(d,!1),d):za(b).local();return c._isUTC?za(b).zone(c._offset||0):za(b).local()}function Ia(a){return 15*-Math.round(a._d.getTimezoneOffset()/15)}function Ja(b,c){var d,e=this._offset||0;return null!=b?("string"==typeof b&&(b=Ga(b)),Math.abs(b)<16&&(b=60*b),!this._isUTC&&c&&(d=Ia(this)),this._offset=b,this._isUTC=!0,null!=d&&this.add(d,"m"),e!==b&&(!c||this._changeInProgress?Za(this,Ua(b-e,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,a.updateOffset(this,!0),this._changeInProgress=null)),this):this._isUTC?e:Ia(this)}function Ka(a,b){return null!=a?("string"!=typeof a&&(a=-a),this.utcOffset(a,b),this):-this.utcOffset()}function La(a){return this.utcOffset(0,a)}function Ma(a){return this._isUTC&&(this.utcOffset(0,a),this._isUTC=!1,a&&this.subtract(Ia(this),"m")),this}function Na(){return this._tzm?this.utcOffset(this._tzm):"string"==typeof this._i&&this.utcOffset(Ga(this._i)),this}function Oa(a){return a=a?za(a).utcOffset():0,(this.utcOffset()-a)%60===0}function Pa(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function Qa(){if(this._a){var a=this._isUTC?i(this._a):za(this._a);return this.isValid()&&p(this._a,a.toArray())>0}return!1}function Ra(){return!this._isUTC}function Sa(){return this._isUTC}function Ta(){return this._isUTC&&0===this._offset}function Ua(a,b){var c,d,e,f=a,h=null;return Ea(a)?f={ms:a._milliseconds,d:a._days,M:a._months}:"number"==typeof a?(f={},b?f[b]=a:f.milliseconds=a):(h=rd.exec(a))?(c="-"===h[1]?-1:1,f={y:0,d:o(h[ad])*c,h:o(h[bd])*c,m:o(h[cd])*c,s:o(h[dd])*c,ms:o(h[ed])*c}):(h=sd.exec(a))?(c="-"===h[1]?-1:1,f={y:Va(h[2],c),M:Va(h[3],c),d:Va(h[4],c),h:Va(h[5],c),m:Va(h[6],c),s:Va(h[7],c),w:Va(h[8],c)}):null==f?f={}:"object"==typeof f&&("from"in f||"to"in f)&&(e=Xa(za(f.from),za(f.to)),f={},f.ms=e.milliseconds,f.M=e.months),d=new Da(f),Ea(a)&&g(a,"_locale")&&(d._locale=a._locale),d}function Va(a,b){var c=a&&parseFloat(a.replace(",","."));return(isNaN(c)?0:c)*b}function Wa(a,b){var c={milliseconds:0,months:0};return c.months=b.month()-a.month()+12*(b.year()-a.year()),a.clone().add(c.months,"M").isAfter(b)&&--c.months,c.milliseconds=+b-+a.clone().add(c.months,"M"),c}function Xa(a,b){var c;return b=Ha(b,a),a.isBefore(b)?c=Wa(a,b):(c=Wa(b,a),c.milliseconds=-c.milliseconds,c.months=-c.months),c}function Ya(a,b){return function(c,d){var e,f;return null===d||isNaN(+d)||($(b,"moment()."+b+"(period, number) is deprecated. Please use moment()."+b+"(number, period)."),f=c,c=d,d=f),c="string"==typeof c?+c:c,e=Ua(c,d),Za(this,e,a),this}}function Za(b,c,d,e){var f=c._milliseconds,g=c._days,h=c._months;e=null==e?!0:e,f&&b._d.setTime(+b._d+f*d),g&&C(b,"Date",B(b,"Date")+g*d),h&&U(b,B(b,"Month")+h*d),e&&a.updateOffset(b,g||h)}function $a(a){var b=a||za(),c=Ha(b,this).startOf("day"),d=this.diff(c,"days",!0),e=-6>d?"sameElse":-1>d?"lastWeek":0>d?"lastDay":1>d?"sameDay":2>d?"nextDay":7>d?"nextWeek":"sameElse";return this.format(this.localeData().calendar(e,this,za(b)))}function _a(){return new m(this)}function ab(a,b){var c;return b=y("undefined"!=typeof b?b:"millisecond"),"millisecond"===b?(a=n(a)?a:za(a),+this>+a):(c=n(a)?+a:+za(a),c<+this.clone().startOf(b))}function bb(a,b){var c;return b=y("undefined"!=typeof b?b:"millisecond"),"millisecond"===b?(a=n(a)?a:za(a),+a>+this):(c=n(a)?+a:+za(a),+this.clone().endOf(b)<c)}function cb(a,b,c){return this.isAfter(a,c)&&this.isBefore(b,c)}function db(a,b){var c;return b=y(b||"millisecond"),"millisecond"===b?(a=n(a)?a:za(a),+this===+a):(c=+za(a),+this.clone().startOf(b)<=c&&c<=+this.clone().endOf(b))}function eb(a){return 0>a?Math.ceil(a):Math.floor(a)}function fb(a,b,c){var d,e,f=Ha(a,this),g=6e4*(f.utcOffset()-this.utcOffset());return b=y(b),"year"===b||"month"===b||"quarter"===b?(e=gb(this,f),"quarter"===b?e/=3:"year"===b&&(e/=12)):(d=this-f,e="second"===b?d/1e3:"minute"===b?d/6e4:"hour"===b?d/36e5:"day"===b?(d-g)/864e5:"week"===b?(d-g)/6048e5:d),c?e:eb(e)}function gb(a,b){var c,d,e=12*(b.year()-a.year())+(b.month()-a.month()),f=a.clone().add(e,"months");return 0>b-f?(c=a.clone().add(e-1,"months"),d=(b-f)/(f-c)):(c=a.clone().add(e+1,"months"),d=(b-f)/(c-f)),-(e+d)}function hb(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")}function ib(){var a=this.clone().utc();return 0<a.year()&&a.year()<=9999?"function"==typeof Date.prototype.toISOString?this.toDate().toISOString():I(a,"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]"):I(a,"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]")}function jb(b){var c=I(this,b||a.defaultFormat);return this.localeData().postformat(c)}function kb(a,b){return Ua({to:this,from:a}).locale(this.locale()).humanize(!b)}function lb(a){return this.from(za(),a)}function mb(a){var b;return void 0===a?this._locale._abbr:(b=w(a),null!=b&&(this._locale=b),this)}function nb(){return this._locale}function ob(a){switch(a=y(a)){case"year":this.month(0);case"quarter":case"month":this.date(1);case"week":case"isoWeek":case"day":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return"week"===a&&this.weekday(0),"isoWeek"===a&&this.isoWeekday(1),"quarter"===a&&this.month(3*Math.floor(this.month()/3)),this}function pb(a){return a=y(a),void 0===a||"millisecond"===a?this:this.startOf(a).add(1,"isoWeek"===a?"week":a).subtract(1,"ms")}function qb(){return+this._d-6e4*(this._offset||0)}function rb(){return Math.floor(+this/1e3)}function sb(){return this._offset?new Date(+this):this._d}function tb(){var a=this;return[a.year(),a.month(),a.date(),a.hour(),a.minute(),a.second(),a.millisecond()]}function ub(){return j(this)}function vb(){return h({},this._pf)}function wb(){return this._pf.overflow}function xb(a,b){F(0,[a,a.length],0,b)}function yb(a,b,c){return ga(za([a,11,31+b-c]),b,c).week}function zb(a){var b=ga(this,this.localeData()._week.dow,this.localeData()._week.doy).year;return null==a?b:this.add(a-b,"y")}function Ab(a){var b=ga(this,1,4).year;return null==a?b:this.add(a-b,"y")}function Bb(){return yb(this.year(),1,4)}function Cb(){var a=this.localeData()._week;return yb(this.year(),a.dow,a.doy)}function Db(a){return null==a?Math.ceil((this.month()+1)/3):this.month(3*(a-1)+this.month()%3)}function Eb(a,b){if("string"==typeof a)if(isNaN(a)){if(a=b.weekdaysParse(a),"number"!=typeof a)return null}else a=parseInt(a,10);return a}function Fb(a){return this._weekdays[a.day()]}function Gb(a){return this._weekdaysShort[a.day()]}function Hb(a){return this._weekdaysMin[a.day()]}function Ib(a){var b,c,d;for(this._weekdaysParse||(this._weekdaysParse=[]),b=0;7>b;b++)if(this._weekdaysParse[b]||(c=za([2e3,1]).day(b),d="^"+this.weekdays(c,"")+"|^"+this.weekdaysShort(c,"")+"|^"+this.weekdaysMin(c,""),this._weekdaysParse[b]=new RegExp(d.replace(".",""),"i")),this._weekdaysParse[b].test(a))return b}function Jb(a){var b=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=a?(a=Eb(a,this.localeData()),this.add(a-b,"d")):b}function Kb(a){var b=(this.day()+7-this.localeData()._week.dow)%7;return null==a?b:this.add(a-b,"d")}function Lb(a){return null==a?this.day()||7:this.day(this.day()%7?a:a-7)}function Mb(a,b){F(a,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),b)})}function Nb(a,b){return b._meridiemParse}function Ob(a){return"p"===(a+"").toLowerCase().charAt(0)}function Pb(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"}function Qb(a){F(0,[a,3],0,"millisecond")}function Rb(){return this._isUTC?"UTC":""}function Sb(){return this._isUTC?"Coordinated Universal Time":""}function Tb(a){return za(1e3*a)}function Ub(){return za.apply(null,arguments).parseZone()}function Vb(a,b,c){var d=this._calendar[a];return"function"==typeof d?d.call(b,c):d}function Wb(a){var b=this._longDateFormat[a];return!b&&this._longDateFormat[a.toUpperCase()]&&(b=this._longDateFormat[a.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a]=b),b}function Xb(){return this._invalidDate}function Yb(a){return this._ordinal.replace("%d",a)}function Zb(a){return a}function $b(a,b,c,d){var e=this._relativeTime[c];return"function"==typeof e?e(a,b,c,d):e.replace(/%d/i,a)}function _b(a,b){var c=this._relativeTime[a>0?"future":"past"];return"function"==typeof c?c(b):c.replace(/%s/i,b)}function ac(a){var b,c;for(c in a)b=a[c],"function"==typeof b?this[c]=b:this["_"+c]=b;this._ordinalParseLenient=new RegExp(this._ordinalParse.source+"|"+/\d{1,2}/.source)}function bc(a,b,c,d){var e=w(),f=i().set(d,b);return e[c](f,a)}function cc(a,b,c,d,e){if("number"==typeof a&&(b=a,a=void 0),a=a||"",null!=b)return bc(a,b,c,e);var f,g=[];for(f=0;d>f;f++)g[f]=bc(a,f,c,e);return g}function dc(a,b){return cc(a,b,"months",12,"month")}function ec(a,b){return cc(a,b,"monthsShort",12,"month")}function fc(a,b){return cc(a,b,"weekdays",7,"day")}function gc(a,b){return cc(a,b,"weekdaysShort",7,"day")}function hc(a,b){return cc(a,b,"weekdaysMin",7,"day")}function ic(){var a=this._data;return this._milliseconds=Od(this._milliseconds),this._days=Od(this._days),this._months=Od(this._months),a.milliseconds=Od(a.milliseconds),a.seconds=Od(a.seconds),a.minutes=Od(a.minutes),a.hours=Od(a.hours),a.months=Od(a.months),a.years=Od(a.years),this}function jc(a,b,c,d){var e=Ua(b,c);return a._milliseconds+=d*e._milliseconds,a._days+=d*e._days,a._months+=d*e._months,a._bubble()}function kc(a,b){return jc(this,a,b,1)}function lc(a,b){return jc(this,a,b,-1)}function mc(){var a,b,c,d=this._milliseconds,e=this._days,f=this._months,g=this._data,h=0;return g.milliseconds=d%1e3,a=eb(d/1e3),g.seconds=a%60,b=eb(a/60),g.minutes=b%60,c=eb(b/60),g.hours=c%24,e+=eb(c/24),h=eb(nc(e)),e-=eb(oc(h)),f+=eb(e/30),e%=30,h+=eb(f/12),f%=12,g.days=e,g.months=f,g.years=h,this}function nc(a){return 400*a/146097}function oc(a){return 146097*a/400}function pc(a){var b,c,d=this._milliseconds;if(a=y(a),"month"===a||"year"===a)return b=this._days+d/864e5,c=this._months+12*nc(b),"month"===a?c:c/12;switch(b=this._days+Math.round(oc(this._months/12)),a){case"week":return b/7+d/6048e5;case"day":return b+d/864e5;case"hour":return 24*b+d/36e5;case"minute":return 24*b*60+d/6e4;case"second":return 24*b*60*60+d/1e3;case"millisecond":return Math.floor(24*b*60*60*1e3)+d;default:throw new Error("Unknown unit "+a)}}function qc(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*o(this._months/12)}function rc(a){return function(){return this.as(a)}}function sc(a){return a=y(a),this[a+"s"]()}function tc(a){return function(){return this._data[a]}}function uc(){return eb(this.days()/7)}function vc(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function wc(a,b,c){var d=Ua(a).abs(),e=ce(d.as("s")),f=ce(d.as("m")),g=ce(d.as("h")),h=ce(d.as("d")),i=ce(d.as("M")),j=ce(d.as("y")),k=e<de.s&&["s",e]||1===f&&["m"]||f<de.m&&["mm",f]||1===g&&["h"]||g<de.h&&["hh",g]||1===h&&["d"]||h<de.d&&["dd",h]||1===i&&["M"]||i<de.M&&["MM",i]||1===j&&["y"]||["yy",j];return k[2]=b,k[3]=+a>0,k[4]=c,vc.apply(null,k)}function xc(a,b){return void 0===de[a]?!1:void 0===b?de[a]:(de[a]=b,!0)}function yc(a){var b=this.localeData(),c=wc(this,!a,b);return a&&(c=b.pastFuture(+this,c)),b.postformat(c)}function zc(){var a=ee(this.years()),b=ee(this.months()),c=ee(this.days()),d=ee(this.hours()),e=ee(this.minutes()),f=ee(this.seconds()+this.milliseconds()/1e3),g=this.asSeconds();return g?(0>g?"-":"")+"P"+(a?a+"Y":"")+(b?b+"M":"")+(c?c+"D":"")+(d||e||f?"T":"")+(d?d+"H":"")+(e?e+"M":"")+(f?f+"S":""):"P0D"}var Ac,Bc,Cc=a.momentProperties=[],Dc=!1,Ec={},Fc={},Gc=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|x|X|zz?|ZZ?|.)/g,Hc=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,Ic={},Jc={},Kc=/\d/,Lc=/\d\d/,Mc=/\d{3}/,Nc=/\d{4}/,Oc=/[+-]?\d{6}/,Pc=/\d\d?/,Qc=/\d{1,3}/,Rc=/\d{1,4}/,Sc=/[+-]?\d{1,6}/,Tc=/\d+/,Uc=/[+-]?\d+/,Vc=/Z|[+-]\d\d:?\d\d/gi,Wc=/[+-]?\d+(\.\d{1,3})?/,Xc=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,Yc={},Zc={},$c=0,_c=1,ad=2,bd=3,cd=4,dd=5,ed=6;F("M",["MM",2],"Mo",function(){return this.month()+1}),F("MMM",0,0,function(a){return this.localeData().monthsShort(this,a)}),F("MMMM",0,0,function(a){return this.localeData().months(this,a)}),x("month","M"),K("M",Pc),K("MM",Pc,Lc),K("MMM",Xc),K("MMMM",Xc),N(["M","MM"],function(a,b){b[_c]=o(a)-1}),N(["MMM","MMMM"],function(a,b,c,d){var e=c._locale.monthsParse(a,d,c._strict);null!=e?b[_c]=e:c._pf.invalidMonth=a});var fd="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),gd="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),hd={};a.suppressDeprecationWarnings=!1;var id=/^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,jd=[["YYYYYY-MM-DD",/[+-]\d{6}-\d{2}-\d{2}/],["YYYY-MM-DD",/\d{4}-\d{2}-\d{2}/],["GGGG-[W]WW-E",/\d{4}-W\d{2}-\d/],["GGGG-[W]WW",/\d{4}-W\d{2}/],["YYYY-DDD",/\d{4}-\d{3}/]],kd=[["HH:mm:ss.SSSS",/(T| )\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss",/(T| )\d\d:\d\d:\d\d/],["HH:mm",/(T| )\d\d:\d\d/],["HH",/(T| )\d\d/]],ld=/^\/?Date\((\-?\d+)/i;a.createFromInputFallback=Z("moment construction falls back to js Date. This is discouraged and will be removed in upcoming major release. Please refer to https://github.com/moment/moment/issues/1407 for more info.",function(a){a._d=new Date(a._i+(a._useUTC?" UTC":""))}),F(0,["YY",2],0,function(){return this.year()%100}),F(0,["YYYY",4],0,"year"),F(0,["YYYYY",5],0,"year"),F(0,["YYYYYY",6,!0],0,"year"),x("year","y"),K("Y",Uc),K("YY",Pc,Lc),K("YYYY",Rc,Nc),K("YYYYY",Sc,Oc),K("YYYYYY",Sc,Oc),N(["YYYY","YYYYY","YYYYYY"],$c),N("YY",function(b,c){c[$c]=a.parseTwoDigitYear(b)}),a.parseTwoDigitYear=function(a){return o(a)+(o(a)>68?1900:2e3)};var md=A("FullYear",!1);F("w",["ww",2],"wo","week"),F("W",["WW",2],"Wo","isoWeek"),x("week","w"),x("isoWeek","W"),K("w",Pc),K("ww",Pc,Lc),K("W",Pc),K("WW",Pc,Lc),O(["w","ww","W","WW"],function(a,b,c,d){b[d.substr(0,1)]=o(a)});var nd={dow:0,doy:6};F("DDD",["DDDD",3],"DDDo","dayOfYear"),x("dayOfYear","DDD"),K("DDD",Qc),K("DDDD",Mc),N(["DDD","DDDD"],function(a,b,c){c._dayOfYear=o(a)}),a.ISO_8601=function(){};var od=Z("moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548",function(){var a=za.apply(null,arguments);return this>a?this:a}),pd=Z("moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548",function(){var a=za.apply(null,arguments);return a>this?this:a});Fa("Z",":"),Fa("ZZ",""),K("Z",Vc),K("ZZ",Vc),N(["Z","ZZ"],function(a,b,c){c._useUTC=!0,c._tzm=Ga(a)});var qd=/([\+\-]|\d\d)/gi;a.updateOffset=function(){};var rd=/(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,sd=/^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/;Ua.fn=Da.prototype;var td=Ya(1,"add"),ud=Ya(-1,"subtract");a.defaultFormat="YYYY-MM-DDTHH:mm:ssZ";var vd=Z("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(a){return void 0===a?this.localeData():this.locale(a)});F(0,["gg",2],0,function(){return this.weekYear()%100}),F(0,["GG",2],0,function(){return this.isoWeekYear()%100}),xb("gggg","weekYear"),xb("ggggg","weekYear"),xb("GGGG","isoWeekYear"),xb("GGGGG","isoWeekYear"),x("weekYear","gg"),x("isoWeekYear","GG"),K("G",Uc),K("g",Uc),K("GG",Pc,Lc),K("gg",Pc,Lc),K("GGGG",Rc,Nc),K("gggg",Rc,Nc),K("GGGGG",Sc,Oc),K("ggggg",Sc,Oc),O(["gggg","ggggg","GGGG","GGGGG"],function(a,b,c,d){b[d.substr(0,2)]=o(a)}),O(["gg","GG"],function(b,c,d,e){c[e]=a.parseTwoDigitYear(b)}),F("Q",0,0,"quarter"),x("quarter","Q"),K("Q",Kc),N("Q",function(a,b){b[_c]=3*(o(a)-1)}),F("D",["DD",2],"Do","date"),x("date","D"),K("D",Pc),K("DD",Pc,Lc),K("Do",function(a,b){return a?b._ordinalParse:b._ordinalParseLenient}),N(["D","DD"],ad),N("Do",function(a,b){b[ad]=o(a.match(Pc)[0],10)});var wd=A("Date",!0);F("d",0,"do","day"),F("dd",0,0,function(a){return this.localeData().weekdaysMin(this,a)}),F("ddd",0,0,function(a){return this.localeData().weekdaysShort(this,a)}),F("dddd",0,0,function(a){return this.localeData().weekdays(this,a)}),F("e",0,0,"weekday"),F("E",0,0,"isoWeekday"),x("day","d"),x("weekday","e"),x("isoWeekday","E"),K("d",Pc),K("e",Pc),K("E",Pc),K("dd",Xc),K("ddd",Xc),K("dddd",Xc),O(["dd","ddd","dddd"],function(a,b,c){var d=c._locale.weekdaysParse(a);null!=d?b.d=d:c._pf.invalidWeekday=a}),O(["d","e","E"],function(a,b,c,d){b[d]=o(a)});var xd="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),yd="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),zd="Su_Mo_Tu_We_Th_Fr_Sa".split("_");F("H",["HH",2],0,"hour"),F("h",["hh",2],0,function(){return this.hours()%12||12}),Mb("a",!0),Mb("A",!1),x("hour","h"),K("a",Nb),K("A",Nb),K("H",Pc),K("h",Pc),K("HH",Pc,Lc),K("hh",Pc,Lc),N(["H","HH"],bd),N(["a","A"],function(a,b,c){c._isPm=c._locale.isPM(a),c._meridiem=a}),N(["h","hh"],function(a,b,c){b[bd]=o(a),c._pf.bigHour=!0});var Ad=/[ap]\.?m?\.?/i,Bd=A("Hours",!0);F("m",["mm",2],0,"minute"),x("minute","m"),K("m",Pc),K("mm",Pc,Lc),N(["m","mm"],cd);var Cd=A("Minutes",!1);F("s",["ss",2],0,"second"),x("second","s"),K("s",Pc),K("ss",Pc,Lc),N(["s","ss"],dd);var Dd=A("Seconds",!1);F("S",0,0,function(){return~~(this.millisecond()/100)}),F(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),Qb("SSS"),Qb("SSSS"),x("millisecond","ms"),K("S",Qc,Kc),K("SS",Qc,Lc),K("SSS",Qc,Mc),K("SSSS",Tc),N(["S","SS","SSS","SSSS"],function(a,b){b[ed]=o(1e3*("0."+a))});var Ed=A("Milliseconds",!1);F("z",0,0,"zoneAbbr"),F("zz",0,0,"zoneName");var Fd=m.prototype;Fd.add=td,Fd.calendar=$a,Fd.clone=_a,Fd.diff=fb,Fd.endOf=pb,Fd.format=jb,Fd.from=kb,Fd.fromNow=lb,Fd.get=D,Fd.invalidAt=wb,Fd.isAfter=ab,Fd.isBefore=bb,Fd.isBetween=cb,Fd.isSame=db,Fd.isValid=ub,Fd.lang=vd,Fd.locale=mb,Fd.localeData=nb,Fd.max=pd,Fd.min=od,Fd.parsingFlags=vb,Fd.set=D,Fd.startOf=ob,Fd.subtract=ud,Fd.toArray=tb,Fd.toDate=sb,Fd.toISOString=ib,Fd.toJSON=ib,Fd.toString=hb,Fd.unix=rb,Fd.valueOf=qb,Fd.year=md,Fd.isLeapYear=fa,Fd.weekYear=zb,Fd.isoWeekYear=Ab,Fd.quarter=Fd.quarters=Db,Fd.month=V,Fd.daysInMonth=W,Fd.week=Fd.weeks=ka,Fd.isoWeek=Fd.isoWeeks=la,Fd.weeksInYear=Cb,Fd.isoWeeksInYear=Bb,Fd.date=wd,Fd.day=Fd.days=Jb,Fd.weekday=Kb,Fd.isoWeekday=Lb,Fd.dayOfYear=na,Fd.hour=Fd.hours=Bd,Fd.minute=Fd.minutes=Cd,Fd.second=Fd.seconds=Dd,Fd.millisecond=Fd.milliseconds=Ed,Fd.utcOffset=Ja,Fd.utc=La,Fd.local=Ma,Fd.parseZone=Na,Fd.hasAlignedHourOffset=Oa,Fd.isDST=Pa,Fd.isDSTShifted=Qa,Fd.isLocal=Ra,Fd.isUtcOffset=Sa,Fd.isUtc=Ta,Fd.isUTC=Ta,Fd.zoneAbbr=Rb,Fd.zoneName=Sb,Fd.dates=Z("dates accessor is deprecated. Use date instead.",wd),Fd.months=Z("months accessor is deprecated. Use month instead",V),Fd.years=Z("years accessor is deprecated. Use year instead",md),Fd.zone=Z("moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779",Ka);var Gd=Fd,Hd={sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},Id={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY LT",LLLL:"dddd, MMMM D, YYYY LT"},Jd="Invalid date",Kd="%d",Ld=/\d{1,2}/,Md={future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},Nd=q.prototype;Nd._calendar=Hd,Nd.calendar=Vb,Nd._longDateFormat=Id,Nd.longDateFormat=Wb,Nd._invalidDate=Jd,Nd.invalidDate=Xb,Nd._ordinal=Kd,Nd.ordinal=Yb,Nd._ordinalParse=Ld,
|
7
|
+
Nd.preparse=Zb,Nd.postformat=Zb,Nd._relativeTime=Md,Nd.relativeTime=$b,Nd.pastFuture=_b,Nd.set=ac,Nd.months=R,Nd._months=fd,Nd.monthsShort=S,Nd._monthsShort=gd,Nd.monthsParse=T,Nd.week=ha,Nd._week=nd,Nd.firstDayOfYear=ja,Nd.firstDayOfWeek=ia,Nd.weekdays=Fb,Nd._weekdays=xd,Nd.weekdaysMin=Hb,Nd._weekdaysMin=zd,Nd.weekdaysShort=Gb,Nd._weekdaysShort=yd,Nd.weekdaysParse=Ib,Nd.isPM=Ob,Nd._meridiemParse=Ad,Nd.meridiem=Pb,u("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(a){var b=a%10,c=1===o(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}}),a.lang=Z("moment.lang is deprecated. Use moment.locale instead.",u),a.langData=Z("moment.langData is deprecated. Use moment.localeData instead.",w);var Od=Math.abs,Pd=rc("ms"),Qd=rc("s"),Rd=rc("m"),Sd=rc("h"),Td=rc("d"),Ud=rc("w"),Vd=rc("M"),Wd=rc("y"),Xd=tc("milliseconds"),Yd=tc("seconds"),Zd=tc("minutes"),$d=tc("hours"),_d=tc("days"),ae=tc("months"),be=tc("years"),ce=Math.round,de={s:45,m:45,h:22,d:26,M:11},ee=Math.abs,fe=Da.prototype;fe.abs=ic,fe.add=kc,fe.subtract=lc,fe.as=pc,fe.asMilliseconds=Pd,fe.asSeconds=Qd,fe.asMinutes=Rd,fe.asHours=Sd,fe.asDays=Td,fe.asWeeks=Ud,fe.asMonths=Vd,fe.asYears=Wd,fe.valueOf=qc,fe._bubble=mc,fe.get=sc,fe.milliseconds=Xd,fe.seconds=Yd,fe.minutes=Zd,fe.hours=$d,fe.days=_d,fe.weeks=uc,fe.months=ae,fe.years=be,fe.humanize=yc,fe.toISOString=zc,fe.toString=zc,fe.toJSON=zc,fe.locale=mb,fe.localeData=nb,fe.toIsoString=Z("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",zc),fe.lang=vd,F("X",0,0,"unix"),F("x",0,0,"valueOf"),K("x",Uc),K("X",Wc),N("X",function(a,b,c){c._d=new Date(1e3*parseFloat(a,10))}),N("x",function(a,b,c){c._d=new Date(o(a))}),a.version="2.10.2",b(za),a.fn=Gd,a.min=Ba,a.max=Ca,a.utc=i,a.unix=Tb,a.months=dc,a.isDate=e,a.locale=u,a.invalid=k,a.duration=Ua,a.isMoment=n,a.weekdays=fc,a.parseZone=Ub,a.localeData=w,a.isDuration=Ea,a.monthsShort=ec,a.weekdaysMin=hc,a.defineLocale=v,a.weekdaysShort=gc,a.normalizeUnits=y,a.relativeTimeThreshold=xc;var ge=a;return ge});
|
@@ -0,0 +1,22 @@
|
|
1
|
+
- initial_messages ||= 10
|
2
|
+
- messages = WiserChatMessage.where(channel: channel).limit(initial_messages)
|
3
|
+
|
4
|
+
#wiser-chat{data: {uri: "#{request.host}:3245/websocket", channel: channel}}
|
5
|
+
#chat-content.row
|
6
|
+
.col-sm-12
|
7
|
+
#chat-messages
|
8
|
+
- messages.each do |message|
|
9
|
+
.message
|
10
|
+
%span.label.label-default= message.created_at.in_time_zone("Asia/Taipei").strftime("%l:%M:%S %P")
|
11
|
+
%b= message.user.name
|
12
|
+
= message.content
|
13
|
+
#chat-info.row
|
14
|
+
.col-sm-7
|
15
|
+
.form-group.string.hidden
|
16
|
+
= text_field_tag :name, current_user.name, placeholder: "Your Name", class: "string optional form-control", data: {id: current_user.id, channel: channel}
|
17
|
+
.form-group.text
|
18
|
+
= text_area_tag :message, "", placeholder: "Write your message here...", class: "text optional input-md form-control"
|
19
|
+
%button#send.btn.btn-primary.hidden Send
|
20
|
+
.col-sm-5
|
21
|
+
%b= "Online Users"
|
22
|
+
#chat-users
|
@@ -0,0 +1,42 @@
|
|
1
|
+
#wiser-chat {
|
2
|
+
display: none;
|
3
|
+
width: 500px;
|
4
|
+
border: 1px solid #ccc;
|
5
|
+
background: #fdfdfd;
|
6
|
+
position: fixed;
|
7
|
+
top: 0;
|
8
|
+
height: 450px;
|
9
|
+
right: 0;
|
10
|
+
margin-top: 51px;
|
11
|
+
z-index: 999;
|
12
|
+
padding: 20px;
|
13
|
+
}
|
14
|
+
#wiser-chat #chat-info {
|
15
|
+
margin-top: 10px;
|
16
|
+
}
|
17
|
+
#wiser-chat #chat-content {
|
18
|
+
height: 300px;
|
19
|
+
overflow-x: scroll;
|
20
|
+
border: 1px solid #eee;
|
21
|
+
padding: 10px 0;
|
22
|
+
margin: 0;
|
23
|
+
}
|
24
|
+
#wiser-chat #chat-content #chat-messages .message {
|
25
|
+
padding: 5px 0 !important;
|
26
|
+
min-height: 25px;
|
27
|
+
border-bottom: 1px solid #eee;
|
28
|
+
line-height: 1.1em;
|
29
|
+
}
|
30
|
+
#wiser-chat #chat-content #chat-messages .message .label {
|
31
|
+
margin-top: 0px;
|
32
|
+
display: inline-block;
|
33
|
+
float: right;
|
34
|
+
margin-left: 15px;
|
35
|
+
}
|
36
|
+
#wiser-chat #chat-content #chat-messages .message .system_message {
|
37
|
+
color: #aaa;
|
38
|
+
font-style: italic;
|
39
|
+
}
|
40
|
+
#wiser-chat .hidden {
|
41
|
+
display: none;
|
42
|
+
}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'generators/wiser_chat'
|
2
|
+
require 'rails/generators/active_record'
|
3
|
+
|
4
|
+
module WiserChat
|
5
|
+
module Generators
|
6
|
+
# Migration generator that creates migration file from template
|
7
|
+
class MigrationGenerator < ActiveRecord::Generators::Base
|
8
|
+
extend Base
|
9
|
+
argument :name, :type => :string, :default => 'create_wiser_chat_messages'
|
10
|
+
# Create migration in project's folder
|
11
|
+
def generate_files
|
12
|
+
migration_template 'migration.rb', "db/migrate/#{name}.rb"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class CreateWiserChatMessages < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :wiser_chat_messages do |t|
|
4
|
+
t.references :user, index: true
|
5
|
+
t.text :channel
|
6
|
+
t.text :content
|
7
|
+
|
8
|
+
t.timestamps null: false
|
9
|
+
end
|
10
|
+
add_foreign_key :messages, :users
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'rails/generators/named_base'
|
2
|
+
|
3
|
+
module WiserChat
|
4
|
+
module Generators
|
5
|
+
module Base
|
6
|
+
# Get path for migration template
|
7
|
+
def source_root
|
8
|
+
@_wiser_chat_source_root ||= File.expand_path(File.join('../wiser_chat', generator_name, 'templates'), __FILE__)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/lib/wiser_chat.rb
ADDED
data/wiser_chat.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'wiser_chat/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "wiser_chat"
|
8
|
+
s.version = WiserChat::VERSION
|
9
|
+
s.authors = ["Kenneth John Balgos"]
|
10
|
+
s.email = ["kennethjohnbalgos@gmail.com"]
|
11
|
+
s.description = "Enable real-time chat easily in your Ruby on Rails application."
|
12
|
+
s.summary = "Awesome chat on fire!"
|
13
|
+
s.homepage = "https://github.com/kennethjohnbalgos/wiser_chat"
|
14
|
+
s.license = "MIT"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split($/)
|
17
|
+
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
s.test_files = s.files.grep(%r{^(test|s|features)/})
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_dependency "redis", "3.2.0"
|
22
|
+
s.add_dependency "websocket-rails", "0.7.0"
|
23
|
+
|
24
|
+
s.post_install_message = "Welcome to WiserChat v#{WiserChat::VERSION}!"
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: wiser_chat
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kenneth John Balgos
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-05-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: redis
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 3.2.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 3.2.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: websocket-rails
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.7.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.7.0
|
41
|
+
description: Enable real-time chat easily in your Ruby on Rails application.
|
42
|
+
email:
|
43
|
+
- kennethjohnbalgos@gmail.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- ".gitignore"
|
49
|
+
- Gemfile
|
50
|
+
- LICENSE.txt
|
51
|
+
- README.md
|
52
|
+
- Rakefile
|
53
|
+
- lib/generators/wiser_chat.rb
|
54
|
+
- lib/generators/wiser_chat/install/install_generator.rb
|
55
|
+
- lib/generators/wiser_chat/install/templates/controller.rb
|
56
|
+
- lib/generators/wiser_chat/install/templates/events.rb
|
57
|
+
- lib/generators/wiser_chat/install/templates/helper.rb
|
58
|
+
- lib/generators/wiser_chat/install/templates/javascript.js
|
59
|
+
- lib/generators/wiser_chat/install/templates/migration.rb
|
60
|
+
- lib/generators/wiser_chat/install/templates/model.rb
|
61
|
+
- lib/generators/wiser_chat/install/templates/moment.js
|
62
|
+
- lib/generators/wiser_chat/install/templates/partial.html.haml
|
63
|
+
- lib/generators/wiser_chat/install/templates/stylesheet.css
|
64
|
+
- lib/generators/wiser_chat/install/templates/websocket.rb
|
65
|
+
- lib/generators/wiser_chat/migration/migration_generator.rb
|
66
|
+
- lib/generators/wiser_chat/migration/templates/migration.rb
|
67
|
+
- lib/wiser_chat.rb
|
68
|
+
- lib/wiser_chat/engine.rb
|
69
|
+
- lib/wiser_chat/version.rb
|
70
|
+
- wiser_chat.gemspec
|
71
|
+
homepage: https://github.com/kennethjohnbalgos/wiser_chat
|
72
|
+
licenses:
|
73
|
+
- MIT
|
74
|
+
metadata: {}
|
75
|
+
post_install_message: Welcome to WiserChat v0.1.0!
|
76
|
+
rdoc_options: []
|
77
|
+
require_paths:
|
78
|
+
- lib
|
79
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
requirements: []
|
90
|
+
rubyforge_project:
|
91
|
+
rubygems_version: 2.2.2
|
92
|
+
signing_key:
|
93
|
+
specification_version: 4
|
94
|
+
summary: Awesome chat on fire!
|
95
|
+
test_files: []
|
96
|
+
has_rdoc:
|