datien228 commited on
Commit
d0ed3d4
1 Parent(s): 096db64

Add application repo

Browse files
.gitignore ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ ml/*/
2
+ *.jsonl
3
+ __pycache__
app.py ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, render_template, request, jsonify
2
+ from modules.model import summarize
3
+ import __main__
4
+
5
+ app = Flask(__name__)
6
+ # shortTokenizer = BartTokenizer.from_pretrained('sshleifer/distilbart-xsum-12-6')
7
+ # shortModel = BartForConditionalGeneration.from_pretrained('sshleifer/distilbart-xsum-12-6')
8
+
9
+ # longTokenizer = BartTokenizer.from_pretrained('sshleifer/distilbart-cnn-12-6')
10
+ # longModel = BartForConditionalGeneration.from_pretrained('sshleifer/distilbart-cnn-12-6')
11
+
12
+ @app.route('/')
13
+ def home():
14
+ return render_template('index.html')
15
+
16
+
17
+ @app.route('/summarize', methods=['GET', 'POST'])
18
+ def recommend():
19
+ if request.method == "POST":
20
+ # Get form data
21
+ request_data = request.get_json()
22
+ input_text = request_data['input_text']
23
+
24
+ # Call the function summarize to run the text summarization
25
+ try:
26
+ short_output_summary, long_output_summary = summarize(input_text)
27
+ # Pass output summary to the output template
28
+ return jsonify({'short': short_output_summary.strip(), 'long': long_output_summary.strip()})
29
+
30
+ except Exception as e:
31
+ return render_template('index.html', query=e)
32
+
33
+ pass
34
+
35
+ def main():
36
+ app.config['TEMPLATES_AUTO_RELOAD'] = True
37
+ app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 0
38
+ app.run(debug=True)
39
+ app.run()
40
+
41
+ if __name__ == '__main__':
42
+ print("Loading BART model and tokenzier . . .")
43
+ main()
modules/dataset.py ADDED
File without changes
modules/model.py ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from transformers import BartTokenizer, BartForConditionalGeneration
2
+ import sys
3
+
4
+ # shortTokenizer = BartTokenizer.from_pretrained('./ml/distilbart-xsum-12-6/', local_files_only=True)
5
+ # shortModel = BartForConditionalGeneration.from_pretrained('./ml/distilbart-xsum-12-6/', local_files_only=True)
6
+
7
+ # longTokenizer = BartTokenizer.from_pretrained('./ml/distilbart-cnn-12-6/', local_files_only=True)
8
+ # longModel = BartForConditionalGeneration.from_pretrained('./ml/distilbart-cnn-12-6/', local_files_only=True)
9
+
10
+ shortTokenizer = BartTokenizer.from_pretrained('./ml/distilbart-xsum-12-6/')
11
+ shortModel = BartForConditionalGeneration.from_pretrained('./ml/distilbart-xsum-12-6/')
12
+
13
+ longTokenizer = BartTokenizer.from_pretrained('datien228/distilbart-cnn-12-6-ftn-multi_news')
14
+ longModel = BartForConditionalGeneration.from_pretrained('datien228/distilbart-cnn-12-6-ftn-multi_news')
15
+
16
+
17
+ def summarize(text, num_beams=5, length_penalty=2.0, max_length=50, min_length=15, no_repeat_ngram_size=3):
18
+
19
+ text = text.replace('\n','')
20
+ text_input_ids = shortTokenizer.encode(text, return_tensors='pt', max_length=1024, truncation=True)
21
+ summary_ids = shortModel.generate(text_input_ids, num_beams=int(num_beams),
22
+ length_penalty=float(length_penalty),
23
+ max_length=int(max_length),
24
+ min_length=int(min_length),
25
+ no_repeat_ngram_size=int(no_repeat_ngram_size),
26
+ top_k=50)
27
+
28
+ short_summary_txt = shortTokenizer.decode(summary_ids.squeeze(), skip_special_tokens=True,
29
+ clean_up_tokenization_spaces=False)
30
+ print('Short summary done', file=sys.stderr)
31
+
32
+ text_input_ids = longTokenizer.encode(text, return_tensors='pt', max_length=1024, truncation=True)
33
+ summary_ids = longModel.generate(text_input_ids, num_beams=int(num_beams),
34
+ length_penalty=float(length_penalty),
35
+ # max_length=int(max_length)+45,
36
+ # min_length=int(min_length)+45,
37
+ no_repeat_ngram_size=int(no_repeat_ngram_size),
38
+ top_k=50)
39
+
40
+ long_summary_txt = longTokenizer.decode(summary_ids.squeeze(), skip_special_tokens=True,
41
+ clean_up_tokenization_spaces=False)
42
+ print('Long summary done', file=sys.stderr)
43
+
44
+ return short_summary_txt, long_summary_txt
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ torch==1.11.0
2
+ Flask==2.1.0
3
+ transformers==4.20.0
static/assets/css/all.css ADDED
The diff for this file is too large to render. See raw diff
 
static/assets/webfonts/fa-brands-400.ttf ADDED
Binary file (182 kB). View file
 
static/assets/webfonts/fa-brands-400.woff2 ADDED
Binary file (106 kB). View file
 
static/assets/webfonts/fa-regular-400.ttf ADDED
Binary file (60.5 kB). View file
 
static/assets/webfonts/fa-regular-400.woff2 ADDED
Binary file (23.9 kB). View file
 
static/assets/webfonts/fa-solid-900.ttf ADDED
Binary file (388 kB). View file
 
static/assets/webfonts/fa-solid-900.woff2 ADDED
Binary file (154 kB). View file
 
static/assets/webfonts/fa-v4compatibility.ttf ADDED
Binary file (10.6 kB). View file
 
static/assets/webfonts/fa-v4compatibility.woff2 ADDED
Binary file (4.96 kB). View file
 
static/css/style.css ADDED
@@ -0,0 +1,605 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ html, body {
2
+ --def: #fff;
3
+ --inv: #1d1d1d;
4
+ min-height:100%;
5
+ max-height:100%;
6
+ height:100%;
7
+ background:#fff;
8
+ }
9
+
10
+ *, *:before, *:after {
11
+ box-sizing: border-box;
12
+ }
13
+
14
+ * {
15
+ -webkit-transition: opacity .5s ease-in-out;
16
+ -moz-transition: opacity .5s ease-in-out;
17
+ -ms-transition: opacity .5s ease-in-out;
18
+ -o-transition: opacity .5s ease-in-out;
19
+ transition: opacity .5s ease-in-out;
20
+ }
21
+
22
+ .row * {
23
+ padding-left: 0;
24
+ padding-right: 0;
25
+ }
26
+
27
+ .page-title {
28
+ text-transform: uppercase;
29
+ }
30
+
31
+ .link-title {
32
+ cursor: pointer;
33
+ color: #1d1d1d;
34
+ transition: 250ms cubic-bezier(0.215,0.61,0.355,1);
35
+ transition-property: color, opacity;
36
+ }
37
+
38
+ .link-title:hover {
39
+ color: rgba(0, 0, 0, 0.75);
40
+ }
41
+
42
+ h1 {
43
+ font-size: 2.0vw;
44
+ font-family: "Manrope Extra Bold";
45
+ }
46
+ h2, h3 {
47
+ font-size: 2.5vh;
48
+ font-family: "Manrope Bold";
49
+ }
50
+ h4, p {
51
+ font-size: 1.5vmin;
52
+ font-family: "Manrope Light";
53
+ margin: 0
54
+ }
55
+ a {
56
+ text-decoration: none;
57
+ }
58
+
59
+ .spacer {
60
+ padding-top: 20px;
61
+ padding-bottom: 20px
62
+ }
63
+
64
+ .input-nlp-text, .output-nlp-text {
65
+ color: #1d1d1d !important;
66
+ font-family: "Manrope Light";
67
+ font-size: 2vmin;
68
+ height: 50vh;
69
+ width: 100%;
70
+ resize: none !important;
71
+ }
72
+
73
+ .form-control:focus {
74
+ border: 1px solid rgba(40, 40, 40, 0.85);
75
+ }
76
+
77
+ .input-nlp-text {
78
+ padding-right: calc(var(--bs-gutter-x) * .5);
79
+ padding-left: calc(var(--bs-gutter-x) * .5);
80
+ }
81
+
82
+ .input-nlp-text[readonly] {
83
+ background-color: white !important;
84
+ }
85
+
86
+ .output-nlp-text:disabled {
87
+ background-color: white !important;
88
+ }
89
+
90
+ .progress-icon {
91
+ position: absolute;
92
+ margin-left: auto;
93
+ margin-right: auto;
94
+ left: 0;
95
+ right: 0;
96
+ text-align: center;
97
+ position: relative;
98
+ height: 3em;
99
+ width: 3em;
100
+ display: inline-block;
101
+ border: 2px solid rgba(255,255,255,0.2);
102
+ border-radius: 50%;
103
+ border-left-color: #1d1d1d;
104
+ animation: rotate 1.2s linear infinite;
105
+ }
106
+
107
+ @keyframes rotate {
108
+ 50%{
109
+ border-left-color: #1d1d1d;
110
+ }
111
+ 75%{
112
+ border-left-color: #1d1d1d;
113
+ }
114
+ 100%{
115
+ transform: rotate(360deg);
116
+ }
117
+ }
118
+ .progress-icon .check-icon{
119
+ display: none;
120
+ }
121
+ .progress-icon .check-icon:after{
122
+ position: absolute;
123
+ content: "";
124
+ top: 50%;
125
+ left: 0.6em;
126
+ transform: scaleX(-1) rotate(135deg);
127
+ height: 1.5em;
128
+ width: 0.75em;
129
+ border-top: 4px solid #1d1d1d;
130
+ border-right: 4px solid #1d1d1d;
131
+ transform-origin: left top;
132
+ animation: check-icon 0.8s ease;
133
+ }
134
+ @keyframes check-icon {
135
+ 0%{
136
+ height: 0;
137
+ width: 0;
138
+ opacity: 1;
139
+ }
140
+ 20%{
141
+ height: 0;
142
+ width: 0.75em;
143
+ opacity: 1;
144
+ }
145
+ 40%{
146
+ height: 1.5em;
147
+ width: 0.75em;
148
+ opacity: 1;
149
+ }
150
+ 100%{
151
+ height: 1.5em;
152
+ width: 0.75em;
153
+ opacity: 1;
154
+ }
155
+ }
156
+ .toggle-load-icon {
157
+ display: none;
158
+ }
159
+ .toggle-load-icon:checked ~ .progress-icon .check-icon{
160
+ display: block;
161
+ }
162
+ .toggle-load-icon:checked ~ .progress-icon {
163
+ animation: none;
164
+ border-color: #1d1d1d;
165
+ transition: border 0.5s ease-out;
166
+ }
167
+
168
+ .no-border {
169
+ border: 0;
170
+ padding: 0;
171
+ box-shadow: none;
172
+ }
173
+
174
+ .js .loading::before,
175
+ .js .loading::after {
176
+ content: '';
177
+ position: fixed;
178
+ z-index: 1000;
179
+ }
180
+
181
+ .js .loading::before {
182
+ top: 0;
183
+ left: 0;
184
+ width: 100%;
185
+ height: 100%;
186
+ background: var(--color-bg);
187
+ }
188
+
189
+ .js .loading::after {
190
+ top: 50%;
191
+ left: 50%;
192
+ width: 60px;
193
+ height: 60px;
194
+ margin: -30px 0 0 -30px;
195
+ border-radius: 50%;
196
+ opacity: 0.4;
197
+ background: var(--color-link);
198
+ animation: loaderAnim 0.7s linear infinite alternate forwards;
199
+ }
200
+
201
+ @keyframes loaderAnim {
202
+ to {
203
+ opacity: 1;
204
+ transform: scale3d(0.5, 0.5, 1);
205
+ }
206
+ }
207
+
208
+ .nav-tabs {
209
+ width: 100vh;
210
+ position: absolute;
211
+ z-index: 1;
212
+ display: -webkit-inline-box;
213
+ display: -ms-inline-flexbox;
214
+ display: inline-flex;
215
+ border-width: 0px;
216
+ -ms-flex-flow: row-reverse nowrap;
217
+ flex-flow: row-reverse nowrap;
218
+ -webkit-box-pack: end;
219
+ -ms-flex-pack: end;
220
+ justify-content: center;
221
+ -webkit-transform: rotate(-90deg) translateX(-100%);
222
+ transform: rotate(-90deg) translateX(-100%);
223
+ -webkit-transform-origin: 0% 0%;
224
+ transform-origin: 0% 0%;
225
+ padding-left: 0;
226
+ }
227
+
228
+ .nav-tabs > li {
229
+ line-height: 5rem;
230
+ display: block;
231
+ padding: 9.6px 16px;
232
+ padding: 0.6rem 3rem;
233
+ list-style-type: none;
234
+ }
235
+
236
+ .nav-tabs > li > a {
237
+ font-family: "Manrope Regular";
238
+ color: #1d1d1d;
239
+ font-size: 2vmin;
240
+ }
241
+
242
+ .nav-tabs-r {
243
+ width: 100vh;
244
+ display: -webkit-inline-box;
245
+ display: -ms-inline-flexbox;
246
+ display: inline-flex;
247
+ border-width: 0px;
248
+ -ms-flex-flow: row-reverse nowrap;
249
+ flex-flow: row-reverse nowrap;
250
+ -webkit-box-pack: end;
251
+ -ms-flex-pack: end;
252
+ justify-content: center;
253
+ -webkit-transform: rotate(-90deg) translateX(-100%);
254
+ transform: rotate(-90deg) translateX(-100%);
255
+ -webkit-transform-origin: 100% 0%;
256
+ transform-origin: 100% 0%;
257
+ padding-right: 0;
258
+ }
259
+
260
+ .nav-tabs-r > li {
261
+ line-height: 5rem;
262
+ display: block;
263
+ padding: 0.6rem 3rem;
264
+ list-style-type: none;
265
+ }
266
+
267
+ .nav-tabs-r > li > a {
268
+ font-family: "Manrope Light";
269
+ color: #1d1d1d;
270
+ font-size: 2vmin;
271
+ }
272
+
273
+ li {
274
+ list-style:none
275
+ }
276
+
277
+ ul {
278
+ margin:0
279
+ }
280
+
281
+ textarea::-webkit-scrollbar {
282
+ display: none;
283
+ }
284
+
285
+ /* Hide scrollbar for IE, Edge and Firefox */
286
+ textarea {
287
+ -ms-overflow-style: none; /* IE and Edge */
288
+ scrollbar-width: none; /* Firefox */
289
+ }
290
+
291
+ .link {
292
+ cursor: pointer;
293
+ font-size: 2vmin;
294
+ position: relative;
295
+ white-space: nowrap;
296
+ color: var(--color-text);
297
+ }
298
+
299
+ .link::before,
300
+ .link::after {
301
+ position: absolute;
302
+ width: 100%;
303
+ height: 1px;
304
+ background: currentColor;
305
+ top: 100%;
306
+ left: 0;
307
+ pointer-events: none;
308
+ }
309
+
310
+ .link::before {
311
+ content: '';
312
+ /* show by default */
313
+ }
314
+
315
+ .link--io::before {
316
+ transform-origin: 100% 50%;
317
+ transform: scale3d(0, 1, 1);
318
+ transition: transform 0.3s cubic-bezier(0.7, 0, 0.2, 1);
319
+ }
320
+
321
+ .link--io:hover::before {
322
+ transform-origin: 0% 50%;
323
+ transform: scale3d(1, 1, 1);
324
+ transition-timing-function: cubic-bezier(0.4, 1, 0.8, 1);
325
+ }
326
+
327
+ .link--io::after {
328
+ content: '';
329
+ top: calc(100% + 4px);
330
+ transform-origin: 0% 50%;
331
+ transform: scale3d(0, 1, 1);
332
+ transition: transform 0.3s cubic-bezier(0.7, 0, 0.2, 1);
333
+ }
334
+
335
+ .link--io:hover::after {
336
+ transform-origin: 100% 50%;
337
+ transform: scale3d(1, 1, 1);
338
+ transition-timing-function: cubic-bezier(0.4, 1, 0.8, 1);
339
+ }
340
+
341
+ #metadata {
342
+ font-family: monospace;
343
+ }
344
+
345
+ #metadata p {
346
+ margin-top: 1em;
347
+ margin-bottom: 1em;
348
+ }
349
+
350
+ .input-field, .output-field {
351
+ padding: 0rem 2rem 0rem 2rem; /*top right bottom left*/
352
+ }
353
+
354
+ .button {
355
+ --offset: 10px;
356
+ --border-size: 1px;
357
+ display: block;
358
+ position: relative;
359
+ padding: 1.5em 3em;
360
+ margin: auto;
361
+ text-align:center;
362
+ -webkit-appearance: none;
363
+ -moz-appearance: none;
364
+ appearance: none;
365
+ border: 0;
366
+ background: transparent;
367
+ color: #1d1d1d;
368
+ font-family: "Manrope Medium";
369
+ font-size: 0.75vmax;
370
+ text-transform: uppercase;
371
+ letter-spacing: 0.25em;
372
+ outline: none;
373
+ cursor: pointer;
374
+ font-weight: bold;
375
+ border-radius: 0;
376
+ box-shadow: inset 0 0 0 var(--border-size) currentcolor;
377
+ transition: background 0.8s ease;
378
+ }
379
+ .button:hover {
380
+ background: rgba(100, 0, 0, 0.03);
381
+ }
382
+ .button__horizontal, .button__vertical {
383
+ position: absolute;
384
+ top: var(--horizontal-offset, 0);
385
+ right: var(--vertical-offset, 0);
386
+ bottom: var(--horizontal-offset, 0);
387
+ left: var(--vertical-offset, 0);
388
+ transition: transform 0.8s ease;
389
+ will-change: transform;
390
+ }
391
+ .button__horizontal::before, .button__vertical::before {
392
+ content: "";
393
+ position: absolute;
394
+ border: inherit;
395
+ }
396
+ .button__horizontal {
397
+ --vertical-offset: calc(var(--offset) * -1);
398
+ border-top: var(--border-size) solid currentcolor;
399
+ border-bottom: var(--border-size) solid currentcolor;
400
+ }
401
+ .button__horizontal::before {
402
+ top: calc(var(--vertical-offset) - var(--border-size));
403
+ bottom: calc(var(--vertical-offset) - var(--border-size));
404
+ left: calc(var(--vertical-offset) * -1);
405
+ right: calc(var(--vertical-offset) * -1);
406
+ }
407
+ .button:hover .button__horizontal {
408
+ transform: scaleX(0);
409
+ }
410
+ .button__vertical {
411
+ --horizontal-offset: calc(var(--offset) * -1);
412
+ border-left: var(--border-size) solid currentcolor;
413
+ border-right: var(--border-size) solid currentcolor;
414
+ }
415
+ .button__vertical::before {
416
+ top: calc(var(--horizontal-offset) * -1);
417
+ bottom: calc(var(--horizontal-offset) * -1);
418
+ left: calc(var(--horizontal-offset) - var(--border-size));
419
+ right: calc(var(--horizontal-offset) - var(--border-size));
420
+ }
421
+ .button:hover .button__vertical {
422
+ transform: scaleY(0);
423
+ }
424
+
425
+ .toggle {
426
+ margin: 0 0 1.5rem;
427
+ box-sizing: border-box;
428
+ font-size: 0;
429
+ display: flex;
430
+ flex-flow: row nowrap;
431
+ justify-content: flex-end;
432
+ align-items: stretch;
433
+ }
434
+ .toggle input {
435
+ width: 0;
436
+ height: 0;
437
+ position: absolute;
438
+ left: -9999px;
439
+ }
440
+ .toggle input + label {
441
+ margin: 0;
442
+ padding: 0.5rem 1rem;
443
+ box-sizing: border-box;
444
+ position: relative;
445
+ display: inline-block;
446
+ border: solid 1px rgb(207, 207, 207);
447
+ background-color: #fff;
448
+ font-family: "Manrope Medium";
449
+ font-size: 0.6rem;
450
+ line-height: 75%;
451
+ text-align: center;
452
+ /* box-shadow: 0 0 0 rgba(255, 255, 255, 0); */
453
+ transition: border-color 0.15s ease-out, color 0.25s ease-out, background-color 0.15s ease-out, box-shadow 0.15s ease-out;
454
+ /* ADD THESE PROPERTIES TO SWITCH FROM AUTO WIDTH TO FULL WIDTH */
455
+ /*flex: 0 0 50%;
456
+ display: flex;
457
+ justify-content: center;
458
+ align-items: center;
459
+ */
460
+ /* ----- */
461
+ }
462
+ .toggle input + label:first-of-type {
463
+ border-radius: 0px 0 0 0px;
464
+ border-right: none;
465
+ }
466
+ .toggle input + label:last-of-type {
467
+ border-radius: 0 0px 0px 0;
468
+ border-left: none;
469
+ }
470
+ .toggle input:hover + label {
471
+ border-color: #1d1d1d;
472
+ }
473
+ .toggle input:checked + label {
474
+ background-color: #1d1d1d;
475
+ color: #fff;
476
+ /* box-shadow: 0 0 10px rgba(102, 179, 251, .5); */
477
+ border-color: #1d1d1d;
478
+ z-index: 1;
479
+ }
480
+ /* .toggle input:focus + label {
481
+ outline: dotted 1px #ccc;
482
+ outline-offset: 0.45rem;
483
+ } */
484
+
485
+ .spacer {
486
+ display: none;
487
+ }
488
+
489
+ @media (max-width: 864px) {
490
+
491
+ .toggle input + label {
492
+ /* padding: 0.75rem 0.25rem; */
493
+ flex: 0 0 10%;
494
+ display: flex;
495
+ justify-content: center;
496
+ align-items: center;
497
+ font-size: 0.4rem;
498
+ }
499
+
500
+ h1 {
501
+ font-size: 2.5vh;
502
+ font-family: "Manrope Extra Bold";
503
+ letter-spacing: -2px;
504
+ }
505
+
506
+ h2, h3 {
507
+ font-size: 2.0vh;
508
+ font-family: "Manrope Bold";
509
+ }
510
+
511
+ h4, p {
512
+ font-size: 1.5vmin;
513
+ }
514
+
515
+ .input-nlp-text, .output-nlp-text {
516
+ font-size: 1.5vh;
517
+ }
518
+
519
+ .row {
520
+ margin-bottom: 0 !important;
521
+ }
522
+
523
+ #input_form {
524
+ margin-bottom: 1rem;
525
+ }
526
+
527
+ #input_text {
528
+ max-height: 20vh;
529
+ }
530
+
531
+ #output_text {
532
+ max-height: 15vh;
533
+ }
534
+
535
+ .nav-tabs {
536
+ display: none;
537
+ }
538
+
539
+ .flex-col {
540
+ flex-basis: 25%;
541
+ }
542
+
543
+ .flex-col-50 {
544
+ justify-content: space-between;
545
+ }
546
+
547
+ .flex-col-50 div {
548
+ flex-basis: 50%;
549
+ }
550
+
551
+ .spacer {
552
+ display: inline-block;
553
+ }
554
+ }
555
+
556
+ /*======================== FONT ===============================*/
557
+ @font-face {
558
+ font-family: "Gilroy Regular";
559
+ src: url("../fonts/gilroy-regular.otf") format("opentype");
560
+ }
561
+
562
+ @font-face {
563
+ font-family: "Gilroy Medium";
564
+ src: url("../fonts/gilroy_medium.otf") format("opentype");
565
+ }
566
+
567
+ @font-face {
568
+ font-family: "Gilroy Bold";
569
+ src: url("../fonts/gilroy-bold.otf") format("opentype");
570
+ }
571
+
572
+ @font-face {
573
+ font-family: "Manrope Bold";
574
+ src: url("../fonts/Manrope-Bold.otf") format("opentype");
575
+ }
576
+
577
+ @font-face {
578
+ font-family: "Manrope Extra Bold";
579
+ src: url("../fonts/Manrope-ExtraBold.otf") format("opentype");
580
+ }
581
+
582
+ @font-face {
583
+ font-family: "Manrope Extra Light";
584
+ src: url("../fonts/Manrope-ExtraLight.otf") format("opentype");
585
+ }
586
+
587
+ @font-face {
588
+ font-family: "Manrope Light";
589
+ src: url("../fonts/Manrope-Light.otf") format("opentype");
590
+ }
591
+
592
+ @font-face {
593
+ font-family: "Manrope Medium";
594
+ src: url("../fonts/Manrope-Medium.otf") format("opentype");
595
+ }
596
+
597
+ @font-face {
598
+ font-family: "Manrope Regular";
599
+ src: url("../fonts/Manrope-Regular.otf") format("opentype");
600
+ }
601
+
602
+ @font-face {
603
+ font-family: "Manrope Semi Bold";
604
+ src: url("../fonts/Manrope-SemiBold.otf") format("opentype");
605
+ }
static/fonts/Manrope-Bold.otf ADDED
Binary file (63.2 kB). View file
 
