├── .gitignore
├── README.md
├── __init__.py
├── data
└── pull_data.sh
├── data_utils.py
├── env_setup.sh
├── execute.py
├── neuralconvo.ini
├── seq2seq.ini
├── seq2seq_model.py
├── seq2seq_serve.ini
├── ui
├── .gitignore
├── README.md
├── __init.py__
├── app.py
├── requirements.txt
├── setup.sh
├── static
│ ├── css
│ │ ├── normalize.css
│ │ └── style.css
│ ├── js
│ │ ├── index.js
│ │ ├── jquery-latest.js
│ │ ├── jquery.mCustomScrollbar.concat.min.js
│ │ ├── jquery.mCustomScrollbar.min.css
│ │ └── jquery.min.js
│ ├── res
│ │ ├── botim.png
│ │ ├── hd1.jpg
│ │ └── hd2.jpg
│ └── scss
│ │ └── style.scss
└── templates
│ └── index.html
└── working_dir
├── vocab20000.dec
└── vocab20000.enc
/.gitignore:
--------------------------------------------------------------------------------
1 | data/
2 | *.pyc
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # easy\_seq2seq
2 |
3 | 
4 |
5 | * Go to [*practical_seq2seq*](https://github.com/suriyadeepan/practical_seq2seq)
6 |
7 | An implementation of Seq2Seq that actually works. I want to make it easy for people to train their own seq2seq model with any corpus. I am also adding the parameters of my trained model for people to just use it without training. If you have a model that works share your model params here, as external link or do a pull request. I have used Cornell Movie Dialog Corpus to train my model. A link to preprocessed data and scripts for preprocessing can be found in this repo.
8 |
9 | *Have Fun!*
10 |
11 | ## Update 1.1.2017
12 |
13 |
14 | I have created another repository - [practical_seq2seq](https://github.com/suriyadeepan/practical_seq2seq) to experiment with the seq2seq model. The new model trained on Twitter chat log and Cornell Movie Dialog corpus performs well. I wrote an article - [Practical seq2seq](http://suriyadeepan.github.io/2016-12-31-practical-seq2seq/), explaining the code.
15 |
16 | Happy New Year, **2017**
17 |
18 |
19 | ## Setup
20 |
21 |
22 | * Create temporary working directory prior to training
23 |
24 | ```bash
25 | mkdir working_dir
26 | ```
27 |
28 | * Download test/train data from Cornell Movie Dialog Corpus
29 |
30 | ```bash
31 | cd data/
32 | bash pull_data.sh
33 | ```
34 |
35 | ## Training
36 |
37 | ```bash
38 | # edit seq2seq.ini file to set
39 | # mode = train
40 | python execute.py
41 | # or use custom ini file
42 | # python execute.py my_custom_conf.ini
43 | ```
44 |
45 | ## Testing
46 |
47 | ```bash
48 | # edit seq2seq.ini file to set
49 | # mode = test
50 | python execute.py
51 | ```
52 |
53 | ## Serve
54 |
55 | ```bash
56 | # configuration : seq2seq_serve.ini
57 | python ui/app.py
58 | # wait until this message shows up
59 | # "Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)"
60 | # open up the address in browser, chat with the bot
61 | ```
62 |
--------------------------------------------------------------------------------
/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/suriyadeepan/easy_seq2seq/c05b0d02f15e9bd1947ff79ddcd0b761a214e2a9/__init__.py
--------------------------------------------------------------------------------
/data/pull_data.sh:
--------------------------------------------------------------------------------
1 | wget -c 'https://www.dropbox.com/s/ncfa5t950gvtaeb/test.enc?dl=0' -O test.enc
2 | wget -c 'https://www.dropbox.com/s/48ro4759jaikque/test.dec?dl=0' -O test.dec
3 | wget -c 'https://www.dropbox.com/s/gu54ngk3xpwite4/train.enc?dl=0' -O train.enc
4 | wget -c 'https://www.dropbox.com/s/g3z2msjziqocndl/train.dec?dl=0' -O train.dec
5 |
--------------------------------------------------------------------------------
/data_utils.py:
--------------------------------------------------------------------------------
1 | # Copyright 2015 The TensorFlow Authors. All Rights Reserved.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | # ==============================================================================
15 |
16 | """Utilities for downloading data from WMT, tokenizing, vocabularies."""
17 | from __future__ import absolute_import
18 | from __future__ import division
19 | from __future__ import print_function
20 |
21 | import os
22 | import re
23 |
24 | from six.moves import urllib
25 |
26 | from tensorflow.python.platform import gfile
27 |
28 | # Special vocabulary symbols - we always put them at the start.
29 | _PAD = b"_PAD"
30 | _GO = b"_GO"
31 | _EOS = b"_EOS"
32 | _UNK = b"_UNK"
33 | _START_VOCAB = [_PAD, _GO, _EOS, _UNK]
34 |
35 | PAD_ID = 0
36 | GO_ID = 1
37 | EOS_ID = 2
38 | UNK_ID = 3
39 |
40 | # Regular expressions used to tokenize.
41 | _WORD_SPLIT = re.compile(b"([.,!?\"':;)(])")
42 | _DIGIT_RE = re.compile(br"\d")
43 |
44 |
45 |
46 | def basic_tokenizer(sentence):
47 | """Very basic tokenizer: split the sentence into a list of tokens."""
48 | words = []
49 | for space_separated_fragment in sentence.strip().split():
50 | if isinstance(space_separated_fragment, str):
51 | word = str.encode(space_separated_fragment)
52 | else:
53 | word = space_separated_fragment
54 | words.extend(re.split(_WORD_SPLIT, word))
55 | return [w for w in words if w]
56 |
57 |
58 | def create_vocabulary(vocabulary_path, data_path, max_vocabulary_size,
59 | tokenizer=None, normalize_digits=True):
60 |
61 | if not gfile.Exists(vocabulary_path):
62 | print("Creating vocabulary %s from %s" % (vocabulary_path, data_path))
63 | vocab = {}
64 | with gfile.GFile(data_path, mode="rb") as f:
65 | counter = 0
66 | for line in f:
67 | counter += 1
68 | if counter % 100000 == 0:
69 | print(" processing line %d" % counter)
70 | tokens = tokenizer(line) if tokenizer else basic_tokenizer(line)
71 | for w in tokens:
72 | word = re.sub(_DIGIT_RE, b"0", w) if normalize_digits else w
73 | if word in vocab:
74 | vocab[word] += 1
75 | else:
76 | vocab[word] = 1
77 | vocab_list = _START_VOCAB + sorted(vocab, key=vocab.get, reverse=True)
78 | print('>> Full Vocabulary Size :',len(vocab_list))
79 | if len(vocab_list) > max_vocabulary_size:
80 | vocab_list = vocab_list[:max_vocabulary_size]
81 | with gfile.GFile(vocabulary_path, mode="wb") as vocab_file:
82 | for w in vocab_list:
83 | vocab_file.write(w + b"\n")
84 |
85 |
86 | def initialize_vocabulary(vocabulary_path):
87 |
88 | if gfile.Exists(vocabulary_path):
89 | rev_vocab = []
90 | with gfile.GFile(vocabulary_path, mode="rb") as f:
91 | rev_vocab.extend(f.readlines())
92 | rev_vocab = [line.strip() for line in rev_vocab]
93 | vocab = dict([(x, y) for (y, x) in enumerate(rev_vocab)])
94 | return vocab, rev_vocab
95 | else:
96 | raise ValueError("Vocabulary file %s not found.", vocabulary_path)
97 |
98 |
99 | def sentence_to_token_ids(sentence, vocabulary, tokenizer=None, normalize_digits=True):
100 |
101 | if tokenizer:
102 | words = tokenizer(sentence)
103 | else:
104 | words = basic_tokenizer(sentence)
105 | if not normalize_digits:
106 | return [vocabulary.get(w, UNK_ID) for w in words]
107 | # Normalize digits by 0 before looking words up in the vocabulary.
108 | return [vocabulary.get(re.sub(_DIGIT_RE, b"0", w), UNK_ID) for w in words]
109 |
110 |
111 | def data_to_token_ids(data_path, target_path, vocabulary_path,
112 | tokenizer=None, normalize_digits=True):
113 |
114 | if not gfile.Exists(target_path):
115 | print("Tokenizing data in %s" % data_path)
116 | vocab, _ = initialize_vocabulary(vocabulary_path)
117 | with gfile.GFile(data_path, mode="rb") as data_file:
118 | with gfile.GFile(target_path, mode="w") as tokens_file:
119 | counter = 0
120 | for line in data_file:
121 | counter += 1
122 | if counter % 100000 == 0:
123 | print(" tokenizing line %d" % counter)
124 | token_ids = sentence_to_token_ids(line, vocab, tokenizer,
125 | normalize_digits)
126 | tokens_file.write(" ".join([str(tok) for tok in token_ids]) + "\n")
127 |
128 |
129 |
130 | def prepare_custom_data(working_directory, train_enc, train_dec, test_enc, test_dec, enc_vocabulary_size, dec_vocabulary_size, tokenizer=None):
131 |
132 | # Create vocabularies of the appropriate sizes.
133 | enc_vocab_path = os.path.join(working_directory, "vocab%d.enc" % enc_vocabulary_size)
134 | dec_vocab_path = os.path.join(working_directory, "vocab%d.dec" % dec_vocabulary_size)
135 | create_vocabulary(enc_vocab_path, train_enc, enc_vocabulary_size, tokenizer)
136 | create_vocabulary(dec_vocab_path, train_dec, dec_vocabulary_size, tokenizer)
137 |
138 | # Create token ids for the training data.
139 | enc_train_ids_path = train_enc + (".ids%d" % enc_vocabulary_size)
140 | dec_train_ids_path = train_dec + (".ids%d" % dec_vocabulary_size)
141 | data_to_token_ids(train_enc, enc_train_ids_path, enc_vocab_path, tokenizer)
142 | data_to_token_ids(train_dec, dec_train_ids_path, dec_vocab_path, tokenizer)
143 |
144 | # Create token ids for the development data.
145 | enc_dev_ids_path = test_enc + (".ids%d" % enc_vocabulary_size)
146 | dec_dev_ids_path = test_dec + (".ids%d" % dec_vocabulary_size)
147 | data_to_token_ids(test_enc, enc_dev_ids_path, enc_vocab_path, tokenizer)
148 | data_to_token_ids(test_dec, dec_dev_ids_path, dec_vocab_path, tokenizer)
149 |
150 | return (enc_train_ids_path, dec_train_ids_path, enc_dev_ids_path, dec_dev_ids_path, enc_vocab_path, dec_vocab_path)
151 |
--------------------------------------------------------------------------------
/env_setup.sh:
--------------------------------------------------------------------------------
1 | echo 'export PYTHONPATH=$PYTHONPATH:$PWD' >> ~/.bashrc
2 |
--------------------------------------------------------------------------------
/execute.py:
--------------------------------------------------------------------------------
1 | # Copyright 2015 The TensorFlow Authors. All Rights Reserved.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | # ==============================================================================
15 |
16 | from __future__ import absolute_import
17 | from __future__ import division
18 | from __future__ import print_function
19 |
20 | import math
21 | import os
22 | import random
23 | import sys
24 | import time
25 |
26 | import numpy as np
27 | from six.moves import xrange # pylint: disable=redefined-builtin
28 | import tensorflow as tf
29 |
30 | import data_utils
31 | import seq2seq_model
32 |
33 | try:
34 | from ConfigParser import SafeConfigParser
35 | except:
36 | from configparser import SafeConfigParser # In Python 3, ConfigParser has been renamed to configparser for PEP 8 compliance.
37 |
38 | gConfig = {}
39 |
40 | def get_config(config_file='seq2seq.ini'):
41 | parser = SafeConfigParser()
42 | parser.read(config_file)
43 | # get the ints, floats and strings
44 | _conf_ints = [ (key, int(value)) for key,value in parser.items('ints') ]
45 | _conf_floats = [ (key, float(value)) for key,value in parser.items('floats') ]
46 | _conf_strings = [ (key, str(value)) for key,value in parser.items('strings') ]
47 | return dict(_conf_ints + _conf_floats + _conf_strings)
48 |
49 | # We use a number of buckets and pad to the closest one for efficiency.
50 | # See seq2seq_model.Seq2SeqModel for details of how they work.
51 | _buckets = [(5, 10), (10, 15), (20, 25), (40, 50)]
52 |
53 |
54 | def read_data(source_path, target_path, max_size=None):
55 | """Read data from source and target files and put into buckets.
56 |
57 | Args:
58 | source_path: path to the files with token-ids for the source language.
59 | target_path: path to the file with token-ids for the target language;
60 | it must be aligned with the source file: n-th line contains the desired
61 | output for n-th line from the source_path.
62 | max_size: maximum number of lines to read, all other will be ignored;
63 | if 0 or None, data files will be read completely (no limit).
64 |
65 | Returns:
66 | data_set: a list of length len(_buckets); data_set[n] contains a list of
67 | (source, target) pairs read from the provided data files that fit
68 | into the n-th bucket, i.e., such that len(source) < _buckets[n][0] and
69 | len(target) < _buckets[n][1]; source and target are lists of token-ids.
70 | """
71 | data_set = [[] for _ in _buckets]
72 | with tf.gfile.GFile(source_path, mode="r") as source_file:
73 | with tf.gfile.GFile(target_path, mode="r") as target_file:
74 | source, target = source_file.readline(), target_file.readline()
75 | counter = 0
76 | while source and target and (not max_size or counter < max_size):
77 | counter += 1
78 | if counter % 100000 == 0:
79 | print(" reading data line %d" % counter)
80 | sys.stdout.flush()
81 | source_ids = [int(x) for x in source.split()]
82 | target_ids = [int(x) for x in target.split()]
83 | target_ids.append(data_utils.EOS_ID)
84 | for bucket_id, (source_size, target_size) in enumerate(_buckets):
85 | if len(source_ids) < source_size and len(target_ids) < target_size:
86 | data_set[bucket_id].append([source_ids, target_ids])
87 | break
88 | source, target = source_file.readline(), target_file.readline()
89 | return data_set
90 |
91 |
92 | def create_model(session, forward_only):
93 |
94 | """Create model and initialize or load parameters"""
95 | model = seq2seq_model.Seq2SeqModel( gConfig['enc_vocab_size'], gConfig['dec_vocab_size'], _buckets, gConfig['layer_size'], gConfig['num_layers'], gConfig['max_gradient_norm'], gConfig['batch_size'], gConfig['learning_rate'], gConfig['learning_rate_decay_factor'], forward_only=forward_only)
96 |
97 | if 'pretrained_model' in gConfig:
98 | model.saver.restore(session,gConfig['pretrained_model'])
99 | return model
100 |
101 | ckpt = tf.train.get_checkpoint_state(gConfig['working_directory'])
102 | if ckpt and ckpt.model_checkpoint_path:
103 | print("Reading model parameters from %s" % ckpt.model_checkpoint_path)
104 | model.saver.restore(session, ckpt.model_checkpoint_path)
105 | else:
106 | print("Created model with fresh parameters.")
107 | session.run(tf.global_variables_initializer())
108 | return model
109 |
110 |
111 | def train():
112 | # prepare dataset
113 | print("Preparing data in %s" % gConfig['working_directory'])
114 | enc_train, dec_train, enc_dev, dec_dev, _, _ = data_utils.prepare_custom_data(gConfig['working_directory'],gConfig['train_enc'],gConfig['train_dec'],gConfig['test_enc'],gConfig['test_dec'],gConfig['enc_vocab_size'],gConfig['dec_vocab_size'])
115 |
116 | # setup config to use BFC allocator
117 | config = tf.ConfigProto()
118 | config.gpu_options.allocator_type = 'BFC'
119 |
120 | with tf.Session(config=config) as sess:
121 | # Create model.
122 | print("Creating %d layers of %d units." % (gConfig['num_layers'], gConfig['layer_size']))
123 | model = create_model(sess, False)
124 |
125 | # Read data into buckets and compute their sizes.
126 | print ("Reading development and training data (limit: %d)."
127 | % gConfig['max_train_data_size'])
128 | dev_set = read_data(enc_dev, dec_dev)
129 | train_set = read_data(enc_train, dec_train, gConfig['max_train_data_size'])
130 | train_bucket_sizes = [len(train_set[b]) for b in xrange(len(_buckets))]
131 | train_total_size = float(sum(train_bucket_sizes))
132 |
133 | # A bucket scale is a list of increasing numbers from 0 to 1 that we'll use
134 | # to select a bucket. Length of [scale[i], scale[i+1]] is proportional to
135 | # the size if i-th training bucket, as used later.
136 | train_buckets_scale = [sum(train_bucket_sizes[:i + 1]) / train_total_size
137 | for i in xrange(len(train_bucket_sizes))]
138 |
139 | # This is the training loop.
140 | step_time, loss = 0.0, 0.0
141 | current_step = 0
142 | previous_losses = []
143 | while True:
144 | # Choose a bucket according to data distribution. We pick a random number
145 | # in [0, 1] and use the corresponding interval in train_buckets_scale.
146 | random_number_01 = np.random.random_sample()
147 | bucket_id = min([i for i in xrange(len(train_buckets_scale))
148 | if train_buckets_scale[i] > random_number_01])
149 |
150 | # Get a batch and make a step.
151 | start_time = time.time()
152 | encoder_inputs, decoder_inputs, target_weights = model.get_batch(
153 | train_set, bucket_id)
154 | _, step_loss, _ = model.step(sess, encoder_inputs, decoder_inputs,
155 | target_weights, bucket_id, False)
156 | step_time += (time.time() - start_time) / gConfig['steps_per_checkpoint']
157 | loss += step_loss / gConfig['steps_per_checkpoint']
158 | current_step += 1
159 |
160 | # Once in a while, we save checkpoint, print statistics, and run evals.
161 | if current_step % gConfig['steps_per_checkpoint'] == 0:
162 | # Print statistics for the previous epoch.
163 | perplexity = math.exp(loss) if loss < 300 else float('inf')
164 | print ("global step %d learning rate %.4f step-time %.2f perplexity "
165 | "%.2f" % (model.global_step.eval(), model.learning_rate.eval(),
166 | step_time, perplexity))
167 | # Decrease learning rate if no improvement was seen over last 3 times.
168 | if len(previous_losses) > 2 and loss > max(previous_losses[-3:]):
169 | sess.run(model.learning_rate_decay_op)
170 | previous_losses.append(loss)
171 | # Save checkpoint and zero timer and loss.
172 | checkpoint_path = os.path.join(gConfig['working_directory'], "seq2seq.ckpt")
173 | model.saver.save(sess, checkpoint_path, global_step=model.global_step)
174 | step_time, loss = 0.0, 0.0
175 | # Run evals on development set and print their perplexity.
176 | for bucket_id in xrange(len(_buckets)):
177 | if len(dev_set[bucket_id]) == 0:
178 | print(" eval: empty bucket %d" % (bucket_id))
179 | continue
180 | encoder_inputs, decoder_inputs, target_weights = model.get_batch(
181 | dev_set, bucket_id)
182 | _, eval_loss, _ = model.step(sess, encoder_inputs, decoder_inputs,
183 | target_weights, bucket_id, True)
184 | eval_ppx = math.exp(eval_loss) if eval_loss < 300 else float('inf')
185 | print(" eval: bucket %d perplexity %.2f" % (bucket_id, eval_ppx))
186 | sys.stdout.flush()
187 |
188 |
189 | def decode():
190 | with tf.Session() as sess:
191 | # Create model and load parameters.
192 | model = create_model(sess, True)
193 | model.batch_size = 1 # We decode one sentence at a time.
194 |
195 | # Load vocabularies.
196 | enc_vocab_path = os.path.join(gConfig['working_directory'],"vocab%d.enc" % gConfig['enc_vocab_size'])
197 | dec_vocab_path = os.path.join(gConfig['working_directory'],"vocab%d.dec" % gConfig['dec_vocab_size'])
198 |
199 | enc_vocab, _ = data_utils.initialize_vocabulary(enc_vocab_path)
200 | _, rev_dec_vocab = data_utils.initialize_vocabulary(dec_vocab_path)
201 |
202 | # Decode from standard input.
203 | sys.stdout.write("> ")
204 | sys.stdout.flush()
205 | sentence = sys.stdin.readline()
206 | while sentence:
207 | # Get token-ids for the input sentence.
208 | token_ids = data_utils.sentence_to_token_ids(tf.compat.as_bytes(sentence), enc_vocab)
209 | # Which bucket does it belong to?
210 | bucket_id = min([b for b in xrange(len(_buckets))
211 | if _buckets[b][0] > len(token_ids)])
212 | # Get a 1-element batch to feed the sentence to the model.
213 | encoder_inputs, decoder_inputs, target_weights = model.get_batch(
214 | {bucket_id: [(token_ids, [])]}, bucket_id)
215 | # Get output logits for the sentence.
216 | _, _, output_logits = model.step(sess, encoder_inputs, decoder_inputs,
217 | target_weights, bucket_id, True)
218 | # This is a greedy decoder - outputs are just argmaxes of output_logits.
219 | outputs = [int(np.argmax(logit, axis=1)) for logit in output_logits]
220 | # If there is an EOS symbol in outputs, cut them at that point.
221 | if data_utils.EOS_ID in outputs:
222 | outputs = outputs[:outputs.index(data_utils.EOS_ID)]
223 | # Print out French sentence corresponding to outputs.
224 | print(" ".join([tf.compat.as_str(rev_dec_vocab[output]) for output in outputs]))
225 | print("> ", end="")
226 | sys.stdout.flush()
227 | sentence = sys.stdin.readline()
228 |
229 |
230 | def self_test():
231 | """Test the translation model."""
232 | with tf.Session() as sess:
233 | print("Self-test for neural translation model.")
234 | # Create model with vocabularies of 10, 2 small buckets, 2 layers of 32.
235 | model = seq2seq_model.Seq2SeqModel(10, 10, [(3, 3), (6, 6)], 32, 2,
236 | 5.0, 32, 0.3, 0.99, num_samples=8)
237 | sess.run(tf.initialize_all_variables())
238 |
239 | # Fake data set for both the (3, 3) and (6, 6) bucket.
240 | data_set = ([([1, 1], [2, 2]), ([3, 3], [4]), ([5], [6])],
241 | [([1, 1, 1, 1, 1], [2, 2, 2, 2, 2]), ([3, 3, 3], [5, 6])])
242 | for _ in xrange(5): # Train the fake model for 5 steps.
243 | bucket_id = random.choice([0, 1])
244 | encoder_inputs, decoder_inputs, target_weights = model.get_batch(
245 | data_set, bucket_id)
246 | model.step(sess, encoder_inputs, decoder_inputs, target_weights,
247 | bucket_id, False)
248 |
249 |
250 | def init_session(sess, conf='seq2seq.ini'):
251 | global gConfig
252 | gConfig = get_config(conf)
253 |
254 | # Create model and load parameters.
255 | model = create_model(sess, True)
256 | model.batch_size = 1 # We decode one sentence at a time.
257 |
258 | # Load vocabularies.
259 | enc_vocab_path = os.path.join(gConfig['working_directory'],"vocab%d.enc" % gConfig['enc_vocab_size'])
260 | dec_vocab_path = os.path.join(gConfig['working_directory'],"vocab%d.dec" % gConfig['dec_vocab_size'])
261 |
262 | enc_vocab, _ = data_utils.initialize_vocabulary(enc_vocab_path)
263 | _, rev_dec_vocab = data_utils.initialize_vocabulary(dec_vocab_path)
264 |
265 | return sess, model, enc_vocab, rev_dec_vocab
266 |
267 | def decode_line(sess, model, enc_vocab, rev_dec_vocab, sentence):
268 | # Get token-ids for the input sentence.
269 | token_ids = data_utils.sentence_to_token_ids(tf.compat.as_bytes(sentence), enc_vocab)
270 |
271 | # Which bucket does it belong to?
272 | bucket_id = min([b for b in xrange(len(_buckets)) if _buckets[b][0] > len(token_ids)])
273 |
274 | # Get a 1-element batch to feed the sentence to the model.
275 | encoder_inputs, decoder_inputs, target_weights = model.get_batch({bucket_id: [(token_ids, [])]}, bucket_id)
276 |
277 | # Get output logits for the sentence.
278 | _, _, output_logits = model.step(sess, encoder_inputs, decoder_inputs, target_weights, bucket_id, True)
279 |
280 | # This is a greedy decoder - outputs are just argmaxes of output_logits.
281 | outputs = [int(np.argmax(logit, axis=1)) for logit in output_logits]
282 |
283 | # If there is an EOS symbol in outputs, cut them at that point.
284 | if data_utils.EOS_ID in outputs:
285 | outputs = outputs[:outputs.index(data_utils.EOS_ID)]
286 |
287 | return " ".join([tf.compat.as_str(rev_dec_vocab[output]) for output in outputs])
288 |
289 | if __name__ == '__main__':
290 | if len(sys.argv) - 1:
291 | gConfig = get_config(sys.argv[1])
292 | else:
293 | # get configuration from seq2seq.ini
294 | gConfig = get_config()
295 |
296 | print('\n>> Mode : %s\n' %(gConfig['mode']))
297 |
298 | if gConfig['mode'] == 'train':
299 | # start training
300 | train()
301 | elif gConfig['mode'] == 'test':
302 | # interactive decode
303 | decode()
304 | else:
305 | # wrong way to execute "serve"
306 | # Use : >> python ui/app.py
307 | # uses seq2seq_serve.ini as conf file
308 | print('Serve Usage : >> python ui/app.py')
309 | print('# uses seq2seq_serve.ini as conf file')
310 |
--------------------------------------------------------------------------------
/neuralconvo.ini:
--------------------------------------------------------------------------------
1 | [strings]
2 | # Mode : train, test, serve
3 | mode = train
4 | train_enc = data/train.enc
5 | train_dec = data/train.dec
6 | test_enc = data/test.enc
7 | test_dec = data/test.enc
8 | # folder where checkpoints, vocabulary, temporary data will be stored
9 | working_directory = working_dir/
10 | [ints]
11 | # vocabulary size
12 | # 20,000 is a reasonable size
13 | enc_vocab_size = 45000
14 | dec_vocab_size = 45000
15 | # number of LSTM layers : 1/2/3
16 | num_layers = 2
17 | # typical options : 128, 256, 512, 1024
18 | layer_size = 900
19 | # dataset size limit; typically none : no limit
20 | max_train_data_size = 50000
21 | batch_size = 10
22 | # steps per checkpoint
23 | # Note : At a checkpoint, models parameters are saved, model is evaluated
24 | # and results are printed
25 | steps_per_checkpoint = 200
26 | [floats]
27 | learning_rate = 0.001
28 | learning_rate_decay_factor = 0.9
29 | max_gradient_norm = 5.0
30 | ##############################################################################
31 | # Note : Edit the bucket sizes at line47 of execute.py (_buckets)
32 | #
33 | # Learn more about the configurations from this link
34 | # https://www.tensorflow.org/versions/r0.9/tutorials/seq2seq/index.html
35 | ##############################################################################
36 |
--------------------------------------------------------------------------------
/seq2seq.ini:
--------------------------------------------------------------------------------
1 | [strings]
2 | # Mode : train, test, serve
3 | mode = train
4 | train_enc = data/train.enc
5 | train_dec = data/train.dec
6 | test_enc = data/test.enc
7 | test_dec = data/test.dec
8 | # folder where checkpoints, vocabulary, temporary data will be stored
9 | working_directory = working_dir/
10 | [ints]
11 | # vocabulary size
12 | # 20,000 is a reasonable size
13 | enc_vocab_size = 20000
14 | dec_vocab_size = 20000
15 | # number of LSTM layers : 1/2/3
16 | num_layers = 3
17 | # typical options : 128, 256, 512, 1024
18 | layer_size = 256
19 | # dataset size limit; typically none : no limit
20 | max_train_data_size = 0
21 | batch_size = 64
22 | # steps per checkpoint
23 | # Note : At a checkpoint, models parameters are saved, model is evaluated
24 | # and results are printed
25 | steps_per_checkpoint = 300
26 | [floats]
27 | learning_rate = 0.5
28 | learning_rate_decay_factor = 0.99
29 | max_gradient_norm = 5.0
30 | ##############################################################################
31 | # Note : Edit the bucket sizes at line47 of execute.py (_buckets)
32 | #
33 | # Learn more about the configurations from this link
34 | # https://www.tensorflow.org/versions/r0.9/tutorials/seq2seq/index.html
35 | ##############################################################################
36 |
--------------------------------------------------------------------------------
/seq2seq_model.py:
--------------------------------------------------------------------------------
1 | # Copyright 2015 The TensorFlow Authors. All Rights Reserved.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | # ==============================================================================
15 |
16 | """Sequence-to-sequence model with an attention mechanism."""
17 |
18 | from __future__ import absolute_import
19 | from __future__ import division
20 | from __future__ import print_function
21 |
22 | import random
23 |
24 | import numpy as np
25 | from six.moves import xrange # pylint: disable=redefined-builtin
26 | import tensorflow as tf
27 |
28 | from tensorflow.models.rnn.translate import data_utils
29 |
30 |
31 | class Seq2SeqModel(object):
32 | """Sequence-to-sequence model with attention and for multiple buckets.
33 |
34 | This class implements a multi-layer recurrent neural network as encoder,
35 | and an attention-based decoder. This is the same as the model described in
36 | this paper: http://arxiv.org/abs/1412.7449 - please look there for details,
37 | or into the seq2seq library for complete model implementation.
38 | This class also allows to use GRU cells in addition to LSTM cells, and
39 | sampled softmax to handle large output vocabulary size. A single-layer
40 | version of this model, but with bi-directional encoder, was presented in
41 | http://arxiv.org/abs/1409.0473
42 | and sampled softmax is described in Section 3 of the following paper.
43 | http://arxiv.org/abs/1412.2007
44 | """
45 |
46 | def __init__(self, source_vocab_size, target_vocab_size, buckets, size,
47 | num_layers, max_gradient_norm, batch_size, learning_rate,
48 | learning_rate_decay_factor, use_lstm=False,
49 | num_samples=512, forward_only=False):
50 | """Create the model.
51 |
52 | Args:
53 | source_vocab_size: size of the source vocabulary.
54 | target_vocab_size: size of the target vocabulary.
55 | buckets: a list of pairs (I, O), where I specifies maximum input length
56 | that will be processed in that bucket, and O specifies maximum output
57 | length. Training instances that have inputs longer than I or outputs
58 | longer than O will be pushed to the next bucket and padded accordingly.
59 | We assume that the list is sorted, e.g., [(2, 4), (8, 16)].
60 | size: number of units in each layer of the model.
61 | num_layers: number of layers in the model.
62 | max_gradient_norm: gradients will be clipped to maximally this norm.
63 | batch_size: the size of the batches used during training;
64 | the model construction is independent of batch_size, so it can be
65 | changed after initialization if this is convenient, e.g., for decoding.
66 | learning_rate: learning rate to start with.
67 | learning_rate_decay_factor: decay learning rate by this much when needed.
68 | use_lstm: if true, we use LSTM cells instead of GRU cells.
69 | num_samples: number of samples for sampled softmax.
70 | forward_only: if set, we do not construct the backward pass in the model.
71 | """
72 | self.source_vocab_size = source_vocab_size
73 | self.target_vocab_size = target_vocab_size
74 | self.buckets = buckets
75 | self.batch_size = batch_size
76 | self.learning_rate = tf.Variable(float(learning_rate), trainable=False)
77 | self.learning_rate_decay_op = self.learning_rate.assign(
78 | self.learning_rate * learning_rate_decay_factor)
79 | self.global_step = tf.Variable(0, trainable=False)
80 |
81 | # If we use sampled softmax, we need an output projection.
82 | output_projection = None
83 | softmax_loss_function = None
84 | # Sampled softmax only makes sense if we sample less than vocabulary size.
85 | if num_samples > 0 and num_samples < self.target_vocab_size:
86 | w = tf.get_variable("proj_w", [size, self.target_vocab_size])
87 | w_t = tf.transpose(w)
88 | b = tf.get_variable("proj_b", [self.target_vocab_size])
89 | output_projection = (w, b)
90 |
91 | def sampled_loss(inputs, labels):
92 | labels = tf.reshape(labels, [-1, 1])
93 | return tf.nn.sampled_softmax_loss(w_t, b, inputs, labels, num_samples,
94 | self.target_vocab_size)
95 | softmax_loss_function = sampled_loss
96 |
97 | # Create the internal multi-layer cell for our RNN.
98 | single_cell = tf.nn.rnn_cell.GRUCell(size)
99 | if use_lstm:
100 | single_cell = tf.nn.rnn_cell.BasicLSTMCell(size)
101 | cell = single_cell
102 | cell = tf.nn.rnn_cell.DropoutWrapper(cell, output_keep_prob=0.5)
103 | if num_layers > 1:
104 | cell = tf.nn.rnn_cell.MultiRNNCell([single_cell] * num_layers)
105 |
106 | # The seq2seq function: we use embedding for the input and attention.
107 | def seq2seq_f(encoder_inputs, decoder_inputs, do_decode):
108 | return tf.nn.seq2seq.embedding_attention_seq2seq(
109 | encoder_inputs, decoder_inputs, cell,
110 | num_encoder_symbols=source_vocab_size,
111 | num_decoder_symbols=target_vocab_size,
112 | embedding_size=size,
113 | output_projection=output_projection,
114 | feed_previous=do_decode)
115 |
116 | # Feeds for inputs.
117 | self.encoder_inputs = []
118 | self.decoder_inputs = []
119 | self.target_weights = []
120 | for i in xrange(buckets[-1][0]): # Last bucket is the biggest one.
121 | self.encoder_inputs.append(tf.placeholder(tf.int32, shape=[None],
122 | name="encoder{0}".format(i)))
123 | for i in xrange(buckets[-1][1] + 1):
124 | self.decoder_inputs.append(tf.placeholder(tf.int32, shape=[None],
125 | name="decoder{0}".format(i)))
126 | self.target_weights.append(tf.placeholder(tf.float32, shape=[None],
127 | name="weight{0}".format(i)))
128 |
129 | # Our targets are decoder inputs shifted by one.
130 | targets = [self.decoder_inputs[i + 1]
131 | for i in xrange(len(self.decoder_inputs) - 1)]
132 |
133 | # Training outputs and losses.
134 | if forward_only:
135 | self.outputs, self.losses = tf.nn.seq2seq.model_with_buckets(
136 | self.encoder_inputs, self.decoder_inputs, targets,
137 | self.target_weights, buckets, lambda x, y: seq2seq_f(x, y, True),
138 | softmax_loss_function=softmax_loss_function)
139 | # If we use output projection, we need to project outputs for decoding.
140 | if output_projection is not None:
141 | for b in xrange(len(buckets)):
142 | self.outputs[b] = [
143 | tf.matmul(output, output_projection[0]) + output_projection[1]
144 | for output in self.outputs[b]
145 | ]
146 | else:
147 | self.outputs, self.losses = tf.nn.seq2seq.model_with_buckets(
148 | self.encoder_inputs, self.decoder_inputs, targets,
149 | self.target_weights, buckets,
150 | lambda x, y: seq2seq_f(x, y, False),
151 | softmax_loss_function=softmax_loss_function)
152 |
153 | # Gradients and SGD update operation for training the model.
154 | params = tf.trainable_variables()
155 | if not forward_only:
156 | self.gradient_norms = []
157 | self.updates = []
158 | opt = tf.train.AdamOptimizer()
159 | for b in xrange(len(buckets)):
160 | gradients = tf.gradients(self.losses[b], params)
161 | clipped_gradients, norm = tf.clip_by_global_norm(gradients,
162 | max_gradient_norm)
163 | self.gradient_norms.append(norm)
164 | self.updates.append(opt.apply_gradients(
165 | zip(clipped_gradients, params), global_step=self.global_step))
166 |
167 | self.saver = tf.train.Saver(tf.global_variables())
168 |
169 | def step(self, session, encoder_inputs, decoder_inputs, target_weights,
170 | bucket_id, forward_only):
171 | """Run a step of the model feeding the given inputs.
172 |
173 | Args:
174 | session: tensorflow session to use.
175 | encoder_inputs: list of numpy int vectors to feed as encoder inputs.
176 | decoder_inputs: list of numpy int vectors to feed as decoder inputs.
177 | target_weights: list of numpy float vectors to feed as target weights.
178 | bucket_id: which bucket of the model to use.
179 | forward_only: whether to do the backward step or only forward.
180 |
181 | Returns:
182 | A triple consisting of gradient norm (or None if we did not do backward),
183 | average perplexity, and the outputs.
184 |
185 | Raises:
186 | ValueError: if length of encoder_inputs, decoder_inputs, or
187 | target_weights disagrees with bucket size for the specified bucket_id.
188 | """
189 | # Check if the sizes match.
190 | encoder_size, decoder_size = self.buckets[bucket_id]
191 | if len(encoder_inputs) != encoder_size:
192 | raise ValueError("Encoder length must be equal to the one in bucket,"
193 | " %d != %d." % (len(encoder_inputs), encoder_size))
194 | if len(decoder_inputs) != decoder_size:
195 | raise ValueError("Decoder length must be equal to the one in bucket,"
196 | " %d != %d." % (len(decoder_inputs), decoder_size))
197 | if len(target_weights) != decoder_size:
198 | raise ValueError("Weights length must be equal to the one in bucket,"
199 | " %d != %d." % (len(target_weights), decoder_size))
200 |
201 | # Input feed: encoder inputs, decoder inputs, target_weights, as provided.
202 | input_feed = {}
203 | for l in xrange(encoder_size):
204 | input_feed[self.encoder_inputs[l].name] = encoder_inputs[l]
205 | for l in xrange(decoder_size):
206 | input_feed[self.decoder_inputs[l].name] = decoder_inputs[l]
207 | input_feed[self.target_weights[l].name] = target_weights[l]
208 |
209 | # Since our targets are decoder inputs shifted by one, we need one more.
210 | last_target = self.decoder_inputs[decoder_size].name
211 | input_feed[last_target] = np.zeros([self.batch_size], dtype=np.int32)
212 |
213 | # Output feed: depends on whether we do a backward step or not.
214 | if not forward_only:
215 | output_feed = [self.updates[bucket_id], # Update Op that does SGD.
216 | self.gradient_norms[bucket_id], # Gradient norm.
217 | self.losses[bucket_id]] # Loss for this batch.
218 | else:
219 | output_feed = [self.losses[bucket_id]] # Loss for this batch.
220 | for l in xrange(decoder_size): # Output logits.
221 | output_feed.append(self.outputs[bucket_id][l])
222 |
223 | outputs = session.run(output_feed, input_feed)
224 | if not forward_only:
225 | return outputs[1], outputs[2], None # Gradient norm, loss, no outputs.
226 | else:
227 | return None, outputs[0], outputs[1:] # No gradient norm, loss, outputs.
228 |
229 | def get_batch(self, data, bucket_id):
230 | """Get a random batch of data from the specified bucket, prepare for step.
231 |
232 | To feed data in step(..) it must be a list of batch-major vectors, while
233 | data here contains single length-major cases. So the main logic of this
234 | function is to re-index data cases to be in the proper format for feeding.
235 |
236 | Args:
237 | data: a tuple of size len(self.buckets) in which each element contains
238 | lists of pairs of input and output data that we use to create a batch.
239 | bucket_id: integer, which bucket to get the batch for.
240 |
241 | Returns:
242 | The triple (encoder_inputs, decoder_inputs, target_weights) for
243 | the constructed batch that has the proper format to call step(...) later.
244 | """
245 | encoder_size, decoder_size = self.buckets[bucket_id]
246 | encoder_inputs, decoder_inputs = [], []
247 |
248 | # Get a random batch of encoder and decoder inputs from data,
249 | # pad them if needed, reverse encoder inputs and add GO to decoder.
250 | for _ in xrange(self.batch_size):
251 | encoder_input, decoder_input = random.choice(data[bucket_id])
252 |
253 | # Encoder inputs are padded and then reversed.
254 | encoder_pad = [data_utils.PAD_ID] * (encoder_size - len(encoder_input))
255 | encoder_inputs.append(list(reversed(encoder_input + encoder_pad)))
256 |
257 | # Decoder inputs get an extra "GO" symbol, and are padded then.
258 | decoder_pad_size = decoder_size - len(decoder_input) - 1
259 | decoder_inputs.append([data_utils.GO_ID] + decoder_input +
260 | [data_utils.PAD_ID] * decoder_pad_size)
261 |
262 | # Now we create batch-major vectors from the data selected above.
263 | batch_encoder_inputs, batch_decoder_inputs, batch_weights = [], [], []
264 |
265 | # Batch encoder inputs are just re-indexed encoder_inputs.
266 | for length_idx in xrange(encoder_size):
267 | batch_encoder_inputs.append(
268 | np.array([encoder_inputs[batch_idx][length_idx]
269 | for batch_idx in xrange(self.batch_size)], dtype=np.int32))
270 |
271 | # Batch decoder inputs are re-indexed decoder_inputs, we create weights.
272 | for length_idx in xrange(decoder_size):
273 | batch_decoder_inputs.append(
274 | np.array([decoder_inputs[batch_idx][length_idx]
275 | for batch_idx in xrange(self.batch_size)], dtype=np.int32))
276 |
277 | # Create target_weights to be 0 for targets that are padding.
278 | batch_weight = np.ones(self.batch_size, dtype=np.float32)
279 | for batch_idx in xrange(self.batch_size):
280 | # We set weight to 0 if the corresponding target is a PAD symbol.
281 | # The corresponding target is decoder_input shifted by 1 forward.
282 | if length_idx < decoder_size - 1:
283 | target = decoder_inputs[batch_idx][length_idx + 1]
284 | if length_idx == decoder_size - 1 or target == data_utils.PAD_ID:
285 | batch_weight[batch_idx] = 0.0
286 | batch_weights.append(batch_weight)
287 | return batch_encoder_inputs, batch_decoder_inputs, batch_weights
288 |
--------------------------------------------------------------------------------
/seq2seq_serve.ini:
--------------------------------------------------------------------------------
1 | [strings]
2 | # Mode : train, test, serve
3 | mode = serve
4 | train_enc = data/train.enc
5 | train_dec = data/train.dec
6 | test_enc = data/test.enc
7 | test_dec = data/test.enc
8 | # folder where checkpoints, vocabulary, temporary data will be stored
9 | working_directory = working_dir/
10 | [ints]
11 | # vocabulary size
12 | # 20,000 is a reasonable size
13 | enc_vocab_size = 20000
14 | dec_vocab_size = 20000
15 | # number of LSTM layers : 1/2/3
16 | num_layers = 3
17 | # typical options : 128, 256, 512, 1024
18 | layer_size = 256
19 | # dataset size limit; typically none : no limit
20 | max_train_data_size = 0
21 | batch_size = 64
22 | # steps per checkpoint
23 | # Note : At a checkpoint, models parameters are saved, model is evaluated
24 | # and results are printed
25 | steps_per_checkpoint = 300
26 | [floats]
27 | learning_rate = 0.5
28 | learning_rate_decay_factor = 0.99
29 | max_gradient_norm = 5.0
30 | ##############################################################################
31 | # Note : Edit the bucket sizes at line47 of execute.py (_buckets)
32 | #
33 | # Learn more about the configurations from this link
34 | # https://www.tensorflow.org/versions/r0.9/tutorials/seq2seq/index.html
35 | ##############################################################################
36 |
--------------------------------------------------------------------------------
/ui/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | *.pyc
3 | *.pyo
4 | env
5 | env*
6 | dist
7 | build
8 | *.egg
9 | *.egg-info
10 | _mailinglist
11 | .tox
12 | .cache/
13 | .idea/
14 |
--------------------------------------------------------------------------------
/ui/README.md:
--------------------------------------------------------------------------------
1 | # Flask Chatbox
2 |
3 | A simple flask application that provides an UI for chat and handles the model internally.
4 |
--------------------------------------------------------------------------------
/ui/__init.py__:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/suriyadeepan/easy_seq2seq/c05b0d02f15e9bd1947ff79ddcd0b761a214e2a9/ui/__init.py__
--------------------------------------------------------------------------------
/ui/app.py:
--------------------------------------------------------------------------------
1 | from flask import Flask, render_template, request
2 | from flask import jsonify
3 |
4 | app = Flask(__name__,static_url_path="/static")
5 |
6 | #############
7 | # Routing
8 | #
9 | @app.route('/message', methods=['POST'])
10 | def reply():
11 | return jsonify( { 'text': execute.decode_line(sess, model, enc_vocab, rev_dec_vocab, request.form['msg'] ) } )
12 |
13 | @app.route("/")
14 | def index():
15 | return render_template("index.html")
16 | #############
17 |
18 | '''
19 | Init seq2seq model
20 |
21 | 1. Call main from execute.py
22 | 2. Create decode_line function that takes message as input
23 | '''
24 | #_________________________________________________________________
25 | import sys
26 | import os.path
27 |
28 | sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir)))
29 | import tensorflow as tf
30 | import execute
31 |
32 | sess = tf.Session()
33 | sess, model, enc_vocab, rev_dec_vocab = execute.init_session(sess, conf='seq2seq_serve.ini')
34 | #_________________________________________________________________
35 |
36 | # start app
37 | if (__name__ == "__main__"):
38 | app.run(port = 5000)
39 |
--------------------------------------------------------------------------------
/ui/requirements.txt:
--------------------------------------------------------------------------------
1 | click==6.6
2 | Flask==0.11.1
3 | itsdangerous==0.24
4 | Jinja2==2.8
5 | MarkupSafe==0.23
6 | Werkzeug==0.11.10
7 |
--------------------------------------------------------------------------------
/ui/setup.sh:
--------------------------------------------------------------------------------
1 | sudo -H pip install --upgrade pip
2 | sudo -H pip install -r requirements.txt
3 |
--------------------------------------------------------------------------------
/ui/static/css/normalize.css:
--------------------------------------------------------------------------------
1 | /*! normalize.css v4.0.0 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block}audio:not([controls]){display:none;height:0}progress{vertical-align:baseline}template,[hidden]{display:none}a{background-color:transparent}a:active,a:hover{outline-width:0}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:inherit}b,strong{font-weight:bolder}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}img{border-style:none}svg:not(:root){overflow:hidden}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}button,input,select,textarea{font:inherit;margin:0}optgroup{font-weight:bold}button,input,select{overflow:visible}button,select{text-transform:none}button,[type="button"],[type="reset"],[type="submit"]{cursor:pointer}[disabled]{cursor:default}button,html [type="button"],[type="reset"],[type="submit"]{-webkit-appearance:button}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}button:-moz-focusring,input:-moz-focusring{outline:1px dotted ButtonText}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}textarea{overflow:auto}[type="checkbox"],[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{-webkit-appearance:textfield}[type="search"]::-webkit-search-cancel-button,[type="search"]::-webkit-search-decoration{-webkit-appearance:none}
2 |
--------------------------------------------------------------------------------
/ui/static/css/style.css:
--------------------------------------------------------------------------------
1 | /*--------------------
2 | Mixins
3 | --------------------*/
4 | /*--------------------
5 | Body
6 | --------------------*/
7 | *,
8 | *::before,
9 | *::after {
10 | box-sizing: border-box;
11 | }
12 |
13 | html,
14 | body {
15 | height: 100%;
16 | }
17 |
18 | body {
19 | background: -webkit-linear-gradient(315deg, #044f48, #2a7561);
20 | background: linear-gradient(135deg, #044f48, #2a7561);
21 | background-size: cover;
22 | font-family: 'Open Sans', sans-serif;
23 | font-size: 12px;
24 | line-height: 1.3;
25 | overflow: hidden;
26 | }
27 |
28 | .bg {
29 | width: 100%;
30 | height: 100%;
31 | top: 0;
32 | left: 0;
33 | z-index: 1;
34 | background: url("/static/res/hd2.jpg") no-repeat 0 0;
35 | -webkit-filter: blur(80px);
36 | filter: blur(80px);
37 | -webkit-transform: scale(1.2);
38 | transform: scale(1.2);
39 | }
40 |
41 | /*--------------------
42 | Chat
43 | --------------------*/
44 | .chat {
45 | position: absolute;
46 | top: 50%;
47 | left: 50%;
48 | -webkit-transform: translate(-50%, -50%);
49 | transform: translate(-50%, -50%);
50 | width: 300px;
51 | height: 80vh;
52 | max-height: 500px;
53 | z-index: 2;
54 | overflow: hidden;
55 | box-shadow: 0 5px 30px rgba(0, 0, 0, 0.2);
56 | background: rgba(0, 0, 0, 0.5);
57 | border-radius: 20px;
58 | display: -webkit-box;
59 | display: -webkit-flex;
60 | display: -ms-flexbox;
61 | display: flex;
62 | -webkit-box-pack: justify;
63 | -webkit-justify-content: space-between;
64 | -ms-flex-pack: justify;
65 | justify-content: space-between;
66 | -webkit-box-orient: vertical;
67 | -webkit-box-direction: normal;
68 | -webkit-flex-direction: column;
69 | -ms-flex-direction: column;
70 | flex-direction: column;
71 | }
72 |
73 | /*--------------------
74 | Chat Title
75 | --------------------*/
76 | .chat-title {
77 | -webkit-box-flex: 0;
78 | -webkit-flex: 0 1 45px;
79 | -ms-flex: 0 1 45px;
80 | flex: 0 1 45px;
81 | position: relative;
82 | z-index: 2;
83 | background: rgba(0, 0, 0, 0.2);
84 | color: #fff;
85 | text-transform: uppercase;
86 | text-align: left;
87 | padding: 10px 10px 10px 50px;
88 | }
89 | .chat-title h1, .chat-title h2 {
90 | font-weight: normal;
91 | font-size: 10px;
92 | margin: 0;
93 | padding: 0;
94 | }
95 | .chat-title h2 {
96 | color: rgba(255, 255, 255, 0.5);
97 | font-size: 8px;
98 | letter-spacing: 1px;
99 | }
100 | .chat-title .avatar {
101 | position: absolute;
102 | z-index: 1;
103 | top: 8px;
104 | left: 9px;
105 | border-radius: 30px;
106 | width: 30px;
107 | height: 30px;
108 | overflow: hidden;
109 | margin: 0;
110 | padding: 0;
111 | border: 2px solid rgba(255, 255, 255, 0.24);
112 | }
113 | .chat-title .avatar img {
114 | width: 100%;
115 | height: auto;
116 | }
117 |
118 | /*--------------------
119 | Messages
120 | --------------------*/
121 | .messages {
122 | -webkit-box-flex: 1;
123 | -webkit-flex: 1 1 auto;
124 | -ms-flex: 1 1 auto;
125 | flex: 1 1 auto;
126 | color: rgba(255, 255, 255, 0.5);
127 | overflow: hidden;
128 | position: relative;
129 | width: 100%;
130 | }
131 | .messages .messages-content {
132 | position: absolute;
133 | top: 0;
134 | left: 0;
135 | height: 101%;
136 | width: 100%;
137 | }
138 | .messages .message {
139 | clear: both;
140 | float: left;
141 | padding: 6px 10px 7px;
142 | border-radius: 10px 10px 10px 0;
143 | background: rgba(0, 0, 0, 0.3);
144 | margin: 8px 0;
145 | font-size: 11px;
146 | line-height: 1.4;
147 | margin-left: 35px;
148 | position: relative;
149 | text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
150 | }
151 | .messages .message .timestamp {
152 | position: absolute;
153 | bottom: -15px;
154 | font-size: 9px;
155 | color: rgba(255, 255, 255, 0.3);
156 | }
157 | .messages .message::before {
158 | content: '';
159 | position: absolute;
160 | bottom: -6px;
161 | border-top: 6px solid rgba(0, 0, 0, 0.3);
162 | left: 0;
163 | border-right: 7px solid transparent;
164 | }
165 | .messages .message .avatar {
166 | position: absolute;
167 | z-index: 1;
168 | bottom: -15px;
169 | left: -35px;
170 | border-radius: 30px;
171 | width: 30px;
172 | height: 30px;
173 | overflow: hidden;
174 | margin: 0;
175 | padding: 0;
176 | border: 2px solid rgba(255, 255, 255, 0.24);
177 | }
178 | .messages .message .avatar img {
179 | width: 100%;
180 | height: auto;
181 | }
182 | .messages .message.message-personal {
183 | float: right;
184 | color: #fff;
185 | text-align: right;
186 | background: -webkit-linear-gradient(330deg, #248A52, #257287);
187 | background: linear-gradient(120deg, #248A52, #257287);
188 | border-radius: 10px 10px 0 10px;
189 | }
190 | .messages .message.message-personal::before {
191 | left: auto;
192 | right: 0;
193 | border-right: none;
194 | border-left: 5px solid transparent;
195 | border-top: 4px solid #257287;
196 | bottom: -4px;
197 | }
198 | .messages .message:last-child {
199 | margin-bottom: 30px;
200 | }
201 | .messages .message.new {
202 | -webkit-transform: scale(0);
203 | transform: scale(0);
204 | -webkit-transform-origin: 0 0;
205 | transform-origin: 0 0;
206 | -webkit-animation: bounce 500ms linear both;
207 | animation: bounce 500ms linear both;
208 | }
209 | .messages .message.loading::before {
210 | position: absolute;
211 | top: 50%;
212 | left: 50%;
213 | -webkit-transform: translate(-50%, -50%);
214 | transform: translate(-50%, -50%);
215 | content: '';
216 | display: block;
217 | width: 3px;
218 | height: 3px;
219 | border-radius: 50%;
220 | background: rgba(255, 255, 255, 0.5);
221 | z-index: 2;
222 | margin-top: 4px;
223 | -webkit-animation: ball 0.45s cubic-bezier(0, 0, 0.15, 1) alternate infinite;
224 | animation: ball 0.45s cubic-bezier(0, 0, 0.15, 1) alternate infinite;
225 | border: none;
226 | -webkit-animation-delay: .15s;
227 | animation-delay: .15s;
228 | }
229 | .messages .message.loading span {
230 | display: block;
231 | font-size: 0;
232 | width: 20px;
233 | height: 10px;
234 | position: relative;
235 | }
236 | .messages .message.loading span::before {
237 | position: absolute;
238 | top: 50%;
239 | left: 50%;
240 | -webkit-transform: translate(-50%, -50%);
241 | transform: translate(-50%, -50%);
242 | content: '';
243 | display: block;
244 | width: 3px;
245 | height: 3px;
246 | border-radius: 50%;
247 | background: rgba(255, 255, 255, 0.5);
248 | z-index: 2;
249 | margin-top: 4px;
250 | -webkit-animation: ball 0.45s cubic-bezier(0, 0, 0.15, 1) alternate infinite;
251 | animation: ball 0.45s cubic-bezier(0, 0, 0.15, 1) alternate infinite;
252 | margin-left: -7px;
253 | }
254 | .messages .message.loading span::after {
255 | position: absolute;
256 | top: 50%;
257 | left: 50%;
258 | -webkit-transform: translate(-50%, -50%);
259 | transform: translate(-50%, -50%);
260 | content: '';
261 | display: block;
262 | width: 3px;
263 | height: 3px;
264 | border-radius: 50%;
265 | background: rgba(255, 255, 255, 0.5);
266 | z-index: 2;
267 | margin-top: 4px;
268 | -webkit-animation: ball 0.45s cubic-bezier(0, 0, 0.15, 1) alternate infinite;
269 | animation: ball 0.45s cubic-bezier(0, 0, 0.15, 1) alternate infinite;
270 | margin-left: 7px;
271 | -webkit-animation-delay: .3s;
272 | animation-delay: .3s;
273 | }
274 |
275 | /*--------------------
276 | Message Box
277 | --------------------*/
278 | .message-box {
279 | -webkit-box-flex: 0;
280 | -webkit-flex: 0 1 40px;
281 | -ms-flex: 0 1 40px;
282 | flex: 0 1 40px;
283 | width: 100%;
284 | background: rgba(0, 0, 0, 0.3);
285 | padding: 10px;
286 | position: relative;
287 | }
288 | .message-box .message-input {
289 | background: none;
290 | border: none;
291 | outline: none !important;
292 | resize: none;
293 | color: rgba(255, 255, 255, 0.7);
294 | font-size: 11px;
295 | height: 17px;
296 | margin: 0;
297 | padding-right: 20px;
298 | width: 265px;
299 | }
300 | .message-box textarea:focus:-webkit-placeholder {
301 | color: transparent;
302 | }
303 | .message-box .message-submit {
304 | position: absolute;
305 | z-index: 1;
306 | top: 9px;
307 | right: 10px;
308 | color: #fff;
309 | border: none;
310 | background: #248A52;
311 | font-size: 10px;
312 | text-transform: uppercase;
313 | line-height: 1;
314 | padding: 6px 10px;
315 | border-radius: 10px;
316 | outline: none !important;
317 | -webkit-transition: background .2s ease;
318 | transition: background .2s ease;
319 | }
320 | .message-box .message-submit:hover {
321 | background: #1D7745;
322 | }
323 |
324 | /*--------------------
325 | Custom Srollbar
326 | --------------------*/
327 | .mCSB_scrollTools {
328 | margin: 1px -3px 1px 0;
329 | opacity: 0;
330 | }
331 |
332 | .mCSB_inside > .mCSB_container {
333 | margin-right: 0px;
334 | padding: 0 10px;
335 | }
336 |
337 | .mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar {
338 | background-color: rgba(0, 0, 0, 0.5) !important;
339 | }
340 |
341 | /*--------------------
342 | Bounce
343 | --------------------*/
344 | @-webkit-keyframes bounce {
345 | 0% {
346 | -webkit-transform: matrix3d(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
347 | transform: matrix3d(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
348 | }
349 | 4.7% {
350 | -webkit-transform: matrix3d(0.45, 0, 0, 0, 0, 0.45, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
351 | transform: matrix3d(0.45, 0, 0, 0, 0, 0.45, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
352 | }
353 | 9.41% {
354 | -webkit-transform: matrix3d(0.883, 0, 0, 0, 0, 0.883, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
355 | transform: matrix3d(0.883, 0, 0, 0, 0, 0.883, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
356 | }
357 | 14.11% {
358 | -webkit-transform: matrix3d(1.141, 0, 0, 0, 0, 1.141, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
359 | transform: matrix3d(1.141, 0, 0, 0, 0, 1.141, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
360 | }
361 | 18.72% {
362 | -webkit-transform: matrix3d(1.212, 0, 0, 0, 0, 1.212, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
363 | transform: matrix3d(1.212, 0, 0, 0, 0, 1.212, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
364 | }
365 | 24.32% {
366 | -webkit-transform: matrix3d(1.151, 0, 0, 0, 0, 1.151, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
367 | transform: matrix3d(1.151, 0, 0, 0, 0, 1.151, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
368 | }
369 | 29.93% {
370 | -webkit-transform: matrix3d(1.048, 0, 0, 0, 0, 1.048, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
371 | transform: matrix3d(1.048, 0, 0, 0, 0, 1.048, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
372 | }
373 | 35.54% {
374 | -webkit-transform: matrix3d(0.979, 0, 0, 0, 0, 0.979, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
375 | transform: matrix3d(0.979, 0, 0, 0, 0, 0.979, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
376 | }
377 | 41.04% {
378 | -webkit-transform: matrix3d(0.961, 0, 0, 0, 0, 0.961, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
379 | transform: matrix3d(0.961, 0, 0, 0, 0, 0.961, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
380 | }
381 | 52.15% {
382 | -webkit-transform: matrix3d(0.991, 0, 0, 0, 0, 0.991, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
383 | transform: matrix3d(0.991, 0, 0, 0, 0, 0.991, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
384 | }
385 | 63.26% {
386 | -webkit-transform: matrix3d(1.007, 0, 0, 0, 0, 1.007, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
387 | transform: matrix3d(1.007, 0, 0, 0, 0, 1.007, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
388 | }
389 | 85.49% {
390 | -webkit-transform: matrix3d(0.999, 0, 0, 0, 0, 0.999, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
391 | transform: matrix3d(0.999, 0, 0, 0, 0, 0.999, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
392 | }
393 | 100% {
394 | -webkit-transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
395 | transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
396 | }
397 | }
398 | @keyframes bounce {
399 | 0% {
400 | -webkit-transform: matrix3d(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
401 | transform: matrix3d(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
402 | }
403 | 4.7% {
404 | -webkit-transform: matrix3d(0.45, 0, 0, 0, 0, 0.45, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
405 | transform: matrix3d(0.45, 0, 0, 0, 0, 0.45, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
406 | }
407 | 9.41% {
408 | -webkit-transform: matrix3d(0.883, 0, 0, 0, 0, 0.883, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
409 | transform: matrix3d(0.883, 0, 0, 0, 0, 0.883, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
410 | }
411 | 14.11% {
412 | -webkit-transform: matrix3d(1.141, 0, 0, 0, 0, 1.141, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
413 | transform: matrix3d(1.141, 0, 0, 0, 0, 1.141, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
414 | }
415 | 18.72% {
416 | -webkit-transform: matrix3d(1.212, 0, 0, 0, 0, 1.212, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
417 | transform: matrix3d(1.212, 0, 0, 0, 0, 1.212, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
418 | }
419 | 24.32% {
420 | -webkit-transform: matrix3d(1.151, 0, 0, 0, 0, 1.151, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
421 | transform: matrix3d(1.151, 0, 0, 0, 0, 1.151, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
422 | }
423 | 29.93% {
424 | -webkit-transform: matrix3d(1.048, 0, 0, 0, 0, 1.048, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
425 | transform: matrix3d(1.048, 0, 0, 0, 0, 1.048, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
426 | }
427 | 35.54% {
428 | -webkit-transform: matrix3d(0.979, 0, 0, 0, 0, 0.979, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
429 | transform: matrix3d(0.979, 0, 0, 0, 0, 0.979, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
430 | }
431 | 41.04% {
432 | -webkit-transform: matrix3d(0.961, 0, 0, 0, 0, 0.961, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
433 | transform: matrix3d(0.961, 0, 0, 0, 0, 0.961, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
434 | }
435 | 52.15% {
436 | -webkit-transform: matrix3d(0.991, 0, 0, 0, 0, 0.991, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
437 | transform: matrix3d(0.991, 0, 0, 0, 0, 0.991, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
438 | }
439 | 63.26% {
440 | -webkit-transform: matrix3d(1.007, 0, 0, 0, 0, 1.007, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
441 | transform: matrix3d(1.007, 0, 0, 0, 0, 1.007, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
442 | }
443 | 85.49% {
444 | -webkit-transform: matrix3d(0.999, 0, 0, 0, 0, 0.999, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
445 | transform: matrix3d(0.999, 0, 0, 0, 0, 0.999, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
446 | }
447 | 100% {
448 | -webkit-transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
449 | transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
450 | }
451 | }
452 | @-webkit-keyframes ball {
453 | from {
454 | -webkit-transform: translateY(0) scaleY(0.8);
455 | transform: translateY(0) scaleY(0.8);
456 | }
457 | to {
458 | -webkit-transform: translateY(-10px);
459 | transform: translateY(-10px);
460 | }
461 | }
462 | @keyframes ball {
463 | from {
464 | -webkit-transform: translateY(0) scaleY(0.8);
465 | transform: translateY(0) scaleY(0.8);
466 | }
467 | to {
468 | -webkit-transform: translateY(-10px);
469 | transform: translateY(-10px);
470 | }
471 | }
472 |
--------------------------------------------------------------------------------
/ui/static/js/index.js:
--------------------------------------------------------------------------------
1 | var $messages = $('.messages-content'),
2 | d, h, m,
3 | i = 0;
4 |
5 | $(window).load(function() {
6 | $messages.mCustomScrollbar();
7 | setTimeout(function() {
8 | //fakeMessage();
9 | }, 100);
10 | });
11 |
12 | function updateScrollbar() {
13 | $messages.mCustomScrollbar("update").mCustomScrollbar('scrollTo', 'bottom', {
14 | scrollInertia: 10,
15 | timeout: 0
16 | });
17 | }
18 |
19 | function setDate(){
20 | d = new Date()
21 | if (m != d.getMinutes()) {
22 | m = d.getMinutes();
23 | $('
' + d.getHours() + ':' + m + '
').appendTo($('.message:last'));
24 | }
25 | }
26 |
27 | function insertMessage() {
28 | msg = $('.message-input').val();
29 | if ($.trim(msg) == '') {
30 | return false;
31 | }
32 | $('' + msg + '
').appendTo($('.mCSB_container')).addClass('new');
33 | setDate();
34 | $('.message-input').val(null);
35 | updateScrollbar();
36 | interact(msg);
37 | setTimeout(function() {
38 | //fakeMessage();
39 | }, 1000 + (Math.random() * 20) * 100);
40 | }
41 |
42 | $('.message-submit').click(function() {
43 | insertMessage();
44 | });
45 |
46 | $(window).on('keydown', function(e) {
47 | if (e.which == 13) {
48 | insertMessage();
49 | return false;
50 | }
51 | })
52 |
53 |
54 | function interact(message){
55 | // loading message
56 | $('').appendTo($('.mCSB_container'));
57 | // make a POST request [ajax call]
58 | $.post('/message', {
59 | msg: message,
60 | }).done(function(reply) {
61 | // Message Received
62 | // remove loading meassage
63 | $('.message.loading').remove();
64 | // Add message to chatbox
65 | $('
' + reply['text'] + '
').appendTo($('.mCSB_container')).addClass('new');
66 | setDate();
67 | updateScrollbar();
68 |
69 | }).fail(function() {
70 | alert('error calling function');
71 | });
72 | }
73 |
--------------------------------------------------------------------------------
/ui/static/js/jquery.mCustomScrollbar.concat.min.js:
--------------------------------------------------------------------------------
1 | /* == jquery mousewheel plugin == Version: 3.1.13, License: MIT License (MIT) */
2 | !function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof exports?module.exports=a:a(jQuery)}(function(a){function b(b){var g=b||window.event,h=i.call(arguments,1),j=0,l=0,m=0,n=0,o=0,p=0;if(b=a.event.fix(g),b.type="mousewheel","detail"in g&&(m=-1*g.detail),"wheelDelta"in g&&(m=g.wheelDelta),"wheelDeltaY"in g&&(m=g.wheelDeltaY),"wheelDeltaX"in g&&(l=-1*g.wheelDeltaX),"axis"in g&&g.axis===g.HORIZONTAL_AXIS&&(l=-1*m,m=0),j=0===m?l:m,"deltaY"in g&&(m=-1*g.deltaY,j=m),"deltaX"in g&&(l=g.deltaX,0===m&&(j=-1*l)),0!==m||0!==l){if(1===g.deltaMode){var q=a.data(this,"mousewheel-line-height");j*=q,m*=q,l*=q}else if(2===g.deltaMode){var r=a.data(this,"mousewheel-page-height");j*=r,m*=r,l*=r}if(n=Math.max(Math.abs(m),Math.abs(l)),(!f||f>n)&&(f=n,d(g,n)&&(f/=40)),d(g,n)&&(j/=40,l/=40,m/=40),j=Math[j>=1?"floor":"ceil"](j/f),l=Math[l>=1?"floor":"ceil"](l/f),m=Math[m>=1?"floor":"ceil"](m/f),k.settings.normalizeOffset&&this.getBoundingClientRect){var s=this.getBoundingClientRect();o=b.clientX-s.left,p=b.clientY-s.top}return b.deltaX=l,b.deltaY=m,b.deltaFactor=f,b.offsetX=o,b.offsetY=p,b.deltaMode=0,h.unshift(b,j,l,m),e&&clearTimeout(e),e=setTimeout(c,200),(a.event.dispatch||a.event.handle).apply(this,h)}}function c(){f=null}function d(a,b){return k.settings.adjustOldDeltas&&"mousewheel"===a.type&&b%120===0}var e,f,g=["wheel","mousewheel","DOMMouseScroll","MozMousePixelScroll"],h="onwheel"in document||document.documentMode>=9?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"],i=Array.prototype.slice;if(a.event.fixHooks)for(var j=g.length;j;)a.event.fixHooks[g[--j]]=a.event.mouseHooks;var k=a.event.special.mousewheel={version:"3.1.12",setup:function(){if(this.addEventListener)for(var c=h.length;c;)this.addEventListener(h[--c],b,!1);else this.onmousewheel=b;a.data(this,"mousewheel-line-height",k.getLineHeight(this)),a.data(this,"mousewheel-page-height",k.getPageHeight(this))},teardown:function(){if(this.removeEventListener)for(var c=h.length;c;)this.removeEventListener(h[--c],b,!1);else this.onmousewheel=null;a.removeData(this,"mousewheel-line-height"),a.removeData(this,"mousewheel-page-height")},getLineHeight:function(b){var c=a(b),d=c["offsetParent"in a.fn?"offsetParent":"parent"]();return d.length||(d=a("body")),parseInt(d.css("fontSize"),10)||parseInt(c.css("fontSize"),10)||16},getPageHeight:function(b){return a(b).height()},settings:{adjustOldDeltas:!0,normalizeOffset:!0}};a.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})});!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof exports?module.exports=a:a(jQuery)}(function(a){function b(b){var g=b||window.event,h=i.call(arguments,1),j=0,l=0,m=0,n=0,o=0,p=0;if(b=a.event.fix(g),b.type="mousewheel","detail"in g&&(m=-1*g.detail),"wheelDelta"in g&&(m=g.wheelDelta),"wheelDeltaY"in g&&(m=g.wheelDeltaY),"wheelDeltaX"in g&&(l=-1*g.wheelDeltaX),"axis"in g&&g.axis===g.HORIZONTAL_AXIS&&(l=-1*m,m=0),j=0===m?l:m,"deltaY"in g&&(m=-1*g.deltaY,j=m),"deltaX"in g&&(l=g.deltaX,0===m&&(j=-1*l)),0!==m||0!==l){if(1===g.deltaMode){var q=a.data(this,"mousewheel-line-height");j*=q,m*=q,l*=q}else if(2===g.deltaMode){var r=a.data(this,"mousewheel-page-height");j*=r,m*=r,l*=r}if(n=Math.max(Math.abs(m),Math.abs(l)),(!f||f>n)&&(f=n,d(g,n)&&(f/=40)),d(g,n)&&(j/=40,l/=40,m/=40),j=Math[j>=1?"floor":"ceil"](j/f),l=Math[l>=1?"floor":"ceil"](l/f),m=Math[m>=1?"floor":"ceil"](m/f),k.settings.normalizeOffset&&this.getBoundingClientRect){var s=this.getBoundingClientRect();o=b.clientX-s.left,p=b.clientY-s.top}return b.deltaX=l,b.deltaY=m,b.deltaFactor=f,b.offsetX=o,b.offsetY=p,b.deltaMode=0,h.unshift(b,j,l,m),e&&clearTimeout(e),e=setTimeout(c,200),(a.event.dispatch||a.event.handle).apply(this,h)}}function c(){f=null}function d(a,b){return k.settings.adjustOldDeltas&&"mousewheel"===a.type&&b%120===0}var e,f,g=["wheel","mousewheel","DOMMouseScroll","MozMousePixelScroll"],h="onwheel"in document||document.documentMode>=9?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"],i=Array.prototype.slice;if(a.event.fixHooks)for(var j=g.length;j;)a.event.fixHooks[g[--j]]=a.event.mouseHooks;var k=a.event.special.mousewheel={version:"3.1.12",setup:function(){if(this.addEventListener)for(var c=h.length;c;)this.addEventListener(h[--c],b,!1);else this.onmousewheel=b;a.data(this,"mousewheel-line-height",k.getLineHeight(this)),a.data(this,"mousewheel-page-height",k.getPageHeight(this))},teardown:function(){if(this.removeEventListener)for(var c=h.length;c;)this.removeEventListener(h[--c],b,!1);else this.onmousewheel=null;a.removeData(this,"mousewheel-line-height"),a.removeData(this,"mousewheel-page-height")},getLineHeight:function(b){var c=a(b),d=c["offsetParent"in a.fn?"offsetParent":"parent"]();return d.length||(d=a("body")),parseInt(d.css("fontSize"),10)||parseInt(c.css("fontSize"),10)||16},getPageHeight:function(b){return a(b).height()},settings:{adjustOldDeltas:!0,normalizeOffset:!0}};a.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})});
3 | /* == malihu jquery custom scrollbar plugin == Version: 3.1.3, License: MIT License (MIT) */
4 | !function(e){"undefined"!=typeof module&&module.exports?module.exports=e:e(jQuery,window,document)}(function(e){!function(t){var o="function"==typeof define&&define.amd,a="undefined"!=typeof module&&module.exports,n="https:"==document.location.protocol?"https:":"http:",i="cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.13/jquery.mousewheel.min.js";o||(a?require("jquery-mousewheel")(e):e.event.special.mousewheel||e("head").append(decodeURI("%3Cscript src="+n+"//"+i+"%3E%3C/script%3E"))),t()}(function(){var t,o="mCustomScrollbar",a="mCS",n=".mCustomScrollbar",i={setTop:0,setLeft:0,axis:"y",scrollbarPosition:"inside",scrollInertia:950,autoDraggerLength:!0,alwaysShowScrollbar:0,snapOffset:0,mouseWheel:{enable:!0,scrollAmount:"auto",axis:"y",deltaFactor:"auto",disableOver:["select","option","keygen","datalist","textarea"]},scrollButtons:{scrollType:"stepless",scrollAmount:"auto"},keyboard:{enable:!0,scrollType:"stepless",scrollAmount:"auto"},contentTouchScroll:25,documentTouchScroll:!0,advanced:{autoScrollOnFocus:"input,textarea,select,button,datalist,keygen,a[tabindex],area,object,[contenteditable='true']",updateOnContentResize:!0,updateOnImageLoad:"auto",autoUpdateTimeout:60},theme:"light",callbacks:{onTotalScrollOffset:0,onTotalScrollBackOffset:0,alwaysTriggerOffsets:!0}},r=0,l={},s=window.attachEvent&&!window.addEventListener?1:0,c=!1,d=["mCSB_dragger_onDrag","mCSB_scrollTools_onDrag","mCS_img_loaded","mCS_disabled","mCS_destroyed","mCS_no_scrollbar","mCS-autoHide","mCS-dir-rtl","mCS_no_scrollbar_y","mCS_no_scrollbar_x","mCS_y_hidden","mCS_x_hidden","mCSB_draggerContainer","mCSB_buttonUp","mCSB_buttonDown","mCSB_buttonLeft","mCSB_buttonRight"],u={init:function(t){var t=e.extend(!0,{},i,t),o=f.call(this);if(t.live){var s=t.liveSelector||this.selector||n,c=e(s);if("off"===t.live)return void m(s);l[s]=setTimeout(function(){c.mCustomScrollbar(t),"once"===t.live&&c.length&&m(s)},500)}else m(s);return t.setWidth=t.set_width?t.set_width:t.setWidth,t.setHeight=t.set_height?t.set_height:t.setHeight,t.axis=t.horizontalScroll?"x":p(t.axis),t.scrollInertia=t.scrollInertia>0&&t.scrollInertia<17?17:t.scrollInertia,"object"!=typeof t.mouseWheel&&1==t.mouseWheel&&(t.mouseWheel={enable:!0,scrollAmount:"auto",axis:"y",preventDefault:!1,deltaFactor:"auto",normalizeDelta:!1,invert:!1}),t.mouseWheel.scrollAmount=t.mouseWheelPixels?t.mouseWheelPixels:t.mouseWheel.scrollAmount,t.mouseWheel.normalizeDelta=t.advanced.normalizeMouseWheelDelta?t.advanced.normalizeMouseWheelDelta:t.mouseWheel.normalizeDelta,t.scrollButtons.scrollType=g(t.scrollButtons.scrollType),h(t),e(o).each(function(){var o=e(this);if(!o.data(a)){o.data(a,{idx:++r,opt:t,scrollRatio:{y:null,x:null},overflowed:null,contentReset:{y:null,x:null},bindEvents:!1,tweenRunning:!1,sequential:{},langDir:o.css("direction"),cbOffsets:null,trigger:null,poll:{size:{o:0,n:0},img:{o:0,n:0},change:{o:0,n:0}}});var n=o.data(a),i=n.opt,l=o.data("mcs-axis"),s=o.data("mcs-scrollbar-position"),c=o.data("mcs-theme");l&&(i.axis=l),s&&(i.scrollbarPosition=s),c&&(i.theme=c,h(i)),v.call(this),n&&i.callbacks.onCreate&&"function"==typeof i.callbacks.onCreate&&i.callbacks.onCreate.call(this),e("#mCSB_"+n.idx+"_container img:not(."+d[2]+")").addClass(d[2]),u.update.call(null,o)}})},update:function(t,o){var n=t||f.call(this);return e(n).each(function(){var t=e(this);if(t.data(a)){var n=t.data(a),i=n.opt,r=e("#mCSB_"+n.idx+"_container"),l=e("#mCSB_"+n.idx),s=[e("#mCSB_"+n.idx+"_dragger_vertical"),e("#mCSB_"+n.idx+"_dragger_horizontal")];if(!r.length)return;n.tweenRunning&&N(t),o&&n&&i.callbacks.onBeforeUpdate&&"function"==typeof i.callbacks.onBeforeUpdate&&i.callbacks.onBeforeUpdate.call(this),t.hasClass(d[3])&&t.removeClass(d[3]),t.hasClass(d[4])&&t.removeClass(d[4]),l.css("max-height","none"),l.height()!==t.height()&&l.css("max-height",t.height()),_.call(this),"y"===i.axis||i.advanced.autoExpandHorizontalScroll||r.css("width",x(r)),n.overflowed=y.call(this),M.call(this),i.autoDraggerLength&&S.call(this),b.call(this),T.call(this);var c=[Math.abs(r[0].offsetTop),Math.abs(r[0].offsetLeft)];"x"!==i.axis&&(n.overflowed[0]?s[0].height()>s[0].parent().height()?B.call(this):(V(t,c[0].toString(),{dir:"y",dur:0,overwrite:"none"}),n.contentReset.y=null):(B.call(this),"y"===i.axis?k.call(this):"yx"===i.axis&&n.overflowed[1]&&V(t,c[1].toString(),{dir:"x",dur:0,overwrite:"none"}))),"y"!==i.axis&&(n.overflowed[1]?s[1].width()>s[1].parent().width()?B.call(this):(V(t,c[1].toString(),{dir:"x",dur:0,overwrite:"none"}),n.contentReset.x=null):(B.call(this),"x"===i.axis?k.call(this):"yx"===i.axis&&n.overflowed[0]&&V(t,c[0].toString(),{dir:"y",dur:0,overwrite:"none"}))),o&&n&&(2===o&&i.callbacks.onImageLoad&&"function"==typeof i.callbacks.onImageLoad?i.callbacks.onImageLoad.call(this):3===o&&i.callbacks.onSelectorChange&&"function"==typeof i.callbacks.onSelectorChange?i.callbacks.onSelectorChange.call(this):i.callbacks.onUpdate&&"function"==typeof i.callbacks.onUpdate&&i.callbacks.onUpdate.call(this)),X.call(this)}})},scrollTo:function(t,o){if("undefined"!=typeof t&&null!=t){var n=f.call(this);return e(n).each(function(){var n=e(this);if(n.data(a)){var i=n.data(a),r=i.opt,l={trigger:"external",scrollInertia:r.scrollInertia,scrollEasing:"mcsEaseInOut",moveDragger:!1,timeout:60,callbacks:!0,onStart:!0,onUpdate:!0,onComplete:!0},s=e.extend(!0,{},l,o),c=q.call(this,t),d=s.scrollInertia>0&&s.scrollInertia<17?17:s.scrollInertia;c[0]=Y.call(this,c[0],"y"),c[1]=Y.call(this,c[1],"x"),s.moveDragger&&(c[0]*=i.scrollRatio.y,c[1]*=i.scrollRatio.x),s.dur=oe()?0:d,setTimeout(function(){null!==c[0]&&"undefined"!=typeof c[0]&&"x"!==r.axis&&i.overflowed[0]&&(s.dir="y",s.overwrite="all",V(n,c[0].toString(),s)),null!==c[1]&&"undefined"!=typeof c[1]&&"y"!==r.axis&&i.overflowed[1]&&(s.dir="x",s.overwrite="none",V(n,c[1].toString(),s))},s.timeout)}})}},stop:function(){var t=f.call(this);return e(t).each(function(){var t=e(this);t.data(a)&&N(t)})},disable:function(t){var o=f.call(this);return e(o).each(function(){var o=e(this);if(o.data(a)){{o.data(a)}X.call(this,"remove"),k.call(this),t&&B.call(this),M.call(this,!0),o.addClass(d[3])}})},destroy:function(){var t=f.call(this);return e(t).each(function(){var n=e(this);if(n.data(a)){var i=n.data(a),r=i.opt,l=e("#mCSB_"+i.idx),s=e("#mCSB_"+i.idx+"_container"),c=e(".mCSB_"+i.idx+"_scrollbar");r.live&&m(r.liveSelector||e(t).selector),X.call(this,"remove"),k.call(this),B.call(this),n.removeData(a),K(this,"mcs"),c.remove(),s.find("img."+d[2]).removeClass(d[2]),l.replaceWith(s.contents()),n.removeClass(o+" _"+a+"_"+i.idx+" "+d[6]+" "+d[7]+" "+d[5]+" "+d[3]).addClass(d[4])}})}},f=function(){return"object"!=typeof e(this)||e(this).length<1?n:this},h=function(t){var o=["rounded","rounded-dark","rounded-dots","rounded-dots-dark"],a=["rounded-dots","rounded-dots-dark","3d","3d-dark","3d-thick","3d-thick-dark","inset","inset-dark","inset-2","inset-2-dark","inset-3","inset-3-dark"],n=["minimal","minimal-dark"],i=["minimal","minimal-dark"],r=["minimal","minimal-dark"];t.autoDraggerLength=e.inArray(t.theme,o)>-1?!1:t.autoDraggerLength,t.autoExpandScrollbar=e.inArray(t.theme,a)>-1?!1:t.autoExpandScrollbar,t.scrollButtons.enable=e.inArray(t.theme,n)>-1?!1:t.scrollButtons.enable,t.autoHideScrollbar=e.inArray(t.theme,i)>-1?!0:t.autoHideScrollbar,t.scrollbarPosition=e.inArray(t.theme,r)>-1?"outside":t.scrollbarPosition},m=function(e){l[e]&&(clearTimeout(l[e]),K(l,e))},p=function(e){return"yx"===e||"xy"===e||"auto"===e?"yx":"x"===e||"horizontal"===e?"x":"y"},g=function(e){return"stepped"===e||"pixels"===e||"step"===e||"click"===e?"stepped":"stepless"},v=function(){var t=e(this),n=t.data(a),i=n.opt,r=i.autoExpandScrollbar?" "+d[1]+"_expand":"",l=["",""],s="yx"===i.axis?"mCSB_vertical_horizontal":"x"===i.axis?"mCSB_horizontal":"mCSB_vertical",c="yx"===i.axis?l[0]+l[1]:"x"===i.axis?l[1]:l[0],u="yx"===i.axis?"":"",f=i.autoHideScrollbar?" "+d[6]:"",h="x"!==i.axis&&"rtl"===n.langDir?" "+d[7]:"";i.setWidth&&t.css("width",i.setWidth),i.setHeight&&t.css("height",i.setHeight),i.setLeft="y"!==i.axis&&"rtl"===n.langDir?"989999px":i.setLeft,t.addClass(o+" _"+a+"_"+n.idx+f+h).wrapInner("");var m=e("#mCSB_"+n.idx),p=e("#mCSB_"+n.idx+"_container");"y"===i.axis||i.advanced.autoExpandHorizontalScroll||p.css("width",x(p)),"outside"===i.scrollbarPosition?("static"===t.css("position")&&t.css("position","relative"),t.css("overflow","visible"),m.addClass("mCSB_outside").after(c)):(m.addClass("mCSB_inside").append(c),p.wrap(u)),w.call(this);var g=[e("#mCSB_"+n.idx+"_dragger_vertical"),e("#mCSB_"+n.idx+"_dragger_horizontal")];g[0].css("min-height",g[0].height()),g[1].css("min-width",g[1].width())},x=function(t){var o=[t[0].scrollWidth,Math.max.apply(Math,t.children().map(function(){return e(this).outerWidth(!0)}).get())],a=t.parent().width();return o[0]>a?o[0]:o[1]>a?o[1]:"100%"},_=function(){var t=e(this),o=t.data(a),n=o.opt,i=e("#mCSB_"+o.idx+"_container");if(n.advanced.autoExpandHorizontalScroll&&"y"!==n.axis){i.css({width:"auto","min-width":0,"overflow-x":"scroll"});var r=Math.ceil(i[0].scrollWidth);3===n.advanced.autoExpandHorizontalScroll||2!==n.advanced.autoExpandHorizontalScroll&&r>i.parent().width()?i.css({width:r,"min-width":"100%","overflow-x":"inherit"}):i.css({"overflow-x":"inherit",position:"absolute"}).wrap("").css({width:Math.ceil(i[0].getBoundingClientRect().right+.4)-Math.floor(i[0].getBoundingClientRect().left),"min-width":"100%",position:"relative"}).unwrap()}},w=function(){var t=e(this),o=t.data(a),n=o.opt,i=e(".mCSB_"+o.idx+"_scrollbar:first"),r=ee(n.scrollButtons.tabindex)?"tabindex='"+n.scrollButtons.tabindex+"'":"",l=["","","",""],s=["x"===n.axis?l[2]:l[0],"x"===n.axis?l[3]:l[1],l[2],l[3]];n.scrollButtons.enable&&i.prepend(s[0]).append(s[1]).next(".mCSB_scrollTools").prepend(s[2]).append(s[3])},S=function(){var t=e(this),o=t.data(a),n=e("#mCSB_"+o.idx),i=e("#mCSB_"+o.idx+"_container"),r=[e("#mCSB_"+o.idx+"_dragger_vertical"),e("#mCSB_"+o.idx+"_dragger_horizontal")],l=[n.height()/i.outerHeight(!1),n.width()/i.outerWidth(!1)],c=[parseInt(r[0].css("min-height")),Math.round(l[0]*r[0].parent().height()),parseInt(r[1].css("min-width")),Math.round(l[1]*r[1].parent().width())],d=s&&c[1]r&&(r=s),c>l&&(l=c),[r>n.height(),l>n.width()]},B=function(){var t=e(this),o=t.data(a),n=o.opt,i=e("#mCSB_"+o.idx),r=e("#mCSB_"+o.idx+"_container"),l=[e("#mCSB_"+o.idx+"_dragger_vertical"),e("#mCSB_"+o.idx+"_dragger_horizontal")];if(N(t),("x"!==n.axis&&!o.overflowed[0]||"y"===n.axis&&o.overflowed[0])&&(l[0].add(r).css("top",0),V(t,"_resetY")),"y"!==n.axis&&!o.overflowed[1]||"x"===n.axis&&o.overflowed[1]){var s=dx=0;"rtl"===o.langDir&&(s=i.width()-r.outerWidth(!1),dx=Math.abs(s/o.scrollRatio.x)),r.css("left",s),l[1].css("left",dx),V(t,"_resetX")}},T=function(){function t(){r=setTimeout(function(){e.event.special.mousewheel?(clearTimeout(r),R.call(o[0])):t()},100)}var o=e(this),n=o.data(a),i=n.opt;if(!n.bindEvents){if(I.call(this),i.contentTouchScroll&&D.call(this),E.call(this),i.mouseWheel.enable){var r;t()}L.call(this),P.call(this),i.advanced.autoScrollOnFocus&&z.call(this),i.scrollButtons.enable&&H.call(this),i.keyboard.enable&&U.call(this),n.bindEvents=!0}},k=function(){var t=e(this),o=t.data(a),n=o.opt,i=a+"_"+o.idx,r=".mCSB_"+o.idx+"_scrollbar",l=e("#mCSB_"+o.idx+",#mCSB_"+o.idx+"_container,#mCSB_"+o.idx+"_container_wrapper,"+r+" ."+d[12]+",#mCSB_"+o.idx+"_dragger_vertical,#mCSB_"+o.idx+"_dragger_horizontal,"+r+">a"),s=e("#mCSB_"+o.idx+"_container");n.advanced.releaseDraggableSelectors&&l.add(e(n.advanced.releaseDraggableSelectors)),n.advanced.extraDraggableSelectors&&l.add(e(n.advanced.extraDraggableSelectors)),o.bindEvents&&(e(document).add(e(!W()||top.document)).unbind("."+i),l.each(function(){e(this).unbind("."+i)}),clearTimeout(t[0]._focusTimeout),K(t[0],"_focusTimeout"),clearTimeout(o.sequential.step),K(o.sequential,"step"),clearTimeout(s[0].onCompleteTimeout),K(s[0],"onCompleteTimeout"),o.bindEvents=!1)},M=function(t){var o=e(this),n=o.data(a),i=n.opt,r=e("#mCSB_"+n.idx+"_container_wrapper"),l=r.length?r:e("#mCSB_"+n.idx+"_container"),s=[e("#mCSB_"+n.idx+"_scrollbar_vertical"),e("#mCSB_"+n.idx+"_scrollbar_horizontal")],c=[s[0].find(".mCSB_dragger"),s[1].find(".mCSB_dragger")];"x"!==i.axis&&(n.overflowed[0]&&!t?(s[0].add(c[0]).add(s[0].children("a")).css("display","block"),l.removeClass(d[8]+" "+d[10])):(i.alwaysShowScrollbar?(2!==i.alwaysShowScrollbar&&c[0].css("display","none"),l.removeClass(d[10])):(s[0].css("display","none"),l.addClass(d[10])),l.addClass(d[8]))),"y"!==i.axis&&(n.overflowed[1]&&!t?(s[1].add(c[1]).add(s[1].children("a")).css("display","block"),l.removeClass(d[9]+" "+d[11])):(i.alwaysShowScrollbar?(2!==i.alwaysShowScrollbar&&c[1].css("display","none"),l.removeClass(d[11])):(s[1].css("display","none"),l.addClass(d[11])),l.addClass(d[9]))),n.overflowed[0]||n.overflowed[1]?o.removeClass(d[5]):o.addClass(d[5])},O=function(t){var o=t.type,a=t.target.ownerDocument!==document?[e(frameElement).offset().top,e(frameElement).offset().left]:null,n=W()&&t.target.ownerDocument!==top.document?[e(t.view.frameElement).offset().top,e(t.view.frameElement).offset().left]:[0,0];switch(o){case"pointerdown":case"MSPointerDown":case"pointermove":case"MSPointerMove":case"pointerup":case"MSPointerUp":return a?[t.originalEvent.pageY-a[0]+n[0],t.originalEvent.pageX-a[1]+n[1],!1]:[t.originalEvent.pageY,t.originalEvent.pageX,!1];case"touchstart":case"touchmove":case"touchend":var i=t.originalEvent.touches[0]||t.originalEvent.changedTouches[0],r=t.originalEvent.touches.length||t.originalEvent.changedTouches.length;return t.target.ownerDocument!==document?[i.screenY,i.screenX,r>1]:[i.pageY,i.pageX,r>1];default:return a?[t.pageY-a[0]+n[0],t.pageX-a[1]+n[1],!1]:[t.pageY,t.pageX,!1]}},I=function(){function t(e){var t=m.find("iframe");if(t.length){var o=e?"auto":"none";t.css("pointer-events",o)}}function o(e,t,o,a){if(m[0].idleTimer=u.scrollInertia<233?250:0,n.attr("id")===h[1])var i="x",r=(n[0].offsetLeft-t+a)*d.scrollRatio.x;else var i="y",r=(n[0].offsetTop-e+o)*d.scrollRatio.y;V(l,r.toString(),{dir:i,drag:!0})}var n,i,r,l=e(this),d=l.data(a),u=d.opt,f=a+"_"+d.idx,h=["mCSB_"+d.idx+"_dragger_vertical","mCSB_"+d.idx+"_dragger_horizontal"],m=e("#mCSB_"+d.idx+"_container"),p=e("#"+h[0]+",#"+h[1]),g=u.advanced.releaseDraggableSelectors?p.add(e(u.advanced.releaseDraggableSelectors)):p,v=u.advanced.extraDraggableSelectors?e(!W()||top.document).add(e(u.advanced.extraDraggableSelectors)):e(!W()||top.document);p.bind("mousedown."+f+" touchstart."+f+" pointerdown."+f+" MSPointerDown."+f,function(o){if(o.stopImmediatePropagation(),o.preventDefault(),Z(o)){c=!0,s&&(document.onselectstart=function(){return!1}),t(!1),N(l),n=e(this);var a=n.offset(),d=O(o)[0]-a.top,f=O(o)[1]-a.left,h=n.height()+a.top,m=n.width()+a.left;h>d&&d>0&&m>f&&f>0&&(i=d,r=f),C(n,"active",u.autoExpandScrollbar)}}).bind("touchmove."+f,function(e){e.stopImmediatePropagation(),e.preventDefault();var t=n.offset(),a=O(e)[0]-t.top,l=O(e)[1]-t.left;o(i,r,a,l)}),e(document).add(v).bind("mousemove."+f+" pointermove."+f+" MSPointerMove."+f,function(e){if(n){var t=n.offset(),a=O(e)[0]-t.top,l=O(e)[1]-t.left;if(i===a&&r===l)return;o(i,r,a,l)}}).add(g).bind("mouseup."+f+" touchend."+f+" pointerup."+f+" MSPointerUp."+f,function(e){n&&(C(n,"active",u.autoExpandScrollbar),n=null),c=!1,s&&(document.onselectstart=null),t(!0)})},D=function(){function o(e){if(!$(e)||c||O(e)[2])return void(t=0);t=1,b=0,C=0,d=1,y.removeClass("mCS_touch_action");var o=I.offset();u=O(e)[0]-o.top,f=O(e)[1]-o.left,z=[O(e)[0],O(e)[1]]}function n(e){if($(e)&&!c&&!O(e)[2]&&(T.documentTouchScroll||e.preventDefault(),e.stopImmediatePropagation(),(!C||b)&&d)){g=G();var t=M.offset(),o=O(e)[0]-t.top,a=O(e)[1]-t.left,n="mcsLinearOut";if(E.push(o),R.push(a),z[2]=Math.abs(O(e)[0]-z[0]),z[3]=Math.abs(O(e)[1]-z[1]),B.overflowed[0])var i=D[0].parent().height()-D[0].height(),r=u-o>0&&o-u>-(i*B.scrollRatio.y)&&(2*z[3]0&&a-f>-(l*B.scrollRatio.x)&&(2*z[2]30)){_=1e3/(v-p);var n="mcsEaseOut",i=2.5>_,r=i?[E[E.length-2],R[R.length-2]]:[0,0];x=i?[o-r[0],a-r[1]]:[o-h,a-m];var u=[Math.abs(x[0]),Math.abs(x[1])];_=i?[Math.abs(x[0]/4),Math.abs(x[1]/4)]:[_,_];var f=[Math.abs(I[0].offsetTop)-x[0]*l(u[0]/_[0],_[0]),Math.abs(I[0].offsetLeft)-x[1]*l(u[1]/_[1],_[1])];w="yx"===T.axis?[f[0],f[1]]:"x"===T.axis?[null,f[1]]:[f[0],null],S=[4*u[0]+T.scrollInertia,4*u[1]+T.scrollInertia];var y=parseInt(T.contentTouchScroll)||0;w[0]=u[0]>y?w[0]:0,w[1]=u[1]>y?w[1]:0,B.overflowed[0]&&s(w[0],S[0],n,"y",L,!1),B.overflowed[1]&&s(w[1],S[1],n,"x",L,!1)}}}function l(e,t){var o=[1.5*t,2*t,t/1.5,t/2];return e>90?t>4?o[0]:o[3]:e>60?t>3?o[3]:o[2]:e>30?t>8?o[1]:t>6?o[0]:t>4?t:o[2]:t>8?t:o[3]}function s(e,t,o,a,n,i){e&&V(y,e.toString(),{dur:t,scrollEasing:o,dir:a,overwrite:n,drag:i})}var d,u,f,h,m,p,g,v,x,_,w,S,b,C,y=e(this),B=y.data(a),T=B.opt,k=a+"_"+B.idx,M=e("#mCSB_"+B.idx),I=e("#mCSB_"+B.idx+"_container"),D=[e("#mCSB_"+B.idx+"_dragger_vertical"),e("#mCSB_"+B.idx+"_dragger_horizontal")],E=[],R=[],A=0,L="yx"===T.axis?"none":"all",z=[],P=I.find("iframe"),H=["touchstart."+k+" pointerdown."+k+" MSPointerDown."+k,"touchmove."+k+" pointermove."+k+" MSPointerMove."+k,"touchend."+k+" pointerup."+k+" MSPointerUp."+k],U=void 0!==document.body.style.touchAction;I.bind(H[0],function(e){o(e)}).bind(H[1],function(e){n(e)}),M.bind(H[0],function(e){i(e)}).bind(H[2],function(e){r(e)}),P.length&&P.each(function(){e(this).load(function(){W(this)&&e(this.contentDocument||this.contentWindow.document).bind(H[0],function(e){o(e),i(e)}).bind(H[1],function(e){n(e)}).bind(H[2],function(e){r(e)})})})},E=function(){function o(){return window.getSelection?window.getSelection().toString():document.selection&&"Control"!=document.selection.type?document.selection.createRange().text:0}function n(e,t,o){d.type=o&&i?"stepped":"stepless",d.scrollAmount=10,F(r,e,t,"mcsLinearOut",o?60:null)}var i,r=e(this),l=r.data(a),s=l.opt,d=l.sequential,u=a+"_"+l.idx,f=e("#mCSB_"+l.idx+"_container"),h=f.parent();f.bind("mousedown."+u,function(e){t||i||(i=1,c=!0)}).add(document).bind("mousemove."+u,function(e){if(!t&&i&&o()){var a=f.offset(),r=O(e)[0]-a.top+f[0].offsetTop,c=O(e)[1]-a.left+f[0].offsetLeft;r>0&&r0&&cr?n("on",38):r>h.height()&&n("on",40)),"y"!==s.axis&&l.overflowed[1]&&(0>c?n("on",37):c>h.width()&&n("on",39)))}}).bind("mouseup."+u+" dragend."+u,function(e){t||(i&&(i=0,n("off",null)),c=!1)})},R=function(){function t(t,a){if(N(o),!A(o,t.target)){var r="auto"!==i.mouseWheel.deltaFactor?parseInt(i.mouseWheel.deltaFactor):s&&t.deltaFactor<100?100:t.deltaFactor||100,d=i.scrollInertia;if("x"===i.axis||"x"===i.mouseWheel.axis)var u="x",f=[Math.round(r*n.scrollRatio.x),parseInt(i.mouseWheel.scrollAmount)],h="auto"!==i.mouseWheel.scrollAmount?f[1]:f[0]>=l.width()?.9*l.width():f[0],m=Math.abs(e("#mCSB_"+n.idx+"_container")[0].offsetLeft),p=c[1][0].offsetLeft,g=c[1].parent().width()-c[1].width(),v=t.deltaX||t.deltaY||a;else var u="y",f=[Math.round(r*n.scrollRatio.y),parseInt(i.mouseWheel.scrollAmount)],h="auto"!==i.mouseWheel.scrollAmount?f[1]:f[0]>=l.height()?.9*l.height():f[0],m=Math.abs(e("#mCSB_"+n.idx+"_container")[0].offsetTop),p=c[0][0].offsetTop,g=c[0].parent().height()-c[0].height(),v=t.deltaY||a;"y"===u&&!n.overflowed[0]||"x"===u&&!n.overflowed[1]||((i.mouseWheel.invert||t.webkitDirectionInvertedFromDevice)&&(v=-v),i.mouseWheel.normalizeDelta&&(v=0>v?-1:1),(v>0&&0!==p||0>v&&p!==g||i.mouseWheel.preventDefault)&&(t.stopImmediatePropagation(),t.preventDefault()),t.deltaFactor<2&&!i.mouseWheel.normalizeDelta&&(h=t.deltaFactor,d=17),V(o,(m-v*h).toString(),{dir:u,dur:d}))}}if(e(this).data(a)){var o=e(this),n=o.data(a),i=n.opt,r=a+"_"+n.idx,l=e("#mCSB_"+n.idx),c=[e("#mCSB_"+n.idx+"_dragger_vertical"),e("#mCSB_"+n.idx+"_dragger_horizontal")],d=e("#mCSB_"+n.idx+"_container").find("iframe");d.length&&d.each(function(){e(this).load(function(){W(this)&&e(this.contentDocument||this.contentWindow.document).bind("mousewheel."+r,function(e,o){t(e,o)})})}),l.bind("mousewheel."+r,function(e,o){t(e,o)})}},W=function(e){var t=null;if(e){try{var o=e.contentDocument||e.contentWindow.document;t=o.body.innerHTML}catch(a){}return null!==t}try{var o=top.document;t=o.body.innerHTML}catch(a){}return null!==t},A=function(t,o){var n=o.nodeName.toLowerCase(),i=t.data(a).opt.mouseWheel.disableOver,r=["select","textarea"];return e.inArray(n,i)>-1&&!(e.inArray(n,r)>-1&&!e(o).is(":focus"))},L=function(){var t,o=e(this),n=o.data(a),i=a+"_"+n.idx,r=e("#mCSB_"+n.idx+"_container"),l=r.parent(),s=e(".mCSB_"+n.idx+"_scrollbar ."+d[12]);s.bind("mousedown."+i+" touchstart."+i+" pointerdown."+i+" MSPointerDown."+i,function(o){c=!0,e(o.target).hasClass("mCSB_dragger")||(t=1)}).bind("touchend."+i+" pointerup."+i+" MSPointerUp."+i,function(e){c=!1}).bind("click."+i,function(a){if(t&&(t=0,e(a.target).hasClass(d[12])||e(a.target).hasClass("mCSB_draggerRail"))){N(o);var i=e(this),s=i.find(".mCSB_dragger");if(i.parent(".mCSB_scrollTools_horizontal").length>0){if(!n.overflowed[1])return;var c="x",u=a.pageX>s.offset().left?-1:1,f=Math.abs(r[0].offsetLeft)-.9*u*l.width()}else{if(!n.overflowed[0])return;var c="y",u=a.pageY>s.offset().top?-1:1,f=Math.abs(r[0].offsetTop)-.9*u*l.height()}V(o,f.toString(),{dir:c,scrollEasing:"mcsEaseInOut"})}})},z=function(){var t=e(this),o=t.data(a),n=o.opt,i=a+"_"+o.idx,r=e("#mCSB_"+o.idx+"_container"),l=r.parent();r.bind("focusin."+i,function(o){var a=e(document.activeElement),i=r.find(".mCustomScrollBox").length,s=0;a.is(n.advanced.autoScrollOnFocus)&&(N(t),clearTimeout(t[0]._focusTimeout),t[0]._focusTimer=i?(s+17)*i:0,t[0]._focusTimeout=setTimeout(function(){var e=[te(a)[0],te(a)[1]],o=[r[0].offsetTop,r[0].offsetLeft],i=[o[0]+e[0]>=0&&o[0]+e[0]=0&&o[0]+e[1]a");s.bind("mousedown."+r+" touchstart."+r+" pointerdown."+r+" MSPointerDown."+r+" mouseup."+r+" touchend."+r+" pointerup."+r+" MSPointerUp."+r+" mouseout."+r+" pointerout."+r+" MSPointerOut."+r+" click."+r,function(a){function r(e,o){i.scrollAmount=n.scrollButtons.scrollAmount,F(t,e,o)}if(a.preventDefault(),Z(a)){var l=e(this).attr("class");switch(i.type=n.scrollButtons.scrollType,a.type){case"mousedown":case"touchstart":case"pointerdown":case"MSPointerDown":if("stepped"===i.type)return;c=!0,o.tweenRunning=!1,r("on",l);break;case"mouseup":case"touchend":case"pointerup":case"MSPointerUp":case"mouseout":case"pointerout":case"MSPointerOut":if("stepped"===i.type)return;c=!1,i.dir&&r("off",l);break;case"click":if("stepped"!==i.type||o.tweenRunning)return;r("on",l)}}})},U=function(){function t(t){function a(e,t){r.type=i.keyboard.scrollType,r.scrollAmount=i.keyboard.scrollAmount,"stepped"===r.type&&n.tweenRunning||F(o,e,t)}switch(t.type){case"blur":n.tweenRunning&&r.dir&&a("off",null);break;case"keydown":case"keyup":var l=t.keyCode?t.keyCode:t.which,s="on";if("x"!==i.axis&&(38===l||40===l)||"y"!==i.axis&&(37===l||39===l)){if((38===l||40===l)&&!n.overflowed[0]||(37===l||39===l)&&!n.overflowed[1])return;"keyup"===t.type&&(s="off"),e(document.activeElement).is(u)||(t.preventDefault(),t.stopImmediatePropagation(),a(s,l))}else if(33===l||34===l){if((n.overflowed[0]||n.overflowed[1])&&(t.preventDefault(),t.stopImmediatePropagation()),"keyup"===t.type){N(o);var f=34===l?-1:1;if("x"===i.axis||"yx"===i.axis&&n.overflowed[1]&&!n.overflowed[0])var h="x",m=Math.abs(c[0].offsetLeft)-.9*f*d.width();else var h="y",m=Math.abs(c[0].offsetTop)-.9*f*d.height();V(o,m.toString(),{dir:h,scrollEasing:"mcsEaseInOut"})}}else if((35===l||36===l)&&!e(document.activeElement).is(u)&&((n.overflowed[0]||n.overflowed[1])&&(t.preventDefault(),t.stopImmediatePropagation()),"keyup"===t.type)){if("x"===i.axis||"yx"===i.axis&&n.overflowed[1]&&!n.overflowed[0])var h="x",m=35===l?Math.abs(d.width()-c.outerWidth(!1)):0;else var h="y",m=35===l?Math.abs(d.height()-c.outerHeight(!1)):0;V(o,m.toString(),{dir:h,scrollEasing:"mcsEaseInOut"})}}}var o=e(this),n=o.data(a),i=n.opt,r=n.sequential,l=a+"_"+n.idx,s=e("#mCSB_"+n.idx),c=e("#mCSB_"+n.idx+"_container"),d=c.parent(),u="input,textarea,select,datalist,keygen,[contenteditable='true']",f=c.find("iframe"),h=["blur."+l+" keydown."+l+" keyup."+l];f.length&&f.each(function(){e(this).load(function(){W(this)&&e(this.contentDocument||this.contentWindow.document).bind(h[0],function(e){t(e)})})}),s.attr("tabindex","0").bind(h[0],function(e){t(e)})},F=function(t,o,n,i,r){function l(e){u.snapAmount&&(f.scrollAmount=u.snapAmount instanceof Array?"x"===f.dir[0]?u.snapAmount[1]:u.snapAmount[0]:u.snapAmount);var o="stepped"!==f.type,a=r?r:e?o?p/1.5:g:1e3/60,n=e?o?7.5:40:2.5,s=[Math.abs(h[0].offsetTop),Math.abs(h[0].offsetLeft)],d=[c.scrollRatio.y>10?10:c.scrollRatio.y,c.scrollRatio.x>10?10:c.scrollRatio.x],m="x"===f.dir[0]?s[1]+f.dir[1]*d[1]*n:s[0]+f.dir[1]*d[0]*n,v="x"===f.dir[0]?s[1]+f.dir[1]*parseInt(f.scrollAmount):s[0]+f.dir[1]*parseInt(f.scrollAmount),x="auto"!==f.scrollAmount?v:m,_=i?i:e?o?"mcsLinearOut":"mcsEaseInOut":"mcsLinear",w=e?!0:!1;return e&&17>a&&(x="x"===f.dir[0]?s[1]:s[0]),V(t,x.toString(),{dir:f.dir[0],scrollEasing:_,dur:a,onComplete:w}),e?void(f.dir=!1):(clearTimeout(f.step),void(f.step=setTimeout(function(){l()},a)))}function s(){clearTimeout(f.step),K(f,"step"),N(t)}var c=t.data(a),u=c.opt,f=c.sequential,h=e("#mCSB_"+c.idx+"_container"),m="stepped"===f.type?!0:!1,p=u.scrollInertia<26?26:u.scrollInertia,g=u.scrollInertia<1?17:u.scrollInertia;switch(o){case"on":if(f.dir=[n===d[16]||n===d[15]||39===n||37===n?"x":"y",n===d[13]||n===d[15]||38===n||37===n?-1:1],N(t),ee(n)&&"stepped"===f.type)return;l(m);break;case"off":s(),(m||c.tweenRunning&&f.dir)&&l(!0)}},q=function(t){var o=e(this).data(a).opt,n=[];return"function"==typeof t&&(t=t()),t instanceof Array?n=t.length>1?[t[0],t[1]]:"x"===o.axis?[null,t[0]]:[t[0],null]:(n[0]=t.y?t.y:t.x||"x"===o.axis?null:t,n[1]=t.x?t.x:t.y||"y"===o.axis?null:t),"function"==typeof n[0]&&(n[0]=n[0]()),"function"==typeof n[1]&&(n[1]=n[1]()),n},Y=function(t,o){if(null!=t&&"undefined"!=typeof t){var n=e(this),i=n.data(a),r=i.opt,l=e("#mCSB_"+i.idx+"_container"),s=l.parent(),c=typeof t;o||(o="x"===r.axis?"x":"y");var d="x"===o?l.outerWidth(!1):l.outerHeight(!1),f="x"===o?l[0].offsetLeft:l[0].offsetTop,h="x"===o?"left":"top";switch(c){case"function":return t();case"object":var m=t.jquery?t:e(t);if(!m.length)return;return"x"===o?te(m)[1]:te(m)[0];case"string":case"number":if(ee(t))return Math.abs(t);if(-1!==t.indexOf("%"))return Math.abs(d*parseInt(t)/100);if(-1!==t.indexOf("-="))return Math.abs(f-parseInt(t.split("-=")[1]));if(-1!==t.indexOf("+=")){var p=f+parseInt(t.split("+=")[1]);return p>=0?0:Math.abs(p)}if(-1!==t.indexOf("px")&&ee(t.split("px")[0]))return Math.abs(t.split("px")[0]);if("top"===t||"left"===t)return 0;if("bottom"===t)return Math.abs(s.height()-l.outerHeight(!1));if("right"===t)return Math.abs(s.width()-l.outerWidth(!1));if("first"===t||"last"===t){var m=l.find(":"+t);return"x"===o?te(m)[1]:te(m)[0]}return e(t).length?"x"===o?te(e(t))[1]:te(e(t))[0]:(l.css(h,t),void u.update.call(null,n[0]))}}},X=function(t){function o(){return clearTimeout(f[0].autoUpdate),0===l.parents("html").length?void(l=null):void(f[0].autoUpdate=setTimeout(function(){return c.advanced.updateOnSelectorChange&&(s.poll.change.n=i(),s.poll.change.n!==s.poll.change.o)?(s.poll.change.o=s.poll.change.n,void r(3)):c.advanced.updateOnContentResize&&(s.poll.size.n=l[0].scrollHeight+l[0].scrollWidth+f[0].offsetHeight+l[0].offsetHeight+l[0].offsetWidth,s.poll.size.n!==s.poll.size.o)?(s.poll.size.o=s.poll.size.n,void r(1)):!c.advanced.updateOnImageLoad||"auto"===c.advanced.updateOnImageLoad&&"y"===c.axis||(s.poll.img.n=f.find("img").length,s.poll.img.n===s.poll.img.o)?void((c.advanced.updateOnSelectorChange||c.advanced.updateOnContentResize||c.advanced.updateOnImageLoad)&&o()):(s.poll.img.o=s.poll.img.n,void f.find("img").each(function(){n(this)}))},c.advanced.autoUpdateTimeout))}function n(t){function o(e,t){return function(){return t.apply(e,arguments)}}function a(){this.onload=null,e(t).addClass(d[2]),r(2)}if(e(t).hasClass(d[2]))return void r();var n=new Image;n.onload=o(n,a),n.src=t.src}function i(){c.advanced.updateOnSelectorChange===!0&&(c.advanced.updateOnSelectorChange="*");var e=0,t=f.find(c.advanced.updateOnSelectorChange);
5 |
6 | return c.advanced.updateOnSelectorChange&&t.length>0&&t.each(function(){e+=this.offsetHeight+this.offsetWidth}),e}function r(e){clearTimeout(f[0].autoUpdate),u.update.call(null,l[0],e)}var l=e(this),s=l.data(a),c=s.opt,f=e("#mCSB_"+s.idx+"_container");return t?(clearTimeout(f[0].autoUpdate),void K(f[0],"autoUpdate")):void o()},j=function(e,t,o){return Math.round(e/t)*t-o},N=function(t){var o=t.data(a),n=e("#mCSB_"+o.idx+"_container,#mCSB_"+o.idx+"_container_wrapper,#mCSB_"+o.idx+"_dragger_vertical,#mCSB_"+o.idx+"_dragger_horizontal");n.each(function(){J.call(this)})},V=function(t,o,n){function i(e){return s&&c.callbacks[e]&&"function"==typeof c.callbacks[e]}function r(){return[c.callbacks.alwaysTriggerOffsets||w>=S[0]+y,c.callbacks.alwaysTriggerOffsets||-B>=w]}function l(){var e=[h[0].offsetTop,h[0].offsetLeft],o=[x[0].offsetTop,x[0].offsetLeft],a=[h.outerHeight(!1),h.outerWidth(!1)],i=[f.height(),f.width()];t[0].mcs={content:h,top:e[0],left:e[1],draggerTop:o[0],draggerLeft:o[1],topPct:Math.round(100*Math.abs(e[0])/(Math.abs(a[0])-i[0])),leftPct:Math.round(100*Math.abs(e[1])/(Math.abs(a[1])-i[1])),direction:n.dir}}var s=t.data(a),c=s.opt,d={trigger:"internal",dir:"y",scrollEasing:"mcsEaseOut",drag:!1,dur:c.scrollInertia,overwrite:"all",callbacks:!0,onStart:!0,onUpdate:!0,onComplete:!0},n=e.extend(d,n),u=[n.dur,n.drag?0:n.dur],f=e("#mCSB_"+s.idx),h=e("#mCSB_"+s.idx+"_container"),m=h.parent(),p=c.callbacks.onTotalScrollOffset?q.call(t,c.callbacks.onTotalScrollOffset):[0,0],g=c.callbacks.onTotalScrollBackOffset?q.call(t,c.callbacks.onTotalScrollBackOffset):[0,0];if(s.trigger=n.trigger,(0!==m.scrollTop()||0!==m.scrollLeft())&&(e(".mCSB_"+s.idx+"_scrollbar").css("visibility","visible"),m.scrollTop(0).scrollLeft(0)),"_resetY"!==o||s.contentReset.y||(i("onOverflowYNone")&&c.callbacks.onOverflowYNone.call(t[0]),s.contentReset.y=1),"_resetX"!==o||s.contentReset.x||(i("onOverflowXNone")&&c.callbacks.onOverflowXNone.call(t[0]),s.contentReset.x=1),"_resetY"!==o&&"_resetX"!==o){if(!s.contentReset.y&&t[0].mcs||!s.overflowed[0]||(i("onOverflowY")&&c.callbacks.onOverflowY.call(t[0]),s.contentReset.x=null),!s.contentReset.x&&t[0].mcs||!s.overflowed[1]||(i("onOverflowX")&&c.callbacks.onOverflowX.call(t[0]),s.contentReset.x=null),c.snapAmount){var v=c.snapAmount instanceof Array?"x"===n.dir?c.snapAmount[1]:c.snapAmount[0]:c.snapAmount;o=j(o,v,c.snapOffset)}switch(n.dir){case"x":var x=e("#mCSB_"+s.idx+"_dragger_horizontal"),_="left",w=h[0].offsetLeft,S=[f.width()-h.outerWidth(!1),x.parent().width()-x.width()],b=[o,0===o?0:o/s.scrollRatio.x],y=p[1],B=g[1],T=y>0?y/s.scrollRatio.x:0,k=B>0?B/s.scrollRatio.x:0;break;case"y":var x=e("#mCSB_"+s.idx+"_dragger_vertical"),_="top",w=h[0].offsetTop,S=[f.height()-h.outerHeight(!1),x.parent().height()-x.height()],b=[o,0===o?0:o/s.scrollRatio.y],y=p[0],B=g[0],T=y>0?y/s.scrollRatio.y:0,k=B>0?B/s.scrollRatio.y:0}b[1]<0||0===b[0]&&0===b[1]?b=[0,0]:b[1]>=S[1]?b=[S[0],S[1]]:b[0]=-b[0],t[0].mcs||(l(),i("onInit")&&c.callbacks.onInit.call(t[0])),clearTimeout(h[0].onCompleteTimeout),Q(x[0],_,Math.round(b[1]),u[1],n.scrollEasing),(s.tweenRunning||!(0===w&&b[0]>=0||w===S[0]&&b[0]<=S[0]))&&Q(h[0],_,Math.round(b[0]),u[0],n.scrollEasing,n.overwrite,{onStart:function(){n.callbacks&&n.onStart&&!s.tweenRunning&&(i("onScrollStart")&&(l(),c.callbacks.onScrollStart.call(t[0])),s.tweenRunning=!0,C(x),s.cbOffsets=r())},onUpdate:function(){n.callbacks&&n.onUpdate&&i("whileScrolling")&&(l(),c.callbacks.whileScrolling.call(t[0]))},onComplete:function(){if(n.callbacks&&n.onComplete){"yx"===c.axis&&clearTimeout(h[0].onCompleteTimeout);var e=h[0].idleTimer||0;h[0].onCompleteTimeout=setTimeout(function(){i("onScroll")&&(l(),c.callbacks.onScroll.call(t[0])),i("onTotalScroll")&&b[1]>=S[1]-T&&s.cbOffsets[0]&&(l(),c.callbacks.onTotalScroll.call(t[0])),i("onTotalScrollBack")&&b[1]<=k&&s.cbOffsets[1]&&(l(),c.callbacks.onTotalScrollBack.call(t[0])),s.tweenRunning=!1,h[0].idleTimer=0,C(x,"hide")},e)}}})}},Q=function(e,t,o,a,n,i,r){function l(){S.stop||(x||m.call(),x=G()-v,s(),x>=S.time&&(S.time=x>S.time?x+f-(x-S.time):x+f-1,S.time0?(S.currVal=u(S.time,_,b,a,n),w[t]=Math.round(S.currVal)+"px"):w[t]=o+"px",p.call()}function c(){f=1e3/60,S.time=x+f,h=window.requestAnimationFrame?window.requestAnimationFrame:function(e){return s(),setTimeout(e,.01)},S.id=h(l)}function d(){null!=S.id&&(window.requestAnimationFrame?window.cancelAnimationFrame(S.id):clearTimeout(S.id),S.id=null)}function u(e,t,o,a,n){switch(n){case"linear":case"mcsLinear":return o*e/a+t;case"mcsLinearOut":return e/=a,e--,o*Math.sqrt(1-e*e)+t;case"easeInOutSmooth":return e/=a/2,1>e?o/2*e*e+t:(e--,-o/2*(e*(e-2)-1)+t);case"easeInOutStrong":return e/=a/2,1>e?o/2*Math.pow(2,10*(e-1))+t:(e--,o/2*(-Math.pow(2,-10*e)+2)+t);case"easeInOut":case"mcsEaseInOut":return e/=a/2,1>e?o/2*e*e*e+t:(e-=2,o/2*(e*e*e+2)+t);case"easeOutSmooth":return e/=a,e--,-o*(e*e*e*e-1)+t;case"easeOutStrong":return o*(-Math.pow(2,-10*e/a)+1)+t;case"easeOut":case"mcsEaseOut":default:var i=(e/=a)*e,r=i*e;return t+o*(.499999999999997*r*i+-2.5*i*i+5.5*r+-6.5*i+4*e)}}e._mTween||(e._mTween={top:{},left:{}});var f,h,r=r||{},m=r.onStart||function(){},p=r.onUpdate||function(){},g=r.onComplete||function(){},v=G(),x=0,_=e.offsetTop,w=e.style,S=e._mTween[t];"left"===t&&(_=e.offsetLeft);var b=o-_;S.stop=0,"none"!==i&&d(),c()},G=function(){return window.performance&&window.performance.now?window.performance.now():window.performance&&window.performance.webkitNow?window.performance.webkitNow():Date.now?Date.now():(new Date).getTime()},J=function(){var e=this;e._mTween||(e._mTween={top:{},left:{}});for(var t=["top","left"],o=0;o=0&&a[0]+te(n)[0]=0&&a[1]+te(n)[1].mCSB_container{margin-right:30px}.mCSB_container.mCS_no_scrollbar_y.mCS_y_hidden{margin-right:0}.mCS-dir-rtl>.mCSB_inside>.mCSB_container{margin-right:0;margin-left:30px}.mCS-dir-rtl>.mCSB_inside>.mCSB_container.mCS_no_scrollbar_y.mCS_y_hidden{margin-left:0}.mCSB_scrollTools{position:absolute;width:16px;height:auto;left:auto;top:0;right:0;bottom:0;opacity:.75;filter:"alpha(opacity=75)";-ms-filter:"alpha(opacity=75)"}.mCSB_outside+.mCSB_scrollTools{right:-26px}.mCS-dir-rtl>.mCSB_inside>.mCSB_scrollTools,.mCS-dir-rtl>.mCSB_outside+.mCSB_scrollTools{right:auto;left:0}.mCS-dir-rtl>.mCSB_outside+.mCSB_scrollTools{left:-26px}.mCSB_scrollTools .mCSB_draggerContainer{position:absolute;top:0;left:0;bottom:0;right:0;height:auto}.mCSB_scrollTools a+.mCSB_draggerContainer{margin:20px 0}.mCSB_scrollTools .mCSB_draggerRail{width:2px;height:100%;margin:0 auto;-webkit-border-radius:16px;-moz-border-radius:16px;border-radius:16px}.mCSB_scrollTools .mCSB_dragger{cursor:pointer;width:100%;height:30px;z-index:1}.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{position:relative;width:4px;height:100%;margin:0 auto;-webkit-border-radius:16px;-moz-border-radius:16px;border-radius:16px;text-align:center}.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar,.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar{width:12px}.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded+.mCSB_draggerRail,.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{width:8px}.mCSB_scrollTools .mCSB_buttonDown,.mCSB_scrollTools .mCSB_buttonUp{display:block;position:absolute;height:20px;width:100%;overflow:hidden;margin:0 auto;cursor:pointer}.mCSB_scrollTools .mCSB_buttonDown{bottom:0}.mCSB_horizontal.mCSB_inside>.mCSB_container{margin-right:0;margin-bottom:30px}.mCSB_horizontal.mCSB_outside>.mCSB_container{min-height:100%}.mCSB_horizontal>.mCSB_container.mCS_no_scrollbar_x.mCS_x_hidden{margin-bottom:0}.mCSB_scrollTools.mCSB_scrollTools_horizontal{width:auto;height:16px;top:auto;right:0;bottom:0;left:0}.mCustomScrollBox+.mCSB_scrollTools+.mCSB_scrollTools.mCSB_scrollTools_horizontal,.mCustomScrollBox+.mCSB_scrollTools.mCSB_scrollTools_horizontal{bottom:-26px}.mCSB_scrollTools.mCSB_scrollTools_horizontal a+.mCSB_draggerContainer{margin:0 20px}.mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_draggerRail{width:100%;height:2px;margin:7px 0}.mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_dragger{width:30px;height:100%;left:0}.mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{width:100%;height:4px;margin:6px auto}.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar,.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar{height:12px;margin:2px auto}.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded+.mCSB_draggerRail,.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{height:8px;margin:4px 0}.mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_buttonLeft,.mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_buttonRight{display:block;position:absolute;width:20px;height:100%;overflow:hidden;margin:0 auto;cursor:pointer}.mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_buttonLeft{left:0}.mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_buttonRight{right:0}.mCSB_container_wrapper{position:absolute;height:auto;width:auto;overflow:hidden;top:0;left:0;right:0;bottom:0;margin-right:30px;margin-bottom:30px}.mCSB_container_wrapper>.mCSB_container{padding-right:30px;padding-bottom:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.mCSB_vertical_horizontal>.mCSB_scrollTools.mCSB_scrollTools_vertical{bottom:20px}.mCSB_vertical_horizontal>.mCSB_scrollTools.mCSB_scrollTools_horizontal{right:20px}.mCSB_container_wrapper.mCS_no_scrollbar_x.mCS_x_hidden+.mCSB_scrollTools.mCSB_scrollTools_vertical{bottom:0}.mCS-dir-rtl>.mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside>.mCSB_scrollTools.mCSB_scrollTools_horizontal,.mCSB_container_wrapper.mCS_no_scrollbar_y.mCS_y_hidden+.mCSB_scrollTools~.mCSB_scrollTools.mCSB_scrollTools_horizontal{right:0}.mCS-dir-rtl>.mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside>.mCSB_scrollTools.mCSB_scrollTools_horizontal{left:20px}.mCS-dir-rtl>.mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside>.mCSB_container_wrapper.mCS_no_scrollbar_y.mCS_y_hidden+.mCSB_scrollTools~.mCSB_scrollTools.mCSB_scrollTools_horizontal{left:0}.mCS-dir-rtl>.mCSB_inside>.mCSB_container_wrapper{margin-right:0;margin-left:30px}.mCSB_container_wrapper.mCS_no_scrollbar_y.mCS_y_hidden>.mCSB_container{padding-right:0}.mCSB_container_wrapper.mCS_no_scrollbar_x.mCS_x_hidden>.mCSB_container{padding-bottom:0}.mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside>.mCSB_container_wrapper.mCS_no_scrollbar_y.mCS_y_hidden{margin-right:0;margin-left:0}.mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside>.mCSB_container_wrapper.mCS_no_scrollbar_x.mCS_x_hidden{margin-bottom:0}.mCSB_scrollTools,.mCSB_scrollTools .mCSB_buttonDown,.mCSB_scrollTools .mCSB_buttonLeft,.mCSB_scrollTools .mCSB_buttonRight,.mCSB_scrollTools .mCSB_buttonUp,.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{-webkit-transition:opacity .2s ease-in-out,background-color .2s ease-in-out;-moz-transition:opacity .2s ease-in-out,background-color .2s ease-in-out;-o-transition:opacity .2s ease-in-out,background-color .2s ease-in-out;transition:opacity .2s ease-in-out,background-color .2s ease-in-out}.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerRail,.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger_bar,.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerRail,.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger_bar{-webkit-transition:width .2s ease-out .2s,height .2s ease-out .2s,margin-left .2s ease-out .2s,margin-right .2s ease-out .2s,margin-top .2s ease-out .2s,margin-bottom .2s ease-out .2s,opacity .2s ease-in-out,background-color .2s ease-in-out;-moz-transition:width .2s ease-out .2s,height .2s ease-out .2s,margin-left .2s ease-out .2s,margin-right .2s ease-out .2s,margin-top .2s ease-out .2s,margin-bottom .2s ease-out .2s,opacity .2s ease-in-out,background-color .2s ease-in-out;-o-transition:width .2s ease-out .2s,height .2s ease-out .2s,margin-left .2s ease-out .2s,margin-right .2s ease-out .2s,margin-top .2s ease-out .2s,margin-bottom .2s ease-out .2s,opacity .2s ease-in-out,background-color .2s ease-in-out;transition:width .2s ease-out .2s,height .2s ease-out .2s,margin-left .2s ease-out .2s,margin-right .2s ease-out .2s,margin-top .2s ease-out .2s,margin-bottom .2s ease-out .2s,opacity .2s ease-in-out,background-color .2s ease-in-out}.mCS-autoHide>.mCustomScrollBox>.mCSB_scrollTools,.mCS-autoHide>.mCustomScrollBox~.mCSB_scrollTools{opacity:0;filter:"alpha(opacity=0)";-ms-filter:"alpha(opacity=0)"}.mCS-autoHide:hover>.mCustomScrollBox>.mCSB_scrollTools,.mCS-autoHide:hover>.mCustomScrollBox~.mCSB_scrollTools,.mCustomScrollBox:hover>.mCSB_scrollTools,.mCustomScrollBox:hover~.mCSB_scrollTools,.mCustomScrollbar>.mCustomScrollBox>.mCSB_scrollTools.mCSB_scrollTools_onDrag,.mCustomScrollbar>.mCustomScrollBox~.mCSB_scrollTools.mCSB_scrollTools_onDrag{opacity:1;filter:"alpha(opacity=100)";-ms-filter:"alpha(opacity=100)"}.mCSB_scrollTools .mCSB_draggerRail{background-color:#000;background-color:rgba(0,0,0,.4);filter:"alpha(opacity=40)";-ms-filter:"alpha(opacity=40)"}.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{background-color:#fff;background-color:rgba(255,255,255,.75);filter:"alpha(opacity=75)";-ms-filter:"alpha(opacity=75)"}.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{background-color:#fff;background-color:rgba(255,255,255,.85);filter:"alpha(opacity=85)";-ms-filter:"alpha(opacity=85)"}.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar,.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar{background-color:#fff;background-color:rgba(255,255,255,.9);filter:"alpha(opacity=90)";-ms-filter:"alpha(opacity=90)"}.mCSB_scrollTools .mCSB_buttonDown,.mCSB_scrollTools .mCSB_buttonLeft,.mCSB_scrollTools .mCSB_buttonRight,.mCSB_scrollTools .mCSB_buttonUp{background-image:url(mCSB_buttons.png);background-repeat:no-repeat;opacity:.4;filter:"alpha(opacity=40)";-ms-filter:"alpha(opacity=40)"}.mCSB_scrollTools .mCSB_buttonUp{background-position:0 0}.mCSB_scrollTools .mCSB_buttonDown{background-position:0 -20px}.mCSB_scrollTools .mCSB_buttonLeft{background-position:0 -40px}.mCSB_scrollTools .mCSB_buttonRight{background-position:0 -56px}.mCSB_scrollTools .mCSB_buttonDown:hover,.mCSB_scrollTools .mCSB_buttonLeft:hover,.mCSB_scrollTools .mCSB_buttonRight:hover,.mCSB_scrollTools .mCSB_buttonUp:hover{opacity:.75;filter:"alpha(opacity=75)";-ms-filter:"alpha(opacity=75)"}.mCSB_scrollTools .mCSB_buttonDown:active,.mCSB_scrollTools .mCSB_buttonLeft:active,.mCSB_scrollTools .mCSB_buttonRight:active,.mCSB_scrollTools .mCSB_buttonUp:active{opacity:.9;filter:"alpha(opacity=90)";-ms-filter:"alpha(opacity=90)"}.mCS-dark.mCSB_scrollTools .mCSB_draggerRail{background-color:#000;background-color:rgba(0,0,0,.15)}.mCS-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{background-color:#000;background-color:rgba(0,0,0,.75)}.mCS-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{background-color:rgba(0,0,0,.85)}.mCS-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar,.mCS-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar{background-color:rgba(0,0,0,.9)}.mCS-dark.mCSB_scrollTools .mCSB_buttonUp{background-position:-80px 0}.mCS-dark.mCSB_scrollTools .mCSB_buttonDown{background-position:-80px -20px}.mCS-dark.mCSB_scrollTools .mCSB_buttonLeft{background-position:-80px -40px}.mCS-dark.mCSB_scrollTools .mCSB_buttonRight{background-position:-80px -56px}.mCS-dark-2.mCSB_scrollTools .mCSB_draggerRail,.mCS-light-2.mCSB_scrollTools .mCSB_draggerRail{width:4px;background-color:#fff;background-color:rgba(255,255,255,.1);-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px}.mCS-dark-2.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar,.mCS-light-2.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{width:4px;background-color:#fff;background-color:rgba(255,255,255,.75);-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px}.mCS-dark-2.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar,.mCS-dark-2.mCSB_scrollTools_horizontal .mCSB_draggerRail,.mCS-light-2.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar,.mCS-light-2.mCSB_scrollTools_horizontal .mCSB_draggerRail{width:100%;height:4px;margin:6px auto}.mCS-light-2.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{background-color:#fff;background-color:rgba(255,255,255,.85)}.mCS-light-2.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar,.mCS-light-2.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar{background-color:#fff;background-color:rgba(255,255,255,.9)}.mCS-light-2.mCSB_scrollTools .mCSB_buttonUp{background-position:-32px 0}.mCS-light-2.mCSB_scrollTools .mCSB_buttonDown{background-position:-32px -20px}.mCS-light-2.mCSB_scrollTools .mCSB_buttonLeft{background-position:-40px -40px}.mCS-light-2.mCSB_scrollTools .mCSB_buttonRight{background-position:-40px -56px}.mCS-dark-2.mCSB_scrollTools .mCSB_draggerRail{background-color:#000;background-color:rgba(0,0,0,.1);-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px}.mCS-dark-2.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{background-color:#000;background-color:rgba(0,0,0,.75);-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px}.mCS-dark-2.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{background-color:#000;background-color:rgba(0,0,0,.85)}.mCS-dark-2.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar,.mCS-dark-2.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar{background-color:#000;background-color:rgba(0,0,0,.9)}.mCS-dark-2.mCSB_scrollTools .mCSB_buttonUp{background-position:-112px 0}.mCS-dark-2.mCSB_scrollTools .mCSB_buttonDown{background-position:-112px -20px}.mCS-dark-2.mCSB_scrollTools .mCSB_buttonLeft{background-position:-120px -40px}.mCS-dark-2.mCSB_scrollTools .mCSB_buttonRight{background-position:-120px -56px}.mCS-dark-thick.mCSB_scrollTools .mCSB_draggerRail,.mCS-light-thick.mCSB_scrollTools .mCSB_draggerRail{width:4px;background-color:#fff;background-color:rgba(255,255,255,.1);-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px}.mCS-dark-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar,.mCS-light-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{width:6px;background-color:#fff;background-color:rgba(255,255,255,.75);-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px}.mCS-dark-thick.mCSB_scrollTools_horizontal .mCSB_draggerRail,.mCS-light-thick.mCSB_scrollTools_horizontal .mCSB_draggerRail{width:100%;height:4px;margin:6px 0}.mCS-dark-thick.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar,.mCS-light-thick.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{width:100%;height:6px;margin:5px auto}.mCS-light-thick.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{background-color:#fff;background-color:rgba(255,255,255,.85)}.mCS-light-thick.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar,.mCS-light-thick.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar{background-color:#fff;background-color:rgba(255,255,255,.9)}.mCS-light-thick.mCSB_scrollTools .mCSB_buttonUp{background-position:-16px 0}.mCS-light-thick.mCSB_scrollTools .mCSB_buttonDown{background-position:-16px -20px}.mCS-light-thick.mCSB_scrollTools .mCSB_buttonLeft{background-position:-20px -40px}.mCS-light-thick.mCSB_scrollTools .mCSB_buttonRight{background-position:-20px -56px}.mCS-dark-thick.mCSB_scrollTools .mCSB_draggerRail{background-color:#000;background-color:rgba(0,0,0,.1);-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px}.mCS-dark-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{background-color:#000;background-color:rgba(0,0,0,.75);-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px}.mCS-dark-thick.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{background-color:#000;background-color:rgba(0,0,0,.85)}.mCS-dark-thick.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar,.mCS-dark-thick.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar{background-color:#000;background-color:rgba(0,0,0,.9)}.mCS-dark-thick.mCSB_scrollTools .mCSB_buttonUp{background-position:-96px 0}.mCS-dark-thick.mCSB_scrollTools .mCSB_buttonDown{background-position:-96px -20px}.mCS-dark-thick.mCSB_scrollTools .mCSB_buttonLeft{background-position:-100px -40px}.mCS-dark-thick.mCSB_scrollTools .mCSB_buttonRight{background-position:-100px -56px}.mCS-light-thin.mCSB_scrollTools .mCSB_draggerRail{background-color:#fff;background-color:rgba(255,255,255,.1)}.mCS-dark-thin.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar,.mCS-light-thin.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{width:2px}.mCS-dark-thin.mCSB_scrollTools_horizontal .mCSB_draggerRail,.mCS-light-thin.mCSB_scrollTools_horizontal .mCSB_draggerRail{width:100%}.mCS-dark-thin.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar,.mCS-light-thin.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{width:100%;height:2px;margin:7px auto}.mCS-dark-thin.mCSB_scrollTools .mCSB_draggerRail{background-color:#000;background-color:rgba(0,0,0,.15)}.mCS-dark-thin.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{background-color:#000;background-color:rgba(0,0,0,.75)}.mCS-dark-thin.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{background-color:#000;background-color:rgba(0,0,0,.85)}.mCS-dark-thin.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar,.mCS-dark-thin.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar{background-color:#000;background-color:rgba(0,0,0,.9)}.mCS-dark-thin.mCSB_scrollTools .mCSB_buttonUp{background-position:-80px 0}.mCS-dark-thin.mCSB_scrollTools .mCSB_buttonDown{background-position:-80px -20px}.mCS-dark-thin.mCSB_scrollTools .mCSB_buttonLeft{background-position:-80px -40px}.mCS-dark-thin.mCSB_scrollTools .mCSB_buttonRight{background-position:-80px -56px}.mCS-rounded.mCSB_scrollTools .mCSB_draggerRail{background-color:#fff;background-color:rgba(255,255,255,.15)}.mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger,.mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger,.mCS-rounded-dots.mCSB_scrollTools .mCSB_dragger,.mCS-rounded.mCSB_scrollTools .mCSB_dragger{height:14px}.mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar,.mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar,.mCS-rounded-dots.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar,.mCS-rounded.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{width:14px;margin:0 1px}.mCS-rounded-dark.mCSB_scrollTools_horizontal .mCSB_dragger,.mCS-rounded-dots-dark.mCSB_scrollTools_horizontal .mCSB_dragger,.mCS-rounded-dots.mCSB_scrollTools_horizontal .mCSB_dragger,.mCS-rounded.mCSB_scrollTools_horizontal .mCSB_dragger{width:14px}.mCS-rounded-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar,.mCS-rounded-dots-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar,.mCS-rounded-dots.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar,.mCS-rounded.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{height:14px;margin:1px 0}.mCS-rounded-dark.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar,.mCS-rounded-dark.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar,.mCS-rounded.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar,.mCS-rounded.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar{width:16px;height:16px;margin:-1px 0}.mCS-rounded-dark.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded+.mCSB_draggerRail,.mCS-rounded-dark.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail,.mCS-rounded.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded+.mCSB_draggerRail,.mCS-rounded.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{width:4px}.mCS-rounded-dark.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar,.mCS-rounded-dark.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar,.mCS-rounded.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar,.mCS-rounded.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar{height:16px;width:16px;margin:0 -1px}.mCS-rounded-dark.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded+.mCSB_draggerRail,.mCS-rounded-dark.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail,.mCS-rounded.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded+.mCSB_draggerRail,.mCS-rounded.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{height:4px;margin:6px 0}.mCS-rounded.mCSB_scrollTools .mCSB_buttonUp{background-position:0 -72px}.mCS-rounded.mCSB_scrollTools .mCSB_buttonDown{background-position:0 -92px}.mCS-rounded.mCSB_scrollTools .mCSB_buttonLeft{background-position:0 -112px}.mCS-rounded.mCSB_scrollTools .mCSB_buttonRight{background-position:0 -128px}.mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar,.mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{background-color:#000;background-color:rgba(0,0,0,.75)}.mCS-rounded-dark.mCSB_scrollTools .mCSB_draggerRail{background-color:#000;background-color:rgba(0,0,0,.15)}.mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar,.mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{background-color:#000;background-color:rgba(0,0,0,.85)}.mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar,.mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar,.mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar,.mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar{background-color:#000;background-color:rgba(0,0,0,.9)}.mCS-rounded-dark.mCSB_scrollTools .mCSB_buttonUp{background-position:-80px -72px}.mCS-rounded-dark.mCSB_scrollTools .mCSB_buttonDown{background-position:-80px -92px}.mCS-rounded-dark.mCSB_scrollTools .mCSB_buttonLeft{background-position:-80px -112px}.mCS-rounded-dark.mCSB_scrollTools .mCSB_buttonRight{background-position:-80px -128px}.mCS-rounded-dots-dark.mCSB_scrollTools_vertical .mCSB_draggerRail,.mCS-rounded-dots.mCSB_scrollTools_vertical .mCSB_draggerRail{width:4px}.mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_draggerRail,.mCS-rounded-dots-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail,.mCS-rounded-dots.mCSB_scrollTools .mCSB_draggerRail,.mCS-rounded-dots.mCSB_scrollTools_horizontal .mCSB_draggerRail{background-color:transparent;background-position:center}.mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_draggerRail,.mCS-rounded-dots.mCSB_scrollTools .mCSB_draggerRail{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAANElEQVQYV2NkIAAYiVbw//9/Y6DiM1ANJoyMjGdBbLgJQAX/kU0DKgDLkaQAvxW4HEvQFwCRcxIJK1XznAAAAABJRU5ErkJggg==);background-repeat:repeat-y;opacity:.3;filter:"alpha(opacity=30)";-ms-filter:"alpha(opacity=30)"}.mCS-rounded-dots-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail,.mCS-rounded-dots.mCSB_scrollTools_horizontal .mCSB_draggerRail{height:4px;margin:6px 0;background-repeat:repeat-x}.mCS-rounded-dots.mCSB_scrollTools .mCSB_buttonUp{background-position:-16px -72px}.mCS-rounded-dots.mCSB_scrollTools .mCSB_buttonDown{background-position:-16px -92px}.mCS-rounded-dots.mCSB_scrollTools .mCSB_buttonLeft{background-position:-20px -112px}.mCS-rounded-dots.mCSB_scrollTools .mCSB_buttonRight{background-position:-20px -128px}.mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_draggerRail{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAALElEQVQYV2NkIAAYSVFgDFR8BqrBBEifBbGRTfiPZhpYjiQFBK3A6l6CvgAAE9kGCd1mvgEAAAAASUVORK5CYII=)}.mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_buttonUp{background-position:-96px -72px}.mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_buttonDown{background-position:-96px -92px}.mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_buttonLeft{background-position:-100px -112px}.mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_buttonRight{background-position:-100px -128px}.mCS-3d-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar,.mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar,.mCS-3d-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar,.mCS-3d.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{background-repeat:repeat-y;background-image:-moz-linear-gradient(left,rgba(255,255,255,.5) 0,rgba(255,255,255,0) 100%);background-image:-webkit-gradient(linear,left top,right top,color-stop(0,rgba(255,255,255,.5)),color-stop(100%,rgba(255,255,255,0)));background-image:-webkit-linear-gradient(left,rgba(255,255,255,.5) 0,rgba(255,255,255,0) 100%);background-image:-o-linear-gradient(left,rgba(255,255,255,.5) 0,rgba(255,255,255,0) 100%);background-image:-ms-linear-gradient(left,rgba(255,255,255,.5) 0,rgba(255,255,255,0) 100%);background-image:linear-gradient(to right,rgba(255,255,255,.5) 0,rgba(255,255,255,0) 100%)}.mCS-3d-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar,.mCS-3d-thick-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar,.mCS-3d-thick.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar,.mCS-3d.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{background-repeat:repeat-x;background-image:-moz-linear-gradient(top,rgba(255,255,255,.5) 0,rgba(255,255,255,0) 100%);background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,rgba(255,255,255,.5)),color-stop(100%,rgba(255,255,255,0)));background-image:-webkit-linear-gradient(top,rgba(255,255,255,.5) 0,rgba(255,255,255,0) 100%);background-image:-o-linear-gradient(top,rgba(255,255,255,.5) 0,rgba(255,255,255,0) 100%);background-image:-ms-linear-gradient(top,rgba(255,255,255,.5) 0,rgba(255,255,255,0) 100%);background-image:linear-gradient(to bottom,rgba(255,255,255,.5) 0,rgba(255,255,255,0) 100%)}.mCS-3d-dark.mCSB_scrollTools_vertical .mCSB_dragger,.mCS-3d.mCSB_scrollTools_vertical .mCSB_dragger{height:70px}.mCS-3d-dark.mCSB_scrollTools_horizontal .mCSB_dragger,.mCS-3d.mCSB_scrollTools_horizontal .mCSB_dragger{width:70px}.mCS-3d-dark.mCSB_scrollTools,.mCS-3d.mCSB_scrollTools{opacity:1;filter:"alpha(opacity=30)";-ms-filter:"alpha(opacity=30)"}.mCS-3d-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar,.mCS-3d-dark.mCSB_scrollTools .mCSB_draggerRail,.mCS-3d.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar,.mCS-3d.mCSB_scrollTools .mCSB_draggerRail{-webkit-border-radius:16px;-moz-border-radius:16px;border-radius:16px}.mCS-3d-dark.mCSB_scrollTools .mCSB_draggerRail,.mCS-3d.mCSB_scrollTools .mCSB_draggerRail{width:8px;background-color:#000;background-color:rgba(0,0,0,.2);box-shadow:inset 1px 0 1px rgba(0,0,0,.5),inset -1px 0 1px rgba(255,255,255,.2)}.mCS-3d-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar,.mCS-3d-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar,.mCS-3d-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar,.mCS-3d-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar,.mCS-3d.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar,.mCS-3d.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar,.mCS-3d.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar,.mCS-3d.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{background-color:#555}.mCS-3d-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar,.mCS-3d.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{width:8px}.mCS-3d-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail,.mCS-3d.mCSB_scrollTools_horizontal .mCSB_draggerRail{width:100%;height:8px;margin:4px 0;box-shadow:inset 0 1px 1px rgba(0,0,0,.5),inset 0 -1px 1px rgba(255,255,255,.2)}.mCS-3d-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar,.mCS-3d.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{width:100%;height:8px;margin:4px auto}.mCS-3d.mCSB_scrollTools .mCSB_buttonUp{background-position:-32px -72px}.mCS-3d.mCSB_scrollTools .mCSB_buttonDown{background-position:-32px -92px}.mCS-3d.mCSB_scrollTools .mCSB_buttonLeft{background-position:-40px -112px}.mCS-3d.mCSB_scrollTools .mCSB_buttonRight{background-position:-40px -128px}.mCS-3d-dark.mCSB_scrollTools .mCSB_draggerRail{background-color:#000;background-color:rgba(0,0,0,.1);box-shadow:inset 1px 0 1px rgba(0,0,0,.1)}.mCS-3d-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail{box-shadow:inset 0 1px 1px rgba(0,0,0,.1)}.mCS-3d-dark.mCSB_scrollTools .mCSB_buttonUp{background-position:-112px -72px}.mCS-3d-dark.mCSB_scrollTools .mCSB_buttonDown{background-position:-112px -92px}.mCS-3d-dark.mCSB_scrollTools .mCSB_buttonLeft{background-position:-120px -112px}.mCS-3d-dark.mCSB_scrollTools .mCSB_buttonRight{background-position:-120px -128px}.mCS-3d-thick-dark.mCSB_scrollTools,.mCS-3d-thick.mCSB_scrollTools{opacity:1;filter:"alpha(opacity=30)";-ms-filter:"alpha(opacity=30)"}.mCS-3d-thick-dark.mCSB_scrollTools,.mCS-3d-thick-dark.mCSB_scrollTools .mCSB_draggerContainer,.mCS-3d-thick.mCSB_scrollTools,.mCS-3d-thick.mCSB_scrollTools .mCSB_draggerContainer{-webkit-border-radius:7px;-moz-border-radius:7px;border-radius:7px}.mCSB_inside+.mCS-3d-thick-dark.mCSB_scrollTools_vertical,.mCSB_inside+.mCS-3d-thick.mCSB_scrollTools_vertical{right:1px}.mCS-3d-thick-dark.mCSB_scrollTools_vertical,.mCS-3d-thick.mCSB_scrollTools_vertical{box-shadow:inset 1px 0 1px rgba(0,0,0,.1),inset 0 0 14px rgba(0,0,0,.5)}.mCS-3d-thick-dark.mCSB_scrollTools_horizontal,.mCS-3d-thick.mCSB_scrollTools_horizontal{bottom:1px;box-shadow:inset 0 1px 1px rgba(0,0,0,.1),inset 0 0 14px rgba(0,0,0,.5)}.mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar,.mCS-3d-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;box-shadow:inset 1px 0 0 rgba(255,255,255,.4);width:12px;margin:2px;position:absolute;height:auto;top:0;bottom:0;left:0;right:0}.mCS-3d-thick-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar,.mCS-3d-thick.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{box-shadow:inset 0 1px 0 rgba(255,255,255,.4);height:12px;width:auto}.mCS-3d-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar,.mCS-3d-thick.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar,.mCS-3d-thick.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar,.mCS-3d-thick.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{background-color:#555}.mCS-3d-thick.mCSB_scrollTools .mCSB_draggerContainer{background-color:#000;background-color:rgba(0,0,0,.05);box-shadow:inset 1px 1px 16px rgba(0,0,0,.1)}.mCS-3d-thick.mCSB_scrollTools .mCSB_draggerRail{background-color:transparent}.mCS-3d-thick.mCSB_scrollTools .mCSB_buttonUp{background-position:-32px -72px}.mCS-3d-thick.mCSB_scrollTools .mCSB_buttonDown{background-position:-32px -92px}.mCS-3d-thick.mCSB_scrollTools .mCSB_buttonLeft{background-position:-40px -112px}.mCS-3d-thick.mCSB_scrollTools .mCSB_buttonRight{background-position:-40px -128px}.mCS-3d-thick-dark.mCSB_scrollTools{box-shadow:inset 0 0 14px rgba(0,0,0,.2)}.mCS-3d-thick-dark.mCSB_scrollTools_horizontal{box-shadow:inset 0 1px 1px rgba(0,0,0,.1),inset 0 0 14px rgba(0,0,0,.2)}.mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{box-shadow:inset 1px 0 0 rgba(255,255,255,.4),inset -1px 0 0 rgba(0,0,0,.2)}.mCS-3d-thick-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{box-shadow:inset 0 1px 0 rgba(255,255,255,.4),inset 0 -1px 0 rgba(0,0,0,.2)}.mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar,.mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar,.mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar,.mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{background-color:#777}.mCS-3d-thick-dark.mCSB_scrollTools .mCSB_draggerContainer{background-color:#fff;background-color:rgba(0,0,0,.05);box-shadow:inset 1px 1px 16px rgba(0,0,0,.1)}.mCS-3d-thick-dark.mCSB_scrollTools .mCSB_draggerRail,.mCS-minimal-dark.mCSB_scrollTools .mCSB_draggerRail,.mCS-minimal.mCSB_scrollTools .mCSB_draggerRail{background-color:transparent}.mCS-3d-thick-dark.mCSB_scrollTools .mCSB_buttonUp{background-position:-112px -72px}.mCS-3d-thick-dark.mCSB_scrollTools .mCSB_buttonDown{background-position:-112px -92px}.mCS-3d-thick-dark.mCSB_scrollTools .mCSB_buttonLeft{background-position:-120px -112px}.mCS-3d-thick-dark.mCSB_scrollTools .mCSB_buttonRight{background-position:-120px -128px}.mCSB_outside+.mCS-minimal-dark.mCSB_scrollTools_vertical,.mCSB_outside+.mCS-minimal.mCSB_scrollTools_vertical{right:0;margin:12px 0}.mCustomScrollBox.mCS-minimal+.mCSB_scrollTools+.mCSB_scrollTools.mCSB_scrollTools_horizontal,.mCustomScrollBox.mCS-minimal+.mCSB_scrollTools.mCSB_scrollTools_horizontal,.mCustomScrollBox.mCS-minimal-dark+.mCSB_scrollTools+.mCSB_scrollTools.mCSB_scrollTools_horizontal,.mCustomScrollBox.mCS-minimal-dark+.mCSB_scrollTools.mCSB_scrollTools_horizontal{bottom:0;margin:0 12px}.mCS-dir-rtl>.mCSB_outside+.mCS-minimal-dark.mCSB_scrollTools_vertical,.mCS-dir-rtl>.mCSB_outside+.mCS-minimal.mCSB_scrollTools_vertical{left:0;right:auto}.mCS-minimal-dark.mCSB_scrollTools_vertical .mCSB_dragger,.mCS-minimal.mCSB_scrollTools_vertical .mCSB_dragger{height:50px}.mCS-minimal-dark.mCSB_scrollTools_horizontal .mCSB_dragger,.mCS-minimal.mCSB_scrollTools_horizontal .mCSB_dragger{width:50px}.mCS-minimal.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{background-color:#fff;background-color:rgba(255,255,255,.2);filter:"alpha(opacity=20)";-ms-filter:"alpha(opacity=20)"}.mCS-minimal.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar,.mCS-minimal.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar{background-color:#fff;background-color:rgba(255,255,255,.5);filter:"alpha(opacity=50)";-ms-filter:"alpha(opacity=50)"}.mCS-minimal-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{background-color:#000;background-color:rgba(0,0,0,.2);filter:"alpha(opacity=20)";-ms-filter:"alpha(opacity=20)"}.mCS-minimal-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar,.mCS-minimal-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar{background-color:#000;background-color:rgba(0,0,0,.5);filter:"alpha(opacity=50)";-ms-filter:"alpha(opacity=50)"}.mCS-dark-3.mCSB_scrollTools .mCSB_draggerRail,.mCS-light-3.mCSB_scrollTools .mCSB_draggerRail{width:6px;background-color:#000;background-color:rgba(0,0,0,.2)}.mCS-dark-3.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar,.mCS-light-3.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{width:6px}.mCS-dark-3.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar,.mCS-dark-3.mCSB_scrollTools_horizontal .mCSB_draggerRail,.mCS-light-3.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar,.mCS-light-3.mCSB_scrollTools_horizontal .mCSB_draggerRail{width:100%;height:6px;margin:5px 0}.mCS-dark-3.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded+.mCSB_draggerRail,.mCS-dark-3.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail,.mCS-light-3.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded+.mCSB_draggerRail,.mCS-light-3.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{width:12px}.mCS-dark-3.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded+.mCSB_draggerRail,.mCS-dark-3.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail,.mCS-light-3.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded+.mCSB_draggerRail,.mCS-light-3.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{height:12px;margin:2px 0}.mCS-light-3.mCSB_scrollTools .mCSB_buttonUp{background-position:-32px -72px}.mCS-light-3.mCSB_scrollTools .mCSB_buttonDown{background-position:-32px -92px}.mCS-light-3.mCSB_scrollTools .mCSB_buttonLeft{background-position:-40px -112px}.mCS-light-3.mCSB_scrollTools .mCSB_buttonRight{background-position:-40px -128px}.mCS-dark-3.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{background-color:#000;background-color:rgba(0,0,0,.75)}.mCS-dark-3.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{background-color:#000;background-color:rgba(0,0,0,.85)}.mCS-dark-3.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar,.mCS-dark-3.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar{background-color:#000;background-color:rgba(0,0,0,.9)}.mCS-dark-3.mCSB_scrollTools .mCSB_draggerRail{background-color:#000;background-color:rgba(0,0,0,.1)}.mCS-dark-3.mCSB_scrollTools .mCSB_buttonUp{background-position:-112px -72px}.mCS-dark-3.mCSB_scrollTools .mCSB_buttonDown{background-position:-112px -92px}.mCS-dark-3.mCSB_scrollTools .mCSB_buttonLeft{background-position:-120px -112px}.mCS-dark-3.mCSB_scrollTools .mCSB_buttonRight{background-position:-120px -128px}.mCS-inset-2-dark.mCSB_scrollTools .mCSB_draggerRail,.mCS-inset-2.mCSB_scrollTools .mCSB_draggerRail,.mCS-inset-3-dark.mCSB_scrollTools .mCSB_draggerRail,.mCS-inset-3.mCSB_scrollTools .mCSB_draggerRail,.mCS-inset-dark.mCSB_scrollTools .mCSB_draggerRail,.mCS-inset.mCSB_scrollTools .mCSB_draggerRail{width:12px;background-color:#000;background-color:rgba(0,0,0,.2)}.mCS-inset-2-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar,.mCS-inset-2.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar,.mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar,.mCS-inset-3.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar,.mCS-inset-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar,.mCS-inset.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{width:6px;margin:3px 5px;position:absolute;height:auto;top:0;bottom:0;left:0;right:0}.mCS-inset-2-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar,.mCS-inset-2.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar,.mCS-inset-3-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar,.mCS-inset-3.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar,.mCS-inset-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar,.mCS-inset.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{height:6px;margin:5px 3px;position:absolute;width:auto;top:0;bottom:0;left:0;right:0}.mCS-inset-2-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail,.mCS-inset-2.mCSB_scrollTools_horizontal .mCSB_draggerRail,.mCS-inset-3-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail,.mCS-inset-3.mCSB_scrollTools_horizontal .mCSB_draggerRail,.mCS-inset-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail,.mCS-inset.mCSB_scrollTools_horizontal .mCSB_draggerRail{width:100%;height:12px;margin:2px 0}.mCS-inset-2.mCSB_scrollTools .mCSB_buttonUp,.mCS-inset-3.mCSB_scrollTools .mCSB_buttonUp,.mCS-inset.mCSB_scrollTools .mCSB_buttonUp{background-position:-32px -72px}.mCS-inset-2.mCSB_scrollTools .mCSB_buttonDown,.mCS-inset-3.mCSB_scrollTools .mCSB_buttonDown,.mCS-inset.mCSB_scrollTools .mCSB_buttonDown{background-position:-32px -92px}.mCS-inset-2.mCSB_scrollTools .mCSB_buttonLeft,.mCS-inset-3.mCSB_scrollTools .mCSB_buttonLeft,.mCS-inset.mCSB_scrollTools .mCSB_buttonLeft{background-position:-40px -112px}.mCS-inset-2.mCSB_scrollTools .mCSB_buttonRight,.mCS-inset-3.mCSB_scrollTools .mCSB_buttonRight,.mCS-inset.mCSB_scrollTools .mCSB_buttonRight{background-position:-40px -128px}.mCS-inset-2-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar,.mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar,.mCS-inset-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{background-color:#000;background-color:rgba(0,0,0,.75)}.mCS-inset-2-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar,.mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar,.mCS-inset-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{background-color:#000;background-color:rgba(0,0,0,.85)}.mCS-inset-2-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar,.mCS-inset-2-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar,.mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar,.mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar,.mCS-inset-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar,.mCS-inset-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar{background-color:#000;background-color:rgba(0,0,0,.9)}.mCS-inset-2-dark.mCSB_scrollTools .mCSB_draggerRail,.mCS-inset-3-dark.mCSB_scrollTools .mCSB_draggerRail,.mCS-inset-dark.mCSB_scrollTools .mCSB_draggerRail{background-color:#000;background-color:rgba(0,0,0,.1)}.mCS-inset-2-dark.mCSB_scrollTools .mCSB_buttonUp,.mCS-inset-3-dark.mCSB_scrollTools .mCSB_buttonUp,.mCS-inset-dark.mCSB_scrollTools .mCSB_buttonUp{background-position:-112px -72px}.mCS-inset-2-dark.mCSB_scrollTools .mCSB_buttonDown,.mCS-inset-3-dark.mCSB_scrollTools .mCSB_buttonDown,.mCS-inset-dark.mCSB_scrollTools .mCSB_buttonDown{background-position:-112px -92px}.mCS-inset-2-dark.mCSB_scrollTools .mCSB_buttonLeft,.mCS-inset-3-dark.mCSB_scrollTools .mCSB_buttonLeft,.mCS-inset-dark.mCSB_scrollTools .mCSB_buttonLeft{background-position:-120px -112px}.mCS-inset-2-dark.mCSB_scrollTools .mCSB_buttonRight,.mCS-inset-3-dark.mCSB_scrollTools .mCSB_buttonRight,.mCS-inset-dark.mCSB_scrollTools .mCSB_buttonRight{background-position:-120px -128px}.mCS-inset-2-dark.mCSB_scrollTools .mCSB_draggerRail,.mCS-inset-2.mCSB_scrollTools .mCSB_draggerRail{background-color:transparent;border-width:1px;border-style:solid;border-color:#fff;border-color:rgba(255,255,255,.2);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.mCS-inset-2-dark.mCSB_scrollTools .mCSB_draggerRail{border-color:#000;border-color:rgba(0,0,0,.2)}.mCS-inset-3.mCSB_scrollTools .mCSB_draggerRail{background-color:#fff;background-color:rgba(255,255,255,.6)}.mCS-inset-3-dark.mCSB_scrollTools .mCSB_draggerRail{background-color:#000;background-color:rgba(0,0,0,.6)}.mCS-inset-3.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{background-color:#000;background-color:rgba(0,0,0,.75)}.mCS-inset-3.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{background-color:#000;background-color:rgba(0,0,0,.85)}.mCS-inset-3.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar,.mCS-inset-3.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar{background-color:#000;background-color:rgba(0,0,0,.9)}.mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{background-color:#fff;background-color:rgba(255,255,255,.75)}.mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{background-color:#fff;background-color:rgba(255,255,255,.85)}.mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar,.mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar{background-color:#fff;background-color:rgba(255,255,255,.9)}
--------------------------------------------------------------------------------
/ui/static/res/botim.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/suriyadeepan/easy_seq2seq/c05b0d02f15e9bd1947ff79ddcd0b761a214e2a9/ui/static/res/botim.png
--------------------------------------------------------------------------------
/ui/static/res/hd1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/suriyadeepan/easy_seq2seq/c05b0d02f15e9bd1947ff79ddcd0b761a214e2a9/ui/static/res/hd1.jpg
--------------------------------------------------------------------------------
/ui/static/res/hd2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/suriyadeepan/easy_seq2seq/c05b0d02f15e9bd1947ff79ddcd0b761a214e2a9/ui/static/res/hd2.jpg
--------------------------------------------------------------------------------
/ui/static/scss/style.scss:
--------------------------------------------------------------------------------
1 | /*--------------------
2 | Mixins
3 | --------------------*/
4 | @mixin center {
5 | position: absolute;
6 | top: 50%;
7 | left: 50%;
8 | transform: translate(-50%, -50%);
9 | }
10 |
11 | @mixin ball {
12 | @include center;
13 | content: '';
14 | display: block;
15 | width: 3px;
16 | height: 3px;
17 | border-radius: 50%;
18 | background: rgba(255, 255, 255, .5);
19 | z-index: 2;
20 | margin-top: 4px;
21 | animation: ball .45s cubic-bezier(0, 0, 0.15, 1) alternate infinite;
22 | }
23 |
24 |
25 | /*--------------------
26 | Body
27 | --------------------*/
28 | *,
29 | *::before,
30 | *::after {
31 | box-sizing: border-box;
32 | }
33 |
34 | html,
35 | body {
36 | height: 100%;
37 | }
38 |
39 | body {
40 | background: linear-gradient(135deg, #044f48, #2a7561);
41 | background-size: cover;
42 | font-family: 'Open Sans', sans-serif;
43 | font-size: 12px;
44 | line-height: 1.3;
45 | overflow: hidden;
46 | }
47 |
48 | .bg {
49 | width: 100%;
50 | height: 100%;
51 | top: 0;
52 | left: 0;
53 | z-index: 1;
54 | background: url('https://images.unsplash.com/photo-1451186859696-371d9477be93?crop=entropy&fit=crop&fm=jpg&h=975&ixjsv=2.1.0&ixlib=rb-0.3.5&q=80&w=1925') no-repeat 0 0;
55 | filter: blur(80px);
56 | transform: scale(1.2);
57 | }
58 |
59 |
60 | /*--------------------
61 | Chat
62 | --------------------*/
63 | .chat {
64 | @include center;
65 | width: 300px;
66 | height: 80vh;
67 | max-height: 500px;
68 | z-index: 2;
69 | overflow: hidden;
70 | box-shadow: 0 5px 30px rgba(0, 0, 0, .2);
71 | background: rgba(0, 0, 0, .5);
72 | border-radius: 20px;
73 | display: flex;
74 | justify-content: space-between;
75 | flex-direction: column;
76 | }
77 |
78 |
79 | /*--------------------
80 | Chat Title
81 | --------------------*/
82 | .chat-title {
83 | flex: 0 1 45px;
84 | position: relative;
85 | z-index: 2;
86 | background: rgba(0, 0, 0, 0.2);
87 | color: #fff;
88 | text-transform: uppercase;
89 | text-align: left;
90 | padding: 10px 10px 10px 50px;
91 |
92 | h1, h2 {
93 | font-weight: normal;
94 | font-size: 10px;
95 | margin: 0;
96 | padding: 0;
97 | }
98 |
99 | h2 {
100 | color: rgba(255, 255, 255, .5);
101 | font-size: 8px;
102 | letter-spacing: 1px;
103 | }
104 |
105 | .avatar {
106 | position: absolute;
107 | z-index: 1;
108 | top: 8px;
109 | left: 9px;
110 | border-radius: 30px;
111 | width: 30px;
112 | height: 30px;
113 | overflow: hidden;
114 | margin: 0;
115 | padding: 0;
116 | border: 2px solid rgba(255, 255, 255, 0.24);
117 |
118 | img {
119 | width: 100%;
120 | height: auto;
121 | }
122 | }
123 | }
124 |
125 |
126 | /*--------------------
127 | Messages
128 | --------------------*/
129 | .messages {
130 | flex: 1 1 auto;
131 | color: rgba(255, 255, 255, .5);
132 | overflow: hidden;
133 | position: relative;
134 | width: 100%;
135 |
136 | & .messages-content {
137 | position: absolute;
138 | top: 0;
139 | left: 0;
140 | height: 101%;
141 | width: 100%;
142 | }
143 |
144 |
145 | .message {
146 | clear: both;
147 | float: left;
148 | padding: 6px 10px 7px;
149 | border-radius: 10px 10px 10px 0;
150 | background: rgba(0, 0, 0, .3);
151 | margin: 8px 0;
152 | font-size: 11px;
153 | line-height: 1.4;
154 | margin-left: 35px;
155 | position: relative;
156 | text-shadow: 0 1px 1px rgba(0, 0, 0, .2);
157 |
158 | .timestamp {
159 | position: absolute;
160 | bottom: -15px;
161 | font-size: 9px;
162 | color: rgba(255, 255, 255, .3);
163 | }
164 |
165 | &::before {
166 | content: '';
167 | position: absolute;
168 | bottom: -6px;
169 | border-top: 6px solid rgba(0, 0, 0, .3);
170 | left: 0;
171 | border-right: 7px solid transparent;
172 | }
173 |
174 | .avatar {
175 | position: absolute;
176 | z-index: 1;
177 | bottom: -15px;
178 | left: -35px;
179 | border-radius: 30px;
180 | width: 30px;
181 | height: 30px;
182 | overflow: hidden;
183 | margin: 0;
184 | padding: 0;
185 | border: 2px solid rgba(255, 255, 255, 0.24);
186 |
187 | img {
188 | width: 100%;
189 | height: auto;
190 | }
191 | }
192 |
193 | &.message-personal {
194 | float: right;
195 | color: #fff;
196 | text-align: right;
197 | background: linear-gradient(120deg, #248A52, #257287);
198 | border-radius: 10px 10px 0 10px;
199 |
200 | &::before {
201 | left: auto;
202 | right: 0;
203 | border-right: none;
204 | border-left: 5px solid transparent;
205 | border-top: 4px solid #257287;
206 | bottom: -4px;
207 | }
208 | }
209 |
210 | &:last-child {
211 | margin-bottom: 30px;
212 | }
213 |
214 | &.new {
215 | transform: scale(0);
216 | transform-origin: 0 0;
217 | animation: bounce 500ms linear both;
218 | }
219 |
220 | &.loading {
221 |
222 | &::before {
223 | @include ball;
224 | border: none;
225 | animation-delay: .15s;
226 | }
227 |
228 | & span {
229 | display: block;
230 | font-size: 0;
231 | width: 20px;
232 | height: 10px;
233 | position: relative;
234 |
235 | &::before {
236 | @include ball;
237 | margin-left: -7px;
238 | }
239 |
240 | &::after {
241 | @include ball;
242 | margin-left: 7px;
243 | animation-delay: .3s;
244 | }
245 | }
246 | }
247 |
248 | }
249 | }
250 |
251 |
252 | /*--------------------
253 | Message Box
254 | --------------------*/
255 | .message-box {
256 | flex: 0 1 40px;
257 | width: 100%;
258 | background: rgba(0, 0, 0, 0.3);
259 | padding: 10px;
260 | position: relative;
261 |
262 | & .message-input {
263 | background: none;
264 | border: none;
265 | outline: none!important;
266 | resize: none;
267 | color: rgba(255, 255, 255, .7);
268 | font-size: 11px;
269 | height: 17px;
270 | margin: 0;
271 | padding-right: 20px;
272 | width: 265px;
273 | }
274 |
275 | textarea:focus:-webkit-placeholder{
276 | color: transparent;
277 | }
278 |
279 | & .message-submit {
280 | position: absolute;
281 | z-index: 1;
282 | top: 9px;
283 | right: 10px;
284 | color: #fff;
285 | border: none;
286 | background: #248A52;
287 | font-size: 10px;
288 | text-transform: uppercase;
289 | line-height: 1;
290 | padding: 6px 10px;
291 | border-radius: 10px;
292 | outline: none!important;
293 | transition: background .2s ease;
294 |
295 | &:hover {
296 | background: #1D7745;
297 | }
298 | }
299 | }
300 |
301 |
302 | /*--------------------
303 | Custom Srollbar
304 | --------------------*/
305 | .mCSB_scrollTools {
306 | margin: 1px -3px 1px 0;
307 | opacity: 0;
308 | }
309 |
310 | .mCSB_inside > .mCSB_container {
311 | margin-right: 0px;
312 | padding: 0 10px;
313 | }
314 |
315 | .mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar {
316 | background-color: rgba(0, 0, 0, 0.5)!important;
317 | }
318 |
319 |
320 | /*--------------------
321 | Bounce
322 | --------------------*/
323 | @keyframes bounce {
324 | 0% { transform: matrix3d(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
325 | 4.7% { transform: matrix3d(0.45, 0, 0, 0, 0, 0.45, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
326 | 9.41% { transform: matrix3d(0.883, 0, 0, 0, 0, 0.883, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
327 | 14.11% { transform: matrix3d(1.141, 0, 0, 0, 0, 1.141, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
328 | 18.72% { transform: matrix3d(1.212, 0, 0, 0, 0, 1.212, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
329 | 24.32% { transform: matrix3d(1.151, 0, 0, 0, 0, 1.151, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
330 | 29.93% { transform: matrix3d(1.048, 0, 0, 0, 0, 1.048, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
331 | 35.54% { transform: matrix3d(0.979, 0, 0, 0, 0, 0.979, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
332 | 41.04% { transform: matrix3d(0.961, 0, 0, 0, 0, 0.961, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
333 | 52.15% { transform: matrix3d(0.991, 0, 0, 0, 0, 0.991, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
334 | 63.26% { transform: matrix3d(1.007, 0, 0, 0, 0, 1.007, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
335 | 85.49% { transform: matrix3d(0.999, 0, 0, 0, 0, 0.999, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
336 | 100% { transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
337 | }
338 |
339 |
340 | @keyframes ball {
341 | from {
342 | transform: translateY(0) scaleY(.8);
343 | }
344 | to {
345 | transform: translateY(-10px);
346 | }
347 | }
348 |
--------------------------------------------------------------------------------
/ui/templates/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | @Janus
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
JANUS
20 |
Ask Me Anything
21 |
22 | 
23 |
24 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/working_dir/vocab20000.dec:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/suriyadeepan/easy_seq2seq/c05b0d02f15e9bd1947ff79ddcd0b761a214e2a9/working_dir/vocab20000.dec
--------------------------------------------------------------------------------
/working_dir/vocab20000.enc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/suriyadeepan/easy_seq2seq/c05b0d02f15e9bd1947ff79ddcd0b761a214e2a9/working_dir/vocab20000.enc
--------------------------------------------------------------------------------