static/fonts/Manrope-ExtraBold.otf ADDED
Binary file (60.9 kB). View file
 
static/fonts/Manrope-ExtraLight.otf ADDED
Binary file (59.2 kB). View file
 
static/fonts/Manrope-Light.otf ADDED
Binary file (61.9 kB). View file
 
static/fonts/Manrope-Medium.otf ADDED
Binary file (61.9 kB). View file
 
static/fonts/Manrope-Regular.otf ADDED
Binary file (61.8 kB). View file
 
static/fonts/Manrope-SemiBold.otf ADDED
Binary file (61.9 kB). View file
 
static/fonts/gilroy-bold.otf ADDED
Binary file (138 kB). View file
 
static/fonts/gilroy-regular.otf ADDED
Binary file (130 kB). View file
 
static/fonts/gilroy-thin.otf ADDED
Binary file (129 kB). View file
 
static/fonts/gilroy_medium.otf ADDED
Binary file (134 kB). View file
 
static/js/app.js ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* -----------------------------------------------
2
+ /* How to use? : Check the GitHub README
3
+ /* ----------------------------------------------- */
4
+
5
+ /* To load a config file (particles.json) you need to host this demo (MAMP/WAMP/local)... */
6
+ /*
7
+ particlesJS.load('particles-js', 'particles.json', function() {
8
+ console.log('particles.js loaded - callback');
9
+ });
10
+ */
11
+
12
+ /* Otherwise just put the config content (json): */
13
+
14
+ particlesJS('particles-js',
15
+
16
+ {
17
+ "particles": {
18
+ "number": {
19
+ "value": 50,
20
+ "density": {
21
+ "enable": true,
22
+ "value_area": 800
23
+ }
24
+ },
25
+ "color": {
26
+ "value": "#1d1d1d"
27
+ },
28
+ "shape": {
29
+ "type": "circle",
30
+ "stroke": {
31
+ "width": 0,
32
+ "color": "#1d1d1d"
33
+ },
34
+ "polygon": {
35
+ "nb_sides": 5
36
+ },
37
+ "image": {
38
+ "src": "img/github.svg",
39
+ "width": 100,
40
+ "height": 100
41
+ }
42
+ },
43
+ "opacity": {
44
+ "value": 0.3,
45
+ "random": true,
46
+ "anim": {
47
+ "enable": false,
48
+ "speed": 1,
49
+ "opacity_min": 0.1,
50
+ "sync": false
51
+ }
52
+ },
53
+ "size": {
54
+ "value": 4,
55
+ "random": true,
56
+ "anim": {
57
+ "enable": false,
58
+ "speed": 40,
59
+ "size_min": 0.1,
60
+ "sync": false
61
+ }
62
+ },
63
+ "line_linked": {
64
+ "enable": true,
65
+ "distance": 150,
66
+ "color": "#3f3f3f",
67
+ "opacity": 0.4,
68
+ "width": 1
69
+ },
70
+ "move": {
71
+ "enable": true,
72
+ "speed": 2,
73
+ "direction": "none",
74
+ "random": false,
75
+ "straight": false,
76
+ "out_mode": "out",
77
+ "attract": {
78
+ "enable": false,
79
+ "rotateX": 600,
80
+ "rotateY": 1200
81
+ }
82
+ }
83
+ },
84
+ "interactivity": {
85
+ "detect_on": "canvas",
86
+ "events": {
87
+ "onhover": {
88
+ "enable": false,
89
+ "mode": "remove"
90
+ },
91
+ "onclick": {
92
+ "enable": false,
93
+ "mode": "push"
94
+ },
95
+ "resize": true
96
+ },
97
+ "modes": {
98
+ "grab": {
99
+ "distance": 400,
100
+ "line_linked": {
101
+ "opacity": 1
102
+ }
103
+ },
104
+ "bubble": {
105
+ "distance": 400,
106
+ "size": 40,
107
+ "duration": 2,
108
+ "opacity": 8,
109
+ "speed": 3
110
+ },
111
+ "repulse": {
112
+ "distance": 200
113
+ },
114
+ "push": {
115
+ "particles_nb": 2,
116
+ "speed": 3
117
+ },
118
+ "remove": {
119
+ "particles_nb": 2
120
+ }
121
+ }
122
+ },
123
+ "retina_detect": true,
124
+ "config_demo": {
125
+ "hide_card": false,
126
+ "background_color": "#b61924",
127
+ "background_image": "",
128
+ "background_position": "50% 50%",
129
+ "background_repeat": "no-repeat",
130
+ "background_size": "cover"
131
+ }
132
+ }
133
+
134
+ );
static/js/particles.js ADDED
@@ -0,0 +1,1541 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* -----------------------------------------------
2
+ /* Author : Vincent Garreau - vincentgarreau.com
3
+ /* MIT license: http://opensource.org/licenses/MIT
4
+ /* Demo / Generator : vincentgarreau.com/particles.js
5
+ /* GitHub : github.com/VincentGarreau/particles.js
6
+ /* How to use? : Check the GitHub README
7
+ /* v2.0.0
8
+ /* ----------------------------------------------- */
9
+
10
+ var pJS = function(tag_id, params){
11
+
12
+ var canvas_el = document.querySelector('#'+tag_id+' > .particles-js-canvas-el');
13
+
14
+ /* particles.js variables with default values */
15
+ this.pJS = {
16
+ canvas: {
17
+ el: canvas_el,
18
+ w: canvas_el.offsetWidth,
19
+ h: canvas_el.offsetHeight
20
+ },
21
+ particles: {
22
+ number: {
23
+ value: 400,
24
+ density: {
25
+ enable: true,
26
+ value_area: 800
27
+ }
28
+ },
29
+ color: {
30
+ value: '#fff'
31
+ },
32
+ shape: {
33
+ type: 'circle',
34
+ stroke: {
35
+ width: 0,
36
+ color: '#ff0000'
37
+ },
38
+ polygon: {
39
+ nb_sides: 5
40
+ },
41
+ image: {
42
+ src: '',
43
+ width: 100,
44
+ height: 100
45
+ }
46
+ },
47
+ opacity: {
48
+ value: 1,
49
+ random: false,
50
+ anim: {
51
+ enable: false,
52
+ speed: 2,
53
+ opacity_min: 0,
54
+ sync: false
55
+ }
56
+ },
57
+ size: {
58
+ value: 20,
59
+ random: false,
60
+ anim: {
61
+ enable: false,
62
+ speed: 20,
63
+ size_min: 0,
64
+ sync: false
65
+ }
66
+ },
67
+ line_linked: {
68
+ enable: true,
69
+ distance: 100,
70
+ color: '#fff',
71
+ opacity: 1,
72
+ width: 1
73
+ },
74
+ move: {
75
+ enable: true,
76
+ speed: 2,
77
+ direction: 'none',
78
+ random: false,
79
+ straight: false,
80
+ out_mode: 'out',
81
+ bounce: false,
82
+ attract: {
83
+ enable: false,
84
+ rotateX: 3000,
85
+ rotateY: 3000
86
+ }
87
+ },
88
+ array: []
89
+ },
90
+ interactivity: {
91
+ detect_on: 'canvas',
92
+ events: {
93
+ onhover: {
94
+ enable: true,
95
+ mode: 'grab'
96
+ },
97
+ onclick: {
98
+ enable: true,
99
+ mode: 'push'
100
+ },
101
+ resize: true
102
+ },
103
+ modes: {
104
+ grab:{
105
+ distance: 100,
106
+ line_linked:{
107
+ opacity: 1
108
+ }
109
+ },
110
+ bubble:{
111
+ distance: 200,
112
+ size: 80,
113
+ duration: 0.4
114
+ },
115
+ repulse:{
116
+ distance: 200,
117
+ duration: 0.4
118
+ },
119
+ push:{
120
+ particles_nb: 4
121
+ },
122
+ remove:{
123
+ particles_nb: 2
124
+ }
125
+ },
126
+ mouse:{}
127
+ },
128
+ retina_detect: false,
129
+ fn: {
130
+ interact: {},
131
+ modes: {},
132
+ vendors:{}
133
+ },
134
+ tmp: {}
135
+ };
136
+
137
+ var pJS = this.pJS;
138
+
139
+ /* params settings */
140
+ if(params){
141
+ Object.deepExtend(pJS, params);
142
+ }
143
+
144
+ pJS.tmp.obj = {
145
+ size_value: pJS.particles.size.value,
146
+ size_anim_speed: pJS.particles.size.anim.speed,
147
+ move_speed: pJS.particles.move.speed,
148
+ line_linked_distance: pJS.particles.line_linked.distance,
149
+ line_linked_width: pJS.particles.line_linked.width,
150
+ mode_grab_distance: pJS.interactivity.modes.grab.distance,
151
+ mode_bubble_distance: pJS.interactivity.modes.bubble.distance,
152
+ mode_bubble_size: pJS.interactivity.modes.bubble.size,
153
+ mode_repulse_distance: pJS.interactivity.modes.repulse.distance
154
+ };
155
+
156
+
157
+ pJS.fn.retinaInit = function(){
158
+
159
+ if(pJS.retina_detect && window.devicePixelRatio > 1){
160
+ pJS.canvas.pxratio = window.devicePixelRatio;
161
+ pJS.tmp.retina = true;
162
+ }
163
+ else{
164
+ pJS.canvas.pxratio = 1;
165
+ pJS.tmp.retina = false;
166
+ }
167
+
168
+ pJS.canvas.w = pJS.canvas.el.offsetWidth * pJS.canvas.pxratio;
169
+ pJS.canvas.h = pJS.canvas.el.offsetHeight * pJS.canvas.pxratio;
170
+
171
+ pJS.particles.size.value = pJS.tmp.obj.size_value * pJS.canvas.pxratio;
172
+ pJS.particles.size.anim.speed = pJS.tmp.obj.size_anim_speed * pJS.canvas.pxratio;
173
+ pJS.particles.move.speed = pJS.tmp.obj.move_speed * pJS.canvas.pxratio;
174
+ pJS.particles.line_linked.distance = pJS.tmp.obj.line_linked_distance * pJS.canvas.pxratio;
175
+ pJS.interactivity.modes.grab.distance = pJS.tmp.obj.mode_grab_distance * pJS.canvas.pxratio;
176
+ pJS.interactivity.modes.bubble.distance = pJS.tmp.obj.mode_bubble_distance * pJS.canvas.pxratio;
177
+ pJS.particles.line_linked.width = pJS.tmp.obj.line_linked_width * pJS.canvas.pxratio;
178
+ pJS.interactivity.modes.bubble.size = pJS.tmp.obj.mode_bubble_size * pJS.canvas.pxratio;
179
+ pJS.interactivity.modes.repulse.distance = pJS.tmp.obj.mode_repulse_distance * pJS.canvas.pxratio;
180
+
181
+ };
182
+
183
+
184
+
185
+ /* ---------- pJS functions - canvas ------------ */
186
+
187
+ pJS.fn.canvasInit = function(){
188
+ pJS.canvas.ctx = pJS.canvas.el.getContext('2d');
189
+ };
190
+
191
+ pJS.fn.canvasSize = function(){
192
+
193
+ pJS.canvas.el.width = pJS.canvas.w;
194
+ pJS.canvas.el.height = pJS.canvas.h;
195
+
196
+ if(pJS && pJS.interactivity.events.resize){
197
+
198
+ window.addEventListener('resize', function(){
199
+
200
+ pJS.canvas.w = pJS.canvas.el.offsetWidth;
201
+ pJS.canvas.h = pJS.canvas.el.offsetHeight;
202
+
203
+ /* resize canvas */
204
+ if(pJS.tmp.retina){
205
+ pJS.canvas.w *= pJS.canvas.pxratio;
206
+ pJS.canvas.h *= pJS.canvas.pxratio;
207
+ }
208
+
209
+ pJS.canvas.el.width = pJS.canvas.w;
210
+ pJS.canvas.el.height = pJS.canvas.h;
211
+
212
+ /* repaint canvas on anim disabled */
213
+ if(!pJS.particles.move.enable){
214
+ pJS.fn.particlesEmpty();
215
+ pJS.fn.particlesCreate();
216
+ pJS.fn.particlesDraw();
217
+ pJS.fn.vendors.densityAutoParticles();
218
+ }
219
+
220
+ /* density particles enabled */
221
+ pJS.fn.vendors.densityAutoParticles();
222
+
223
+ });
224
+
225
+ }
226
+
227
+ };
228
+
229
+
230
+ pJS.fn.canvasPaint = function(){
231
+ pJS.canvas.ctx.fillRect(0, 0, pJS.canvas.w, pJS.canvas.h);
232
+ };
233
+
234
+ pJS.fn.canvasClear = function(){
235
+ pJS.canvas.ctx.clearRect(0, 0, pJS.canvas.w, pJS.canvas.h);
236
+ };
237
+
238
+
239
+ /* --------- pJS functions - particles ----------- */
240
+
241
+ pJS.fn.particle = function(color, opacity, position){
242
+
243
+ /* size */
244
+ this.radius = (pJS.particles.size.random ? Math.random() : 1) * pJS.particles.size.value;
245
+ if(pJS.particles.size.anim.enable){
246
+ this.size_status = false;
247
+ this.vs = pJS.particles.size.anim.speed / 100;
248
+ if(!pJS.particles.size.anim.sync){
249
+ this.vs = this.vs * Math.random();
250
+ }
251
+ }
252
+
253
+ /* position */
254
+ this.x = position ? position.x : Math.random() * pJS.canvas.w;
255
+ this.y = position ? position.y : Math.random() * pJS.canvas.h;
256
+
257
+ /* check position - into the canvas */
258
+ if(this.x > pJS.canvas.w - this.radius*2) this.x = this.x - this.radius;
259
+ else if(this.x < this.radius*2) this.x = this.x + this.radius;
260
+ if(this.y > pJS.canvas.h - this.radius*2) this.y = this.y - this.radius;
261
+ else if(this.y < this.radius*2) this.y = this.y + this.radius;
262
+
263
+ /* check position - avoid overlap */
264
+ if(pJS.particles.move.bounce){
265
+ pJS.fn.vendors.checkOverlap(this, position);
266
+ }
267
+
268
+ /* color */
269
+ this.color = {};
270
+ if(typeof(color.value) == 'object'){
271
+
272
+ if(color.value instanceof Array){
273
+ var color_selected = color.value[Math.floor(Math.random() * pJS.particles.color.value.length)];
274
+ this.color.rgb = hexToRgb(color_selected);
275
+ }else{
276
+ if(color.value.r != undefined && color.value.g != undefined && color.value.b != undefined){
277
+ this.color.rgb = {
278
+ r: color.value.r,
279
+ g: color.value.g,
280
+ b: color.value.b
281
+ }
282
+ }
283
+ if(color.value.h != undefined && color.value.s != undefined && color.value.l != undefined){
284
+ this.color.hsl = {
285
+ h: color.value.h,
286
+ s: color.value.s,
287
+ l: color.value.l
288
+ }
289
+ }
290
+ }
291
+
292
+ }
293
+ else if(color.value == 'random'){
294
+ this.color.rgb = {
295
+ r: (Math.floor(Math.random() * (255 - 0 + 1)) + 0),
296
+ g: (Math.floor(Math.random() * (255 - 0 + 1)) + 0),
297
+ b: (Math.floor(Math.random() * (255 - 0 + 1)) + 0)
298
+ }
299
+ }
300
+ else if(typeof(color.value) == 'string'){
301
+ this.color = color;
302
+ this.color.rgb = hexToRgb(this.color.value);
303
+ }
304
+
305
+ /* opacity */
306
+ this.opacity = (pJS.particles.opacity.random ? Math.random() : 1) * pJS.particles.opacity.value;
307
+ if(pJS.particles.opacity.anim.enable){
308
+ this.opacity_status = false;
309
+ this.vo = pJS.particles.opacity.anim.speed / 100;
310
+ if(!pJS.particles.opacity.anim.sync){
311
+ this.vo = this.vo * Math.random();
312
+ }
313
+ }
314
+
315
+ /* animation - velocity for speed */
316
+ var velbase = {}
317
+ switch(pJS.particles.move.direction){
318
+ case 'top':
319
+ velbase = { x:0, y:-1 };
320
+ break;
321
+ case 'top-right':
322
+ velbase = { x:0.5, y:-0.5 };
323
+ break;
324
+ case 'right':
325
+ velbase = { x:1, y:-0 };
326
+ break;
327
+ case 'bottom-right':
328
+ velbase = { x:0.5, y:0.5 };
329
+ break;
330
+ case 'bottom':
331
+ velbase = { x:0, y:1 };
332
+ break;
333
+ case 'bottom-left':
334
+ velbase = { x:-0.5, y:1 };
335
+ break;
336
+ case 'left':
337
+ velbase = { x:-1, y:0 };
338
+ break;
339
+ case 'top-left':
340
+ velbase = { x:-0.5, y:-0.5 };
341
+ break;
342
+ default:
343
+ velbase = { x:0, y:0 };
344
+ break;
345
+ }
346
+
347
+ if(pJS.particles.move.straight){
348
+ this.vx = velbase.x;
349
+ this.vy = velbase.y;
350
+ if(pJS.particles.move.random){
351
+ this.vx = this.vx * (Math.random());
352
+ this.vy = this.vy * (Math.random());
353
+ }
354
+ }else{
355
+ this.vx = velbase.x + Math.random()-0.5;
356
+ this.vy = velbase.y + Math.random()-0.5;
357
+ }
358
+
359
+ // var theta = 2.0 * Math.PI * Math.random();
360
+ // this.vx = Math.cos(theta);
361
+ // this.vy = Math.sin(theta);
362
+
363
+ this.vx_i = this.vx;
364
+ this.vy_i = this.vy;
365
+
366
+
367
+
368
+ /* if shape is image */
369
+
370
+ var shape_type = pJS.particles.shape.type;
371
+ if(typeof(shape_type) == 'object'){
372
+ if(shape_type instanceof Array){
373
+ var shape_selected = shape_type[Math.floor(Math.random() * shape_type.length)];
374
+ this.shape = shape_selected;
375
+ }
376
+ }else{
377
+ this.shape = shape_type;
378
+ }
379
+
380
+ if(this.shape == 'image'){
381
+ var sh = pJS.particles.shape;
382
+ this.img = {
383
+ src: sh.image.src,
384
+ ratio: sh.image.width / sh.image.height
385
+ }
386
+ if(!this.img.ratio) this.img.ratio = 1;
387
+ if(pJS.tmp.img_type == 'svg' && pJS.tmp.source_svg != undefined){
388
+ pJS.fn.vendors.createSvgImg(this);
389
+ if(pJS.tmp.pushing){
390
+ this.img.loaded = false;
391
+ }
392
+ }
393
+ }
394
+
395
+
396
+
397
+ };
398
+
399
+
400
+ pJS.fn.particle.prototype.draw = function() {
401
+
402
+ var p = this;
403
+
404
+ if(p.radius_bubble != undefined){
405
+ var radius = p.radius_bubble;
406
+ }else{
407
+ var radius = p.radius;
408
+ }
409
+
410
+ if(p.opacity_bubble != undefined){
411
+ var opacity = p.opacity_bubble;
412
+ }else{
413
+ var opacity = p.opacity;
414
+ }
415
+
416
+ if(p.color.rgb){
417
+ var color_value = 'rgba('+p.color.rgb.r+','+p.color.rgb.g+','+p.color.rgb.b+','+opacity+')';
418
+ }else{
419
+ var color_value = 'hsla('+p.color.hsl.h+','+p.color.hsl.s+'%,'+p.color.hsl.l+'%,'+opacity+')';
420
+ }
421
+
422
+ pJS.canvas.ctx.fillStyle = color_value;
423
+ pJS.canvas.ctx.beginPath();
424
+
425
+ switch(p.shape){
426
+
427
+ case 'circle':
428
+ pJS.canvas.ctx.arc(p.x, p.y, radius, 0, Math.PI * 2, false);
429
+ break;
430
+
431
+ case 'edge':
432
+ pJS.canvas.ctx.rect(p.x-radius, p.y-radius, radius*2, radius*2);
433
+ break;
434
+
435
+ case 'triangle':
436
+ pJS.fn.vendors.drawShape(pJS.canvas.ctx, p.x-radius, p.y+radius / 1.66, radius*2, 3, 2);
437
+ break;
438
+
439
+ case 'polygon':
440
+ pJS.fn.vendors.drawShape(
441
+ pJS.canvas.ctx,
442
+ p.x - radius / (pJS.particles.shape.polygon.nb_sides/3.5), // startX
443
+ p.y - radius / (2.66/3.5), // startY
444
+ radius*2.66 / (pJS.particles.shape.polygon.nb_sides/3), // sideLength
445
+ pJS.particles.shape.polygon.nb_sides, // sideCountNumerator
446
+ 1 // sideCountDenominator
447
+ );
448
+ break;
449
+
450
+ case 'star':
451
+ pJS.fn.vendors.drawShape(
452
+ pJS.canvas.ctx,
453
+ p.x - radius*2 / (pJS.particles.shape.polygon.nb_sides/4), // startX
454
+ p.y - radius / (2*2.66/3.5), // startY
455
+ radius*2*2.66 / (pJS.particles.shape.polygon.nb_sides/3), // sideLength
456
+ pJS.particles.shape.polygon.nb_sides, // sideCountNumerator
457
+ 2 // sideCountDenominator
458
+ );
459
+ break;
460
+
461
+ case 'image':
462
+
463
+ function draw(){
464
+ pJS.canvas.ctx.drawImage(
465
+ img_obj,
466
+ p.x-radius,
467
+ p.y-radius,
468
+ radius*2,
469
+ radius*2 / p.img.ratio
470
+ );
471
+ }
472
+
473
+ if(pJS.tmp.img_type == 'svg'){
474
+ var img_obj = p.img.obj;
475
+ }else{
476
+ var img_obj = pJS.tmp.img_obj;
477
+ }
478
+
479
+ if(img_obj){
480
+ draw();
481
+ }
482
+
483
+ break;
484
+
485
+ }
486
+
487
+ pJS.canvas.ctx.closePath();
488
+
489
+ if(pJS.particles.shape.stroke.width > 0){
490
+ pJS.canvas.ctx.strokeStyle = pJS.particles.shape.stroke.color;
491
+ pJS.canvas.ctx.lineWidth = pJS.particles.shape.stroke.width;
492
+ pJS.canvas.ctx.stroke();
493
+ }
494
+
495
+ pJS.canvas.ctx.fill();
496
+
497
+ };
498
+
499
+
500
+ pJS.fn.particlesCreate = function(){
501
+ for(var i = 0; i < pJS.particles.number.value; i++) {
502
+ pJS.particles.array.push(new pJS.fn.particle(pJS.particles.color, pJS.particles.opacity.value));
503
+ }
504
+ };
505
+
506
+ pJS.fn.particlesUpdate = function(){
507
+
508
+ for(var i = 0; i < pJS.particles.array.length; i++){
509
+
510
+ /* the particle */
511
+ var p = pJS.particles.array[i];
512
+
513
+ // var d = ( dx = pJS.interactivity.mouse.click_pos_x - p.x ) * dx + ( dy = pJS.interactivity.mouse.click_pos_y - p.y ) * dy;
514
+ // var f = -BANG_SIZE / d;
515
+ // if ( d < BANG_SIZE ) {
516
+ // var t = Math.atan2( dy, dx );
517
+ // p.vx = f * Math.cos(t);
518
+ // p.vy = f * Math.sin(t);
519
+ // }
520
+
521
+ /* move the particle */
522
+ if(pJS.particles.move.enable){
523
+ var ms = pJS.particles.move.speed/2;
524
+ p.x += p.vx * ms;
525
+ p.y += p.vy * ms;
526
+ }
527
+
528
+ /* change opacity status */
529
+ if(pJS.particles.opacity.anim.enable) {
530
+ if(p.opacity_status == true) {
531
+ if(p.opacity >= pJS.particles.opacity.value) p.opacity_status = false;
532
+ p.opacity += p.vo;
533
+ }else {
534
+ if(p.opacity <= pJS.particles.opacity.anim.opacity_min) p.opacity_status = true;
535
+ p.opacity -= p.vo;
536
+ }
537
+ if(p.opacity < 0) p.opacity = 0;
538
+ }
539
+
540
+ /* change size */
541
+ if(pJS.particles.size.anim.enable){
542
+ if(p.size_status == true){
543
+ if(p.radius >= pJS.particles.size.value) p.size_status = false;
544
+ p.radius += p.vs;
545
+ }else{
546
+ if(p.radius <= pJS.particles.size.anim.size_min) p.size_status = true;
547
+ p.radius -= p.vs;
548
+ }
549
+ if(p.radius < 0) p.radius = 0;
550
+ }
551
+
552
+ /* change particle position if it is out of canvas */
553
+ if(pJS.particles.move.out_mode == 'bounce'){
554
+ var new_pos = {
555
+ x_left: p.radius,
556
+ x_right: pJS.canvas.w,
557
+ y_top: p.radius,
558
+ y_bottom: pJS.canvas.h
559
+ }
560
+ }else{
561
+ var new_pos = {
562
+ x_left: -p.radius,
563
+ x_right: pJS.canvas.w + p.radius,
564
+ y_top: -p.radius,
565
+ y_bottom: pJS.canvas.h + p.radius
566
+ }
567
+ }
568
+
569
+ if(p.x - p.radius > pJS.canvas.w){
570
+ p.x = new_pos.x_left;
571
+ p.y = Math.random() * pJS.canvas.h;
572
+ }
573
+ else if(p.x + p.radius < 0){
574
+ p.x = new_pos.x_right;
575
+ p.y = Math.random() * pJS.canvas.h;
576
+ }
577
+ if(p.y - p.radius > pJS.canvas.h){
578
+ p.y = new_pos.y_top;
579
+ p.x = Math.random() * pJS.canvas.w;
580
+ }
581
+ else if(p.y + p.radius < 0){
582
+ p.y = new_pos.y_bottom;
583
+ p.x = Math.random() * pJS.canvas.w;
584
+ }
585
+
586
+ /* out of canvas modes */
587
+ switch(pJS.particles.move.out_mode){
588
+ case 'bounce':
589
+ if (p.x + p.radius > pJS.canvas.w) p.vx = -p.vx;
590
+ else if (p.x - p.radius < 0) p.vx = -p.vx;
591
+ if (p.y + p.radius > pJS.canvas.h) p.vy = -p.vy;
592
+ else if (p.y - p.radius < 0) p.vy = -p.vy;
593
+ break;
594
+ }
595
+
596
+ /* events */
597
+ if(isInArray('grab', pJS.interactivity.events.onhover.mode)){
598
+ pJS.fn.modes.grabParticle(p);
599
+ }
600
+
601
+ if(isInArray('bubble', pJS.interactivity.events.onhover.mode) || isInArray('bubble', pJS.interactivity.events.onclick.mode)){
602
+ pJS.fn.modes.bubbleParticle(p);
603
+ }
604
+
605
+ if(isInArray('repulse', pJS.interactivity.events.onhover.mode) || isInArray('repulse', pJS.interactivity.events.onclick.mode)){
606
+ pJS.fn.modes.repulseParticle(p);
607
+ }
608
+
609
+ /* interaction auto between particles */
610
+ if(pJS.particles.line_linked.enable || pJS.particles.move.attract.enable){
611
+ for(var j = i + 1; j < pJS.particles.array.length; j++){
612
+ var p2 = pJS.particles.array[j];
613
+
614
+ /* link particles */
615
+ if(pJS.particles.line_linked.enable){
616
+ pJS.fn.interact.linkParticles(p,p2);
617
+ }
618
+
619
+ /* attract particles */
620
+ if(pJS.particles.move.attract.enable){
621
+ pJS.fn.interact.attractParticles(p,p2);
622
+ }
623
+
624
+ /* bounce particles */
625
+ if(pJS.particles.move.bounce){
626
+ pJS.fn.interact.bounceParticles(p,p2);
627
+ }
628
+
629
+ }
630
+ }
631
+
632
+
633
+ }
634
+
635
+ };
636
+
637
+ pJS.fn.particlesDraw = function(){
638
+
639
+ /* clear canvas */
640
+ pJS.canvas.ctx.clearRect(0, 0, pJS.canvas.w, pJS.canvas.h);
641
+
642
+ /* update each particles param */
643
+ pJS.fn.particlesUpdate();
644
+
645
+ /* draw each particle */
646
+ for(var i = 0; i < pJS.particles.array.length; i++){
647
+ var p = pJS.particles.array[i];
648
+ p.draw();
649
+ }
650
+
651
+ };
652
+
653
+ pJS.fn.particlesEmpty = function(){
654
+ pJS.particles.array = [];
655
+ };
656
+
657
+ pJS.fn.particlesRefresh = function(){
658
+
659
+ /* init all */
660
+ cancelRequestAnimFrame(pJS.fn.checkAnimFrame);
661
+ cancelRequestAnimFrame(pJS.fn.drawAnimFrame);
662
+ pJS.tmp.source_svg = undefined;
663
+ pJS.tmp.img_obj = undefined;
664
+ pJS.tmp.count_svg = 0;
665
+ pJS.fn.particlesEmpty();
666
+ pJS.fn.canvasClear();
667
+
668
+ /* restart */
669
+ pJS.fn.vendors.start();
670
+
671
+ };
672
+
673
+
674
+ /* ---------- pJS functions - particles interaction ------------ */
675
+
676
+ pJS.fn.interact.linkParticles = function(p1, p2){
677
+
678
+ var dx = p1.x - p2.x,
679
+ dy = p1.y - p2.y,
680
+ dist = Math.sqrt(dx*dx + dy*dy);
681
+
682
+ /* draw a line between p1 and p2 if the distance between them is under the config distance */
683
+ if(dist <= pJS.particles.line_linked.distance){
684
+
685
+ var opacity_line = pJS.particles.line_linked.opacity - (dist / (1/pJS.particles.line_linked.opacity)) / pJS.particles.line_linked.distance;
686
+
687
+ if(opacity_line > 0){
688
+
689
+ /* style */
690
+ var color_line = pJS.particles.line_linked.color_rgb_line;
691
+ pJS.canvas.ctx.strokeStyle = 'rgba('+color_line.r+','+color_line.g+','+color_line.b+','+opacity_line+')';
692
+ pJS.canvas.ctx.lineWidth = pJS.particles.line_linked.width;
693
+ //pJS.canvas.ctx.lineCap = 'round'; /* performance issue */
694
+
695
+ /* path */
696
+ pJS.canvas.ctx.beginPath();
697
+ pJS.canvas.ctx.moveTo(p1.x, p1.y);
698
+ pJS.canvas.ctx.lineTo(p2.x, p2.y);
699
+ pJS.canvas.ctx.stroke();
700
+ pJS.canvas.ctx.closePath();
701
+
702
+ }
703
+
704
+ }
705
+
706
+ };
707
+
708
+
709
+ pJS.fn.interact.attractParticles = function(p1, p2){
710
+
711
+ /* condensed particles */
712
+ var dx = p1.x - p2.x,
713
+ dy = p1.y - p2.y,
714
+ dist = Math.sqrt(dx*dx + dy*dy);
715
+
716
+ if(dist <= pJS.particles.line_linked.distance){
717
+
718
+ var ax = dx/(pJS.particles.move.attract.rotateX*1000),
719
+ ay = dy/(pJS.particles.move.attract.rotateY*1000);
720
+
721
+ p1.vx -= ax;
722
+ p1.vy -= ay;
723
+
724
+ p2.vx += ax;
725
+ p2.vy += ay;
726
+
727
+ }
728
+
729
+
730
+ }
731
+
732
+
733
+ pJS.fn.interact.bounceParticles = function(p1, p2){
734
+
735
+ var dx = p1.x - p2.x,
736
+ dy = p1.y - p2.y,
737
+ dist = Math.sqrt(dx*dx + dy*dy),
738
+ dist_p = p1.radius+p2.radius;
739
+
740
+ if(dist <= dist_p){
741
+ p1.vx = -p1.vx;
742
+ p1.vy = -p1.vy;
743
+
744
+ p2.vx = -p2.vx;
745
+ p2.vy = -p2.vy;
746
+ }
747
+
748
+ }
749
+
750
+
751
+ /* ---------- pJS functions - modes events ------------ */
752
+
753
+ pJS.fn.modes.pushParticles = function(nb, pos){
754
+
755
+ pJS.tmp.pushing = true;
756
+
757
+ for(var i = 0; i < nb; i++){
758
+ pJS.particles.array.push(
759
+ new pJS.fn.particle(
760
+ pJS.particles.color,
761
+ pJS.particles.opacity.value,
762
+ {
763
+ 'x': pos ? pos.pos_x : Math.random() * pJS.canvas.w,
764
+ 'y': pos ? pos.pos_y : Math.random() * pJS.canvas.h
765
+ }
766
+ )
767
+ )
768
+ if(i == nb-1){
769
+ if(!pJS.particles.move.enable){
770
+ pJS.fn.particlesDraw();
771
+ }
772
+ pJS.tmp.pushing = false;
773
+ }
774
+ }
775
+
776
+ };
777
+
778
+
779
+ pJS.fn.modes.removeParticles = function(nb){
780
+
781
+ pJS.particles.array.splice(0, nb);
782
+ if(!pJS.particles.move.enable){
783
+ pJS.fn.particlesDraw();
784
+ }
785
+
786
+ };
787
+
788
+
789
+ pJS.fn.modes.bubbleParticle = function(p){
790
+
791
+ /* on hover event */
792
+ if(pJS.interactivity.events.onhover.enable && isInArray('bubble', pJS.interactivity.events.onhover.mode)){
793
+
794
+ var dx_mouse = p.x - pJS.interactivity.mouse.pos_x,
795
+ dy_mouse = p.y - pJS.interactivity.mouse.pos_y,
796
+ dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse),
797
+ ratio = 1 - dist_mouse / pJS.interactivity.modes.bubble.distance;
798
+
799
+ function init(){
800
+ p.opacity_bubble = p.opacity;
801
+ p.radius_bubble = p.radius;
802
+ }
803
+
804
+ /* mousemove - check ratio */
805
+ if(dist_mouse <= pJS.interactivity.modes.bubble.distance){
806
+
807
+ if(ratio >= 0 && pJS.interactivity.status == 'mousemove'){
808
+
809
+ /* size */
810
+ if(pJS.interactivity.modes.bubble.size != pJS.particles.size.value){
811
+
812
+ if(pJS.interactivity.modes.bubble.size > pJS.particles.size.value){
813
+ var size = p.radius + (pJS.interactivity.modes.bubble.size*ratio);
814
+ if(size >= 0){
815
+ p.radius_bubble = size;
816
+ }
817
+ }else{
818
+ var dif = p.radius - pJS.interactivity.modes.bubble.size,
819
+ size = p.radius - (dif*ratio);
820
+ if(size > 0){
821
+ p.radius_bubble = size;
822
+ }else{
823
+ p.radius_bubble = 0;
824
+ }
825
+ }
826
+
827
+ }
828
+
829
+ /* opacity */
830
+ if(pJS.interactivity.modes.bubble.opacity != pJS.particles.opacity.value){
831
+
832
+ if(pJS.interactivity.modes.bubble.opacity > pJS.particles.opacity.value){
833
+ var opacity = pJS.interactivity.modes.bubble.opacity*ratio;
834
+ if(opacity > p.opacity && opacity <= pJS.interactivity.modes.bubble.opacity){
835
+ p.opacity_bubble = opacity;
836
+ }
837
+ }else{
838
+ var opacity = p.opacity - (pJS.particles.opacity.value-pJS.interactivity.modes.bubble.opacity)*ratio;
839
+ if(opacity < p.opacity && opacity >= pJS.interactivity.modes.bubble.opacity){
840
+ p.opacity_bubble = opacity;
841
+ }
842
+ }
843
+
844
+ }
845
+
846
+ }
847
+
848
+ }else{
849
+ init();
850
+ }
851
+
852
+
853
+ /* mouseleave */
854
+ if(pJS.interactivity.status == 'mouseleave'){
855
+ init();
856
+ }
857
+
858
+ }
859
+
860
+ /* on click event */
861
+ else if(pJS.interactivity.events.onclick.enable && isInArray('bubble', pJS.interactivity.events.onclick.mode)){
862
+
863
+
864
+ if(pJS.tmp.bubble_clicking){
865
+ var dx_mouse = p.x - pJS.interactivity.mouse.click_pos_x,
866
+ dy_mouse = p.y - pJS.interactivity.mouse.click_pos_y,
867
+ dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse),
868
+ time_spent = (new Date().getTime() - pJS.interactivity.mouse.click_time)/1000;
869
+
870
+ if(time_spent > pJS.interactivity.modes.bubble.duration){
871
+ pJS.tmp.bubble_duration_end = true;
872
+ }
873
+
874
+ if(time_spent > pJS.interactivity.modes.bubble.duration*2){
875
+ pJS.tmp.bubble_clicking = false;
876
+ pJS.tmp.bubble_duration_end = false;
877
+ }
878
+ }
879
+
880
+
881
+ function process(bubble_param, particles_param, p_obj_bubble, p_obj, id){
882
+
883
+ if(bubble_param != particles_param){
884
+
885
+ if(!pJS.tmp.bubble_duration_end){
886
+ if(dist_mouse <= pJS.interactivity.modes.bubble.distance){
887
+ if(p_obj_bubble != undefined) var obj = p_obj_bubble;
888
+ else var obj = p_obj;
889
+ if(obj != bubble_param){
890
+ var value = p_obj - (time_spent * (p_obj - bubble_param) / pJS.interactivity.modes.bubble.duration);
891
+ if(id == 'size') p.radius_bubble = value;
892
+ if(id == 'opacity') p.opacity_bubble = value;
893
+ }
894
+ }else{
895
+ if(id == 'size') p.radius_bubble = undefined;
896
+ if(id == 'opacity') p.opacity_bubble = undefined;
897
+ }
898
+ }else{
899
+ if(p_obj_bubble != undefined){
900
+ var value_tmp = p_obj - (time_spent * (p_obj - bubble_param) / pJS.interactivity.modes.bubble.duration),
901
+ dif = bubble_param - value_tmp;
902
+ value = bubble_param + dif;
903
+ if(id == 'size') p.radius_bubble = value;
904
+ if(id == 'opacity') p.opacity_bubble = value;
905
+ }
906
+ }
907
+
908
+ }
909
+
910
+ }
911
+
912
+ if(pJS.tmp.bubble_clicking){
913
+ /* size */
914
+ process(pJS.interactivity.modes.bubble.size, pJS.particles.size.value, p.radius_bubble, p.radius, 'size');
915
+ /* opacity */
916
+ process(pJS.interactivity.modes.bubble.opacity, pJS.particles.opacity.value, p.opacity_bubble, p.opacity, 'opacity');
917
+ }
918
+
919
+ }
920
+
921
+ };
922
+
923
+
924
+ pJS.fn.modes.repulseParticle = function(p){
925
+
926
+ if(pJS.interactivity.events.onhover.enable && isInArray('repulse', pJS.interactivity.events.onhover.mode) && pJS.interactivity.status == 'mousemove') {
927
+
928
+ var dx_mouse = p.x - pJS.interactivity.mouse.pos_x,
929
+ dy_mouse = p.y - pJS.interactivity.mouse.pos_y,
930
+ dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse);
931
+
932
+ var normVec = {x: dx_mouse/dist_mouse, y: dy_mouse/dist_mouse},
933
+ repulseRadius = pJS.interactivity.modes.repulse.distance,
934
+ velocity = 100,
935
+ repulseFactor = clamp((1/repulseRadius)*(-1*Math.pow(dist_mouse/repulseRadius,2)+1)*repulseRadius*velocity, 0, 50);
936
+
937
+ var pos = {
938
+ x: p.x + normVec.x * repulseFactor,
939
+ y: p.y + normVec.y * repulseFactor
940
+ }
941
+
942
+ if(pJS.particles.move.out_mode == 'bounce'){
943
+ if(pos.x - p.radius > 0 && pos.x + p.radius < pJS.canvas.w) p.x = pos.x;
944
+ if(pos.y - p.radius > 0 && pos.y + p.radius < pJS.canvas.h) p.y = pos.y;
945
+ }else{
946
+ p.x = pos.x;
947
+ p.y = pos.y;
948
+ }
949
+
950
+ }
951
+
952
+
953
+ else if(pJS.interactivity.events.onclick.enable && isInArray('repulse', pJS.interactivity.events.onclick.mode)) {
954
+
955
+ if(!pJS.tmp.repulse_finish){
956
+ pJS.tmp.repulse_count++;
957
+ if(pJS.tmp.repulse_count == pJS.particles.array.length){
958
+ pJS.tmp.repulse_finish = true;
959
+ }
960
+ }
961
+
962
+ if(pJS.tmp.repulse_clicking){
963
+
964
+ var repulseRadius = Math.pow(pJS.interactivity.modes.repulse.distance/6, 3);
965
+
966
+ var dx = pJS.interactivity.mouse.click_pos_x - p.x,
967
+ dy = pJS.interactivity.mouse.click_pos_y - p.y,
968
+ d = dx*dx + dy*dy;
969
+
970
+ var force = -repulseRadius / d * 1;
971
+
972
+ function process(){
973
+
974
+ var f = Math.atan2(dy,dx);
975
+ p.vx = force * Math.cos(f);
976
+ p.vy = force * Math.sin(f);
977
+
978
+ if(pJS.particles.move.out_mode == 'bounce'){
979
+ var pos = {
980
+ x: p.x + p.vx,
981
+ y: p.y + p.vy
982
+ }
983
+ if (pos.x + p.radius > pJS.canvas.w) p.vx = -p.vx;
984
+ else if (pos.x - p.radius < 0) p.vx = -p.vx;
985
+ if (pos.y + p.radius > pJS.canvas.h) p.vy = -p.vy;
986
+ else if (pos.y - p.radius < 0) p.vy = -p.vy;
987
+ }
988
+
989
+ }
990
+
991
+ // default
992
+ if(d <= repulseRadius){
993
+ process();
994
+ }
995
+
996
+ // bang - slow motion mode
997
+ // if(!pJS.tmp.repulse_finish){
998
+ // if(d <= repulseRadius){
999
+ // process();
1000
+ // }
1001
+ // }else{
1002
+ // process();
1003
+ // }
1004
+
1005
+
1006
+ }else{
1007
+
1008
+ if(pJS.tmp.repulse_clicking == false){
1009
+
1010
+ p.vx = p.vx_i;
1011
+ p.vy = p.vy_i;
1012
+
1013
+ }
1014
+
1015
+ }
1016
+
1017
+ }
1018
+
1019
+ }
1020
+
1021
+
1022
+ pJS.fn.modes.grabParticle = function(p){
1023
+
1024
+ if(pJS.interactivity.events.onhover.enable && pJS.interactivity.status == 'mousemove'){
1025
+
1026
+ var dx_mouse = p.x - pJS.interactivity.mouse.pos_x,
1027
+ dy_mouse = p.y - pJS.interactivity.mouse.pos_y,
1028
+ dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse);
1029
+
1030
+ /* draw a line between the cursor and the particle if the distance between them is under the config distance */
1031
+ if(dist_mouse <= pJS.interactivity.modes.grab.distance){
1032
+
1033
+ var opacity_line = pJS.interactivity.modes.grab.line_linked.opacity - (dist_mouse / (1/pJS.interactivity.modes.grab.line_linked.opacity)) / pJS.interactivity.modes.grab.distance;
1034
+
1035
+ if(opacity_line > 0){
1036
+
1037
+ /* style */
1038
+ var color_line = pJS.particles.line_linked.color_rgb_line;
1039
+ pJS.canvas.ctx.strokeStyle = 'rgba('+color_line.r+','+color_line.g+','+color_line.b+','+opacity_line+')';
1040
+ pJS.canvas.ctx.lineWidth = pJS.particles.line_linked.width;
1041
+ //pJS.canvas.ctx.lineCap = 'round'; /* performance issue */
1042
+
1043
+ /* path */
1044
+ pJS.canvas.ctx.beginPath();
1045
+ pJS.canvas.ctx.moveTo(p.x, p.y);
1046
+ pJS.canvas.ctx.lineTo(pJS.interactivity.mouse.pos_x, pJS.interactivity.mouse.pos_y);
1047
+ pJS.canvas.ctx.stroke();
1048
+ pJS.canvas.ctx.closePath();
1049
+
1050
+ }
1051
+
1052
+ }
1053
+
1054
+ }
1055
+
1056
+ };
1057
+
1058
+
1059
+
1060
+ /* ---------- pJS functions - vendors ------------ */
1061
+
1062
+ pJS.fn.vendors.eventsListeners = function(){
1063
+
1064
+ /* events target element */
1065
+ if(pJS.interactivity.detect_on == 'window'){
1066
+ pJS.interactivity.el = window;
1067
+ }else{
1068
+ pJS.interactivity.el = pJS.canvas.el;
1069
+ }
1070
+
1071
+
1072
+ /* detect mouse pos - on hover / click event */
1073
+ if(pJS.interactivity.events.onhover.enable || pJS.interactivity.events.onclick.enable){
1074
+
1075
+ /* el on mousemove */
1076
+ pJS.interactivity.el.addEventListener('mousemove', function(e){
1077
+
1078
+ if(pJS.interactivity.el == window){
1079
+ var pos_x = e.clientX,
1080
+ pos_y = e.clientY;
1081
+ }
1082
+ else{
1083
+ var pos_x = e.offsetX || e.clientX,
1084
+ pos_y = e.offsetY || e.clientY;
1085
+ }
1086
+
1087
+ pJS.interactivity.mouse.pos_x = pos_x;
1088
+ pJS.interactivity.mouse.pos_y = pos_y;
1089
+
1090
+ if(pJS.tmp.retina){
1091
+ pJS.interactivity.mouse.pos_x *= pJS.canvas.pxratio;
1092
+ pJS.interactivity.mouse.pos_y *= pJS.canvas.pxratio;
1093
+ }
1094
+
1095
+ pJS.interactivity.status = 'mousemove';
1096
+
1097
+ });
1098
+
1099
+ /* el on onmouseleave */
1100
+ pJS.interactivity.el.addEventListener('mouseleave', function(e){
1101
+
1102
+ pJS.interactivity.mouse.pos_x = null;
1103
+ pJS.interactivity.mouse.pos_y = null;
1104
+ pJS.interactivity.status = 'mouseleave';
1105
+
1106
+ });
1107
+
1108
+ }
1109
+
1110
+ /* on click event */
1111
+ if(pJS.interactivity.events.onclick.enable){
1112
+
1113
+ pJS.interactivity.el.addEventListener('click', function(){
1114
+
1115
+ pJS.interactivity.mouse.click_pos_x = pJS.interactivity.mouse.pos_x;
1116
+ pJS.interactivity.mouse.click_pos_y = pJS.interactivity.mouse.pos_y;
1117
+ pJS.interactivity.mouse.click_time = new Date().getTime();
1118
+
1119
+ if(pJS.interactivity.events.onclick.enable){
1120
+
1121
+ switch(pJS.interactivity.events.onclick.mode){
1122
+
1123
+ case 'push':
1124
+ if(pJS.particles.move.enable){
1125
+ pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb, pJS.interactivity.mouse);
1126
+ }else{
1127
+ if(pJS.interactivity.modes.push.particles_nb == 1){
1128
+ pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb, pJS.interactivity.mouse);
1129
+ }
1130
+ else if(pJS.interactivity.modes.push.particles_nb > 1){
1131
+ pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb);
1132
+ }
1133
+ }
1134
+ break;
1135
+
1136
+ case 'remove':
1137
+ pJS.fn.modes.removeParticles(pJS.interactivity.modes.remove.particles_nb);
1138
+ break;
1139
+
1140
+ case 'bubble':
1141
+ pJS.tmp.bubble_clicking = true;
1142
+ break;
1143
+
1144
+ case 'repulse':
1145
+ pJS.tmp.repulse_clicking = true;
1146
+ pJS.tmp.repulse_count = 0;
1147
+ pJS.tmp.repulse_finish = false;
1148
+ setTimeout(function(){
1149
+ pJS.tmp.repulse_clicking = false;
1150
+ }, pJS.interactivity.modes.repulse.duration*1000)
1151
+ break;
1152
+
1153
+ }
1154
+
1155
+ }
1156
+
1157
+ });
1158
+
1159
+ }
1160
+
1161
+
1162
+ };
1163
+
1164
+ pJS.fn.vendors.densityAutoParticles = function(){
1165
+
1166
+ if(pJS.particles.number.density.enable){
1167
+
1168
+ /* calc area */
1169
+ var area = pJS.canvas.el.width * pJS.canvas.el.height / 1000;
1170
+ if(pJS.tmp.retina){
1171
+ area = area/(pJS.canvas.pxratio*2);
1172
+ }
1173
+
1174
+ /* calc number of particles based on density area */
1175
+ var nb_particles = area * pJS.particles.number.value / pJS.particles.number.density.value_area;
1176
+
1177
+ /* add or remove X particles */
1178
+ var missing_particles = pJS.particles.array.length - nb_particles;
1179
+ if(missing_particles < 0) pJS.fn.modes.pushParticles(Math.abs(missing_particles));
1180
+ else pJS.fn.modes.removeParticles(missing_particles);
1181
+
1182
+ }
1183
+
1184
+ };
1185
+
1186
+
1187
+ pJS.fn.vendors.checkOverlap = function(p1, position){
1188
+ for(var i = 0; i < pJS.particles.array.length; i++){
1189
+ var p2 = pJS.particles.array[i];
1190
+
1191
+ var dx = p1.x - p2.x,
1192
+ dy = p1.y - p2.y,
1193
+ dist = Math.sqrt(dx*dx + dy*dy);
1194
+
1195
+ if(dist <= p1.radius + p2.radius){
1196
+ p1.x = position ? position.x : Math.random() * pJS.canvas.w;
1197
+ p1.y = position ? position.y : Math.random() * pJS.canvas.h;
1198
+ pJS.fn.vendors.checkOverlap(p1);
1199
+ }
1200
+ }
1201
+ };
1202
+
1203
+
1204
+ pJS.fn.vendors.createSvgImg = function(p){
1205
+
1206
+ /* set color to svg element */
1207
+ var svgXml = pJS.tmp.source_svg,
1208
+ rgbHex = /#([0-9A-F]{3,6})/gi,
1209
+ coloredSvgXml = svgXml.replace(rgbHex, function (m, r, g, b) {
1210
+ if(p.color.rgb){
1211
+ var color_value = 'rgba('+p.color.rgb.r+','+p.color.rgb.g+','+p.color.rgb.b+','+p.opacity+')';
1212
+ }else{
1213
+ var color_value = 'hsla('+p.color.hsl.h+','+p.color.hsl.s+'%,'+p.color.hsl.l+'%,'+p.opacity+')';
1214
+ }
1215
+ return color_value;
1216
+ });
1217
+
1218
+ /* prepare to create img with colored svg */
1219
+ var svg = new Blob([coloredSvgXml], {type: 'image/svg+xml;charset=utf-8'}),
1220
+ DOMURL = window.URL || window.webkitURL || window,
1221
+ url = DOMURL.createObjectURL(svg);
1222
+
1223
+ /* create particle img obj */
1224
+ var img = new Image();
1225
+ img.addEventListener('load', function(){
1226
+ p.img.obj = img;
1227
+ p.img.loaded = true;
1228
+ DOMURL.revokeObjectURL(url);
1229
+ pJS.tmp.count_svg++;
1230
+ });
1231
+ img.src = url;
1232
+
1233
+ };
1234
+
1235
+
1236
+ pJS.fn.vendors.destroypJS = function(){
1237
+ cancelAnimationFrame(pJS.fn.drawAnimFrame);
1238
+ canvas_el.remove();
1239
+ pJSDom = null;
1240
+ };
1241
+
1242
+
1243
+ pJS.fn.vendors.drawShape = function(c, startX, startY, sideLength, sideCountNumerator, sideCountDenominator){
1244
+
1245
+ // By Programming Thomas - https://programmingthomas.wordpress.com/2013/04/03/n-sided-shapes/
1246
+ var sideCount = sideCountNumerator * sideCountDenominator;
1247
+ var decimalSides = sideCountNumerator / sideCountDenominator;
1248
+ var interiorAngleDegrees = (180 * (decimalSides - 2)) / decimalSides;
1249
+ var interiorAngle = Math.PI - Math.PI * interiorAngleDegrees / 180; // convert to radians
1250
+ c.save();
1251
+ c.beginPath();
1252
+ c.translate(startX, startY);
1253
+ c.moveTo(0,0);
1254
+ for (var i = 0; i < sideCount; i++) {
1255
+ c.lineTo(sideLength,0);
1256
+ c.translate(sideLength,0);
1257
+ c.rotate(interiorAngle);
1258
+ }
1259
+ //c.stroke();
1260
+ c.fill();
1261
+ c.restore();
1262
+
1263
+ };
1264
+
1265
+ pJS.fn.vendors.exportImg = function(){
1266
+ window.open(pJS.canvas.el.toDataURL('image/png'), '_blank');
1267
+ };
1268
+
1269
+
1270
+ pJS.fn.vendors.loadImg = function(type){
1271
+
1272
+ pJS.tmp.img_error = undefined;
1273
+
1274
+ if(pJS.particles.shape.image.src != ''){
1275
+
1276
+ if(type == 'svg'){
1277
+
1278
+ var xhr = new XMLHttpRequest();
1279
+ xhr.open('GET', pJS.particles.shape.image.src);
1280
+ xhr.onreadystatechange = function (data) {
1281
+ if(xhr.readyState == 4){
1282
+ if(xhr.status == 200){
1283
+ pJS.tmp.source_svg = data.currentTarget.response;
1284
+ pJS.fn.vendors.checkBeforeDraw();
1285
+ }else{
1286
+ console.log('Error pJS - Image not found');
1287
+ pJS.tmp.img_error = true;
1288
+ }
1289
+ }
1290
+ }
1291
+ xhr.send();
1292
+
1293
+ }else{
1294
+
1295
+ var img = new Image();
1296
+ img.addEventListener('load', function(){
1297
+ pJS.tmp.img_obj = img;
1298
+ pJS.fn.vendors.checkBeforeDraw();
1299
+ });
1300
+ img.src = pJS.particles.shape.image.src;
1301
+
1302
+ }
1303
+
1304
+ }else{
1305
+ console.log('Error pJS - No image.src');
1306
+ pJS.tmp.img_error = true;
1307
+ }
1308
+
1309
+ };
1310
+
1311
+
1312
+ pJS.fn.vendors.draw = function(){
1313
+
1314
+ if(pJS.particles.shape.type == 'image'){
1315
+
1316
+ if(pJS.tmp.img_type == 'svg'){
1317
+
1318
+ if(pJS.tmp.count_svg >= pJS.particles.number.value){
1319
+ pJS.fn.particlesDraw();
1320
+ if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame);
1321
+ else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
1322
+ }else{
1323
+ //console.log('still loading...');
1324
+ if(!pJS.tmp.img_error) pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
1325
+ }
1326
+
1327
+ }else{
1328
+
1329
+ if(pJS.tmp.img_obj != undefined){
1330
+ pJS.fn.particlesDraw();
1331
+ if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame);
1332
+ else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
1333
+ }else{
1334
+ if(!pJS.tmp.img_error) pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
1335
+ }
1336
+
1337
+ }
1338
+
1339
+ }else{
1340
+ pJS.fn.particlesDraw();
1341
+ if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame);
1342
+ else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
1343
+ }
1344
+
1345
+ };
1346
+
1347
+
1348
+ pJS.fn.vendors.checkBeforeDraw = function(){
1349
+
1350
+ // if shape is image
1351
+ if(pJS.particles.shape.type == 'image'){
1352
+
1353
+ if(pJS.tmp.img_type == 'svg' && pJS.tmp.source_svg == undefined){
1354
+ pJS.tmp.checkAnimFrame = requestAnimFrame(check);
1355
+ }else{
1356
+ //console.log('images loaded! cancel check');
1357
+ cancelRequestAnimFrame(pJS.tmp.checkAnimFrame);
1358
+ if(!pJS.tmp.img_error){
1359
+ pJS.fn.vendors.init();
1360
+ pJS.fn.vendors.draw();
1361
+ }
1362
+
1363
+ }
1364
+
1365
+ }else{
1366
+ pJS.fn.vendors.init();
1367
+ pJS.fn.vendors.draw();
1368
+ }
1369
+
1370
+ };
1371
+
1372
+
1373
+ pJS.fn.vendors.init = function(){
1374
+
1375
+ /* init canvas + particles */
1376
+ pJS.fn.retinaInit();
1377
+ pJS.fn.canvasInit();
1378
+ pJS.fn.canvasSize();
1379
+ pJS.fn.canvasPaint();
1380
+ pJS.fn.particlesCreate();
1381
+ pJS.fn.vendors.densityAutoParticles();
1382
+
1383
+ /* particles.line_linked - convert hex colors to rgb */
1384
+ pJS.particles.line_linked.color_rgb_line = hexToRgb(pJS.particles.line_linked.color);
1385
+
1386
+ };
1387
+
1388
+
1389
+ pJS.fn.vendors.start = function(){
1390
+
1391
+ if(isInArray('image', pJS.particles.shape.type)){
1392
+ pJS.tmp.img_type = pJS.particles.shape.image.src.substr(pJS.particles.shape.image.src.length - 3);
1393
+ pJS.fn.vendors.loadImg(pJS.tmp.img_type);
1394
+ }else{
1395
+ pJS.fn.vendors.checkBeforeDraw();
1396
+ }
1397
+
1398
+ };
1399
+
1400
+
1401
+
1402
+
1403
+ /* ---------- pJS - start ------------ */
1404
+
1405
+
1406
+ pJS.fn.vendors.eventsListeners();
1407
+
1408
+ pJS.fn.vendors.start();
1409
+
1410
+
1411
+
1412
+ };
1413
+
1414
+ /* ---------- global functions - vendors ------------ */
1415
+
1416
+ Object.deepExtend = function(destination, source) {
1417
+ for (var property in source) {
1418
+ if (source[property] && source[property].constructor &&
1419
+ source[property].constructor === Object) {
1420
+ destination[property] = destination[property] || {};
1421
+ arguments.callee(destination[property], source[property]);
1422
+ } else {
1423
+ destination[property] = source[property];
1424
+ }
1425
+ }
1426
+ return destination;
1427
+ };
1428
+
1429
+ window.requestAnimFrame = (function(){
1430
+ return window.requestAnimationFrame ||
1431
+ window.webkitRequestAnimationFrame ||
1432
+ window.mozRequestAnimationFrame ||
1433
+ window.oRequestAnimationFrame ||
1434
+ window.msRequestAnimationFrame ||
1435
+ function(callback){
1436
+ window.setTimeout(callback, 1000 / 60);
1437
+ };
1438
+ })();
1439
+
1440
+ window.cancelRequestAnimFrame = ( function() {
1441
+ return window.cancelAnimationFrame ||
1442
+ window.webkitCancelRequestAnimationFrame ||
1443
+ window.mozCancelRequestAnimationFrame ||
1444
+ window.oCancelRequestAnimationFrame ||
1445
+ window.msCancelRequestAnimationFrame ||
1446
+ clearTimeout
1447
+ } )();
1448
+
1449
+ function hexToRgb(hex){
1450
+ // By Tim Down - http://stackoverflow.com/a/5624139/3493650
1451
+ // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
1452
+ var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
1453
+ hex = hex.replace(shorthandRegex, function(m, r, g, b) {
1454
+ return r + r + g + g + b + b;
1455
+ });
1456
+ var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
1457
+ return result ? {
1458
+ r: parseInt(result[1], 16),
1459
+ g: parseInt(result[2], 16),
1460
+ b: parseInt(result[3], 16)
1461
+ } : null;
1462
+ };
1463
+
1464
+ function clamp(number, min, max) {
1465
+ return Math.min(Math.max(number, min), max);
1466
+ };
1467
+
1468
+ function isInArray(value, array) {
1469
+ return array.indexOf(value) > -1;
1470
+ }
1471
+
1472
+
1473
+ /* ---------- particles.js functions - start ------------ */
1474
+
1475
+ window.pJSDom = [];
1476
+
1477
+ window.particlesJS = function(tag_id, params){
1478
+
1479
+ //console.log(params);
1480
+
1481
+ /* no string id? so it's object params, and set the id with default id */
1482
+ if(typeof(tag_id) != 'string'){
1483
+ params = tag_id;
1484
+ tag_id = 'particles-js';
1485
+ }
1486
+
1487
+ /* no id? set the id to default id */
1488
+ if(!tag_id){
1489
+ tag_id = 'particles-js';
1490
+ }
1491
+
1492
+ /* pJS elements */
1493
+ var pJS_tag = document.getElementById(tag_id),
1494
+ pJS_canvas_class = 'particles-js-canvas-el',
1495
+ exist_canvas = pJS_tag.getElementsByClassName(pJS_canvas_class);
1496
+
1497
+ /* remove canvas if exists into the pJS target tag */
1498
+ if(exist_canvas.length){
1499
+ while(exist_canvas.length > 0){
1500
+ pJS_tag.removeChild(exist_canvas[0]);
1501
+ }
1502
+ }
1503
+
1504
+ /* create canvas element */
1505
+ var canvas_el = document.createElement('canvas');
1506
+ canvas_el.className = pJS_canvas_class;
1507
+
1508
+ /* set size canvas */
1509
+ canvas_el.style.width = "100%";
1510
+ canvas_el.style.height = "100%";
1511
+
1512
+ /* append canvas */
1513
+ var canvas = document.getElementById(tag_id).appendChild(canvas_el);
1514
+
1515
+ /* launch particle.js */
1516
+ if(canvas != null){
1517
+ pJSDom.push(new pJS(tag_id, params));
1518
+ }
1519
+
1520
+ };
1521
+
1522
+ window.particlesJS.load = function(tag_id, path_config_json, callback){
1523
+
1524
+ /* load json config */
1525
+ var xhr = new XMLHttpRequest();
1526
+ xhr.open('GET', path_config_json);
1527
+ xhr.onreadystatechange = function (data) {
1528
+ if(xhr.readyState == 4){
1529
+ if(xhr.status == 200){
1530
+ var params = JSON.parse(data.currentTarget.response);
1531
+ window.particlesJS(tag_id, params);
1532
+ if(callback) callback();
1533
+ }else{
1534
+ console.log('Error pJS - XMLHttpRequest status: '+xhr.status);
1535
+ console.log('Error pJS - File config not found');
1536
+ }
1537
+ }
1538
+ };
1539
+ xhr.send();
1540
+
1541
+ };
static/js/style.js ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // ======= INPUT FIELD (FORM CONTROL) VALIDATION =======
2
+ var runOnce = false;
3
+ var short_summary = '';
4
+ var long_summary = '';
5
+
6
+ (function () {
7
+ 'use strict'
8
+ const forms = document.querySelectorAll('.requires-validation')
9
+ Array.from(forms)
10
+ .forEach(function (form) {
11
+ form.addEventListener('submit', function (event) {
12
+ if (!form.checkValidity()) {
13
+ event.preventDefault()
14
+ event.stopPropagation()
15
+ }
16
+ form.classList.add('was-validated')
17
+ }, false)
18
+ })
19
+ })()
20
+
21
+ // ======= RESET INPUT FIELD WHEN USER CLICKED AT IT (HAS RAN ONCE) =======
22
+ $(function () {
23
+ $('#input_text').on("input", function () {
24
+ if (runOnce == true) {
25
+ $(".progress-icon").hide();
26
+ $("#load-noti").hide();
27
+ $(".summarize-button").fadeIn();
28
+ }
29
+ });
30
+ });
31
+
32
+ $('#short_button').on("click", function () {
33
+ var outputField = document.getElementById("output_text");
34
+ outputField.innerHTML = short_summary;
35
+ });
36
+ $('#long_button').on("click", function () {
37
+ var outputField = document.getElementById("output_text");
38
+ outputField.innerHTML = long_summary;
39
+ });
40
+
41
+ setInterval(function (e) {
42
+ var strText = jQuery.trim($('#input_text').val());
43
+ var cntChar = strText.replace(/ /g, '').length;
44
+ var cntWord = strText.split(/\s+/).length;
45
+ var cntPar = strText.split("\n").length;
46
+ var postFix = '';
47
+
48
+ if (strText == '') {
49
+ cntWord = 0;
50
+ cntLine = 0;
51
+ }
52
+
53
+ //$('#cnt-paras').children('p').text(cntPar + (cntPar > 1 ? " pars" : " par"));
54
+ $('#cnt-words').children('p').text(cntWord + (cntWord > 1 ? " words" : " word"));
55
+ $('#cnt-chars').children('p').text(cntChar + (cntChar > 1 ? " chars" : " char"));
56
+ }, 100);
57
+
58
+ // ======= COMMUNICATE WITH FLSAK BACK END TO RUN ML TASK =======
59
+ $(document).on('submit', '#input_form', function (e) {
60
+ var outputField = document.getElementById("output_text");
61
+ var data = { "input_text": $("#input_text").val() };
62
+ e.preventDefault();
63
+ $.ajax({
64
+ type: 'POST',
65
+ url: '/summarize',
66
+ data: JSON.stringify(data),
67
+ contentType: "application/json",
68
+ dataType: 'json',
69
+ beforeSend: function () {
70
+ $("#check").attr('checked', false);
71
+ $("#input_text").attr("readonly", true);
72
+ $(".summarize-button").hide();
73
+ $(".progress-icon").fadeIn();
74
+ $("#load-noti").fadeIn();
75
+ },
76
+ success: function (response) {
77
+ $("#check").attr('checked', true);
78
+ $("#input_text").attr("readonly", false);
79
+ $("#load-noti").text("Completed")
80
+ short_summary = response.short;
81
+ long_summary = response.long;
82
+ outputField.innerHTML = short_summary;
83
+ },
84
+ complete: function () {
85
+ runOnce = true;
86
+ },
87
+ })
88
+ });
templates/creator.html ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ {% extends "index.html" %}
2
+
3
+ {% block content %}
4
+
5
+ {% endblock %}
templates/development.html ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ {% extends "index.html" %}
2
+
3
+ {% block content %}
4
+
5
+ {% endblock %}
templates/feedback.html ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ {% extends "index.html" %}
2
+
3
+ {% block content %}
4
+
5
+ {% endblock %}
templates/index.html ADDED
@@ -0,0 +1,250 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="en" class="js">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <meta name="description" content="summary is a small web application that help users summarizing long documents.">
7
+ <title>summary</title>
8
+ <link href="{{ url_for('static', filename='assets/favicon.png') }}" rel="icon" type="image/png" sizes="16x16">
9
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous">
10
+ <link href="{{ url_for('static', filename='css/style.css') }}" rel="stylesheet">
11
+ <link href="{{ url_for('static', filename='assets/css/all.css') }}" rel="stylesheet">
12
+ <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
13
+ <!-- <script src="{{ url_for('static', filename='js/style.js') }}"></script> -->
14
+ </head>
15
+ <body class="d-flex flex-column min-vh-100">
16
+ <ul class="nav nav-tabs">
17
+ <li><a href="#" class="link link--io">creator</a></li>
18
+ <li><a href="#" class="link link--io">development</a></li>
19
+ <li><a href="#" class="link link--io">feedback</a></li>
20
+ </ul>
21
+ <div class="container-fluid">
22
+ <div class="row">
23
+ <div class="col-md-12 my-4">
24
+ <a href="{{ url_for('home') }}" class="link-title">
25
+ <h1 class="text-center page-title">
26
+ summary
27
+ </h1>
28
+ </a>
29
+ </div>
30
+ </div>
31
+ <div class="row mt-4">
32
+ <div class="col-md-1"></div>
33
+ <div class="col-md-4 input-field">
34
+ <div class="row mb-4 flex-col-50">
35
+ <div class="col-md-8">
36
+ <h2 class="main-heading">
37
+ put your text here
38
+ </h2>
39
+ <p>You can change document's language</p>
40
+ </div>
41
+ <div class="col-md-4 switch-format">
42
+ <div class="toggle">
43
+ <input type="radio" name="langSel" value="eng" id="engLang" checked="checked" />
44
+ <label for="engLang">eng</label>
45
+ <input type="radio" name="langSel" value="vie" id="vieLang" />
46
+ <label for="vieLang">vie</label>
47
+ </div>
48
+ </div>
49
+ </div>
50
+ <div class="row mb-4">
51
+ <div class="col-md-12">
52
+ <form id="input_form" class="form-horizontal requires-validation" method="post" novalidate>
53
+ <textarea type="text" class="input-nlp-text form-control shadow-none" id="input_text" name="input_text"
54
+ placeholder="Enter the documents here >" aria-label="Input Document" required value="@Request["inputText"]"></textarea>
55
+ <!-- <div class="valid-feedback">
56
+ Text looks good!
57
+ </div>
58
+ <div class="invalid-feedback">
59
+ Text is required!
60
+ </div>-->
61
+ </form>
62
+ </div>
63
+ </div>
64
+ <div class="row text-white" id="metadata">
65
+ <div class="col-md-3 bg-black text-center flex-col" id="cnt-paras">
66
+ <p>0 par</p>
67
+ </div>
68
+ <div class="col-md-3 bg-black text-center flex-col" id="cnt-words">
69
+ <p>0 word</p>
70
+ </div>
71
+ <div class="col-md-3 bg-black text-center flex-col" id="cnt-chars">
72
+ <p>0 char</p>
73
+ </div>
74
+ <div class="col-md-3 bg-black text-center flex-col">
75
+ <p>english</p>
76
+ </div>
77
+ </div>
78
+ </div>
79
+ <div class="spacer"></div>
80
+ <div class="col-md-2 text-center my-auto">
81
+ <div class="d-flex flex-column justify-content-center">
82
+ <!-- <i class="fa-2x fa-solid fa-circle-check progress-icon" hidden></i> -->
83
+ <input class="toggle-load-icon" type="checkbox" id="check" disabled>
84
+ <label class="progress-icon" for="check" style="display:none">
85
+ <div class="check-icon"></div>
86
+ </label>
87
+ <button class="button summarize-button" type="submit" form="input_form">
88
+ summarize
89
+ <div class="button__horizontal"></div>
90
+ <div class="button__vertical"></div>
91
+ </button>
92
+ </div>
93
+ <h2 class="mt-2 pt-2" id="load-noti" style="display:none">Generating</h2>
94
+ </div>
95
+ <div class="spacer"></div>
96
+ <div class="col-md-4 output-field">
97
+ <div class="row mb-4 flex-col-50">
98
+ <div class="col-md-8">
99
+ <h2 class="main-heading">
100
+ summary here
101
+ </h2>
102
+ <p>You can change summary's length</p>
103
+ </div>
104
+ <div class="col-md-4 switch-format">
105
+ <div class="toggle">
106
+ <input type="radio" name="lengSel" value="short" id="shortSum" checked="checked" />
107
+ <label for="shortSum">short</label>
108
+ <input type="radio" name="lengSel" value="long" id="longSum" />
109
+ <label for="longSum">long</label>
110
+ </div>
111
+ <!-- <button type="button" class="floated btn btn-outline-dark btn-sm btn-block" id="short_button">short</button>
112
+ <button type="button" class="floated btn btn-outline-dark btn-sm btn-block" id="long_button">long</button> -->
113
+ <!-- <button class="btn btn-outline-dark btn-sm"><i class="fa-solid fa-2xs">Expand</i></button> -->
114
+ </div>
115
+ </div>
116
+ <div class="row mb-4">
117
+ <div class="col-md-12">
118
+ <textarea type="text" class="output-nlp-text no-border shadow-none" id="output_text"
119
+ placeholder="Output will be shown here >" aria-label="Output Document" disabled></textarea>
120
+ </div>
121
+ </div>
122
+ </div>
123
+ <div class="col-md-1"></div>
124
+ </div>
125
+ </div>
126
+ <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2" crossorigin="anonymous"></script>
127
+ <script>
128
+ // ======= INPUT FIELD (FORM CONTROL) VALIDATION =======
129
+ var runOnce = false;
130
+ var short_summary = '';
131
+ var long_summary = '';
132
+
133
+ (function () {
134
+ 'use strict'
135
+ const forms = document.querySelectorAll('.requires-validation')
136
+ Array.from(forms)
137
+ .forEach(function (form) {
138
+ form.addEventListener('submit', function (event) {
139
+ if (!form.checkValidity()) {
140
+ event.preventDefault()
141
+ event.stopPropagation()
142
+ }
143
+ form.classList.add('was-validated')
144
+ }, false)
145
+ })
146
+ })()
147
+
148
+ // ======= RESET INPUT FIELD WHEN USER CLICKED AT IT (HAS RAN ONCE) =======
149
+ $(function () {
150
+ $('#input_text').on("input", function () {
151
+ if (runOnce == true) {
152
+ $(".progress-icon").hide();
153
+ $("#load-noti").hide();
154
+ $(".summarize-button").fadeIn();
155
+ }
156
+ });
157
+ });
158
+
159
+ $('#shortSum').on("click", function () {
160
+ var outputField = document.getElementById("output_text");
161
+ outputField.innerHTML = short_summary;
162
+ });
163
+ $('#longSum').on("click", function () {
164
+ var outputField = document.getElementById("output_text");
165
+ outputField.innerHTML = long_summary;
166
+ });
167
+
168
+ setInterval(function (e) {
169
+ var strText = jQuery.trim($('#input_text').val());
170
+ var cntChar = strText.replace( /[\r\n]+/gm, "" ).length;
171
+ var cntWord = strText.split(/[\s\.\?]+/).length;
172
+ var cntPara = strText.split("\n\n").length;
173
+ var cntPara2 = strText.split("/\n\s/g").length;
174
+ var postFix = '';
175
+
176
+ if (strText == '') {
177
+ cntWord = 0;
178
+ cntLine = 0;
179
+ cntPara = 0;
180
+ }
181
+
182
+ $('#cnt-paras').children('p').text(cntPara + (cntPara > 1 ? " pars" : " par"));
183
+ $('#cnt-words').children('p').text(cntWord + (cntWord > 1 ? " words" : " word"));
184
+ $('#cnt-chars').children('p').text(cntChar + (cntChar > 1 ? " chars" : " char"));
185
+ }, 100);
186
+
187
+ // ======= COMMUNICATE WITH FLSAK BACK END TO RUN ML TASK =======
188
+ $(document).on('submit', '#input_form', function (e) {
189
+ var outputField = document.getElementById("output_text");
190
+ var data = { "input_text": $("#input_text").val() };
191
+ e.preventDefault();
192
+ $.ajax({
193
+ type: 'POST',
194
+ url: '/summarize',
195
+ data: JSON.stringify(data),
196
+ contentType: "application/json",
197
+ dataType: 'json',
198
+ beforeSend: function () {
199
+ $("#check").attr('checked', false);
200
+ $("#input_text").attr("readonly", true);
201
+ $(".summarize-button").hide();
202
+ $(".progress-icon").fadeIn();
203
+ $("#load-noti").fadeIn();
204
+ },
205
+ success: function (response) {
206
+ short_summary = response.short;
207
+ long_summary = response.long;
208
+ outputField.innerHTML = short_summary;
209
+ },
210
+ complete: function (response) {
211
+ $("#check").attr('checked', true);
212
+ $("#input_text").attr("readonly", false);
213
+ $("#load-noti").text("Completed")
214
+ runOnce = true;
215
+ },
216
+ })
217
+ });
218
+
219
+ </script>
220
+ </body>
221
+ <footer class="bg-light text-center text-dark mt-auto">
222
+ <div class="container mt-3 pb-0">
223
+ <section class="mb-3">
224
+ <h4>Processing speed depends on the document's length</h4>
225
+ <!-- Linkedin -->
226
+ <!-- <a class="btn btn-sm btn-outline-light btn-floating m-1" href="#!" role="button"
227
+ ><i class="fab fa-linkedin-in small"></i
228
+ ></a> -->
229
+
230
+ <!-- Github -->
231
+ <!-- <a class="btn btn-sm btn-light btn-floating m-1 small" href="#!" role="button"
232
+ ><i class="fab fa-github small"></i
233
+ ></a> -->
234
+ </section>
235
+ </div>
236
+
237
+ <!-- Copyright -->
238
+ <div class="text-center p-2 bg-dark">
239
+ <p class="text-white">
240
+ Created by
241
+ <a class="link-light" href="https://github.com/anhtien228" style="font-weight: 600;">Anh-Tien Doan</a>
242
+ in 2022
243
+ </p>
244
+ <a class="link-secondary" href="https://flask.palletsprojects.com/en/2.1.x/" style="transition: 0.2s ease-in-out;">
245
+ <p>built with Flask</p>
246
+ </a>
247
+ </div>
248
+ <!-- Copyright -->
249
+ </footer>
250
+ </html>