active_frontend 14.0.99 → 14.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 81d929bbda4bb03643b3f14d0b48b1bfa7185a7c
4
- data.tar.gz: a1f515f1c2608a3ec7b7693057b632e53034c162
3
+ metadata.gz: f57c9edde86486ff06bfd1b06a40ee8c37bb369e
4
+ data.tar.gz: 458fcea810df0496b760427523b2e1ddf12de5de
5
5
  SHA512:
6
- metadata.gz: a949db01af534d560057a6a2d0563ff539be89f411948938f9535fea216144e2a203fbff2159fcdc7c91de4279d1575bb5037209d8f1071ff568e8756e9e98f7
7
- data.tar.gz: 342a4d9a68ac7b28baa3e0ead15c3373c71b5e588713d17e9ba461724d99d4132f7481a7c4a576f35888b5db32c98ce89745a8ab94fc13c9cb69d6c9daa1bbe7
6
+ metadata.gz: dd62aead62296100fe505794f36fe0fee9b5be6f1eadb4c9b283e3a26900036cc1480d4fa5c2925ad289b0cb2479aad7c0afe4e188d2f11f25a414043c5eac25
7
+ data.tar.gz: bedb7761b4179de6a64f41f527a4c4239afdb6d832ded11013740f8148585ca9c789ec9190a1b514f71f3ea307402c96d22d02a553e9a2af881dd0017d70c7d8
@@ -1,3 +1,3 @@
1
1
  module ActiveFrontend
2
- VERSION = '14.0.99'.freeze
2
+ VERSION = '14.1.0'.freeze
3
3
  end
@@ -30,6 +30,7 @@
30
30
  //= require base/_selectpicker
31
31
  //= require base/_timepicker
32
32
  //= require base/_typeahead
33
+ //= require base/_tag
33
34
  //= require base/_timeago
34
35
  //= require base/_switch
35
36
  //= require base/_timezone
@@ -44,5 +45,6 @@
44
45
  //= require extensions/_copy
45
46
  //= require extensions/_funnel
46
47
  //= require extensions/_map
48
+ //= require extensions/_push
47
49
  //= require extensions/_wysiwyg
48
50
  //
@@ -46,6 +46,7 @@
46
46
  @import 'components/selectpicker';
47
47
  @import 'components/timepicker';
48
48
  @import 'components/typeahead';
49
+ @import 'components/tag';
49
50
  @import 'components/ad';
50
51
  @import 'components/label_and_badge';
51
52
  @import 'components/breadcrumb';
@@ -30,6 +30,7 @@
30
30
  //= require base/_selectpicker
31
31
  //= require base/_timepicker
32
32
  //= require base/_typeahead
33
+ //= require base/_tag
33
34
  //= require base/_timeago
34
35
  //= require base/_switch
35
36
  //= require base/_timezone
@@ -44,5 +45,6 @@
44
45
  //= require extensions/_copy
45
46
  //= require extensions/_funnel
46
47
  //= require extensions/_map
48
+ //= require extensions/_push
47
49
  //= require extensions/_wysiwyg
48
50
  //
@@ -0,0 +1,649 @@
1
+ +function ($) {
2
+ 'use strict';
3
+
4
+ // TAG CLASS DEFINITION
5
+ // ====================
6
+
7
+ var Tag = function (element, options) {
8
+ this.isInit = true;
9
+ this.itemsArray = [];
10
+ this.$element = $(element);
11
+ this.$element.hide();
12
+ this.isSelect = (element.tagName === 'SELECT');
13
+ this.multiple = (this.isSelect && element.hasAttribute('multiple'));
14
+ this.objectItems = options && options.itemValue;
15
+ this.placeholderText = element.hasAttribute('placeholder') ? this.$element.attr('placeholder') : '';
16
+ this.inputSize = Math.max(1, this.placeholderText.length);
17
+ this.$container = $('<div class="form-tags"></div>');
18
+ this.$input = $('<input type="text" placeholder="' + this.placeholderText + '"/>').appendTo(this.$container);
19
+ this.$element.before(this.$container);
20
+ this.build(options);
21
+ this.isInit = false;
22
+ };
23
+
24
+ Tag.VERSION = '1.0.0';
25
+ Tag.DEFAULTS = {
26
+ itemText: function(item) {
27
+ return this.itemValue(item);
28
+ },
29
+ itemTitle: function(item) {
30
+ return null;
31
+ },
32
+ itemValue: function(item) {
33
+ return item ? item.toString() : item;
34
+ },
35
+ onTagExists: function(item, $tag) {},
36
+ tagClass: function(item) {
37
+ return 'label';
38
+ },
39
+ addOnBlur: true,
40
+ allowDuplicates: false,
41
+ cancelConfirmKeysOnEmpty: false,
42
+ confirmKeys: [13, 44],
43
+ delimiter: ',',
44
+ delimiterRegex: null,
45
+ focusClass: 'focus',
46
+ freeInput: true,
47
+ maxChars: undefined,
48
+ maxTags: undefined,
49
+ triggerChange: true,
50
+ trimValue: true
51
+ };
52
+
53
+ Tag.prototype.constructor = Tag;
54
+
55
+ Tag.prototype.stopTimer = function () {
56
+ return clearTimeout(this.interval);
57
+ };
58
+
59
+ Tag.prototype.getHtmlAttributes = function (item) {
60
+ if (this.options.itemAttributes === undefined) return '';
61
+
62
+ var res = ' ';
63
+ var itemAttributes = this.options.itemAttributes;
64
+
65
+ for (var e in itemAttributes) {
66
+ if (typeof itemAttributes[e] !== 'function') {
67
+ res += e + '="' + itemAttributes[e].toString() + '"';
68
+ } else {
69
+ res += e + '="' + itemAttributes[e](item) + '"';
70
+ }
71
+ }
72
+
73
+ return res;
74
+ };
75
+
76
+ Tag.prototype.add = function(item, dontPushVal, options) {
77
+ var _self = this;
78
+
79
+ if (_self.options.maxTags && _self.itemsArray.length >= _self.options.maxTags) return;
80
+ if (item !== false && !item) return;
81
+
82
+ if (typeof item === "string" && _self.options.trimValue) {
83
+ item = $.trim(item);
84
+ }
85
+
86
+ if (typeof item === 'object' && !_self.objectItems) throw("Can't add objects when itemValue option is not set");
87
+ if (item.toString().match(/^\s*$/)) return;
88
+ if (_self.isSelect && !_self.multiple && _self.itemsArray.length > 0) _self.remove(_self.itemsArray[0]);
89
+
90
+ if (typeof item === 'string' && this.$element[0].tagName === 'INPUT') {
91
+ var delimiter = (_self.options.delimiterRegex) ? _self.options.delimiterRegex : _self.options.delimiter;
92
+ var items = item.split(delimiter);
93
+
94
+ if (items.length > 1) {
95
+ for (var i = 0; i < items.length; i++) {
96
+ this.add(items[i], true);
97
+ }
98
+
99
+ if (!dontPushVal) _self.pushVal(_self.options.triggerChange);
100
+
101
+ return;
102
+ }
103
+ }
104
+
105
+ var itemValue = _self.options.itemValue(item);
106
+ var itemText = _self.options.itemText(item);
107
+ var tagClass = _self.options.tagClass(item);
108
+ var itemTitle = _self.options.itemTitle(item);
109
+
110
+ var existing = $.grep(_self.itemsArray, function(item) {
111
+ return _self.options.itemValue(item) === itemValue;
112
+ })[0];
113
+
114
+ if (existing && !_self.options.allowDuplicates) {
115
+ if (_self.options.onTagExists) {
116
+ var $existingTag = $('.tag', _self.$container).filter(function () {
117
+ return $(this).data('item') === existing;
118
+ });
119
+
120
+ _self.options.onTagExists(item, $existingTag);
121
+ }
122
+
123
+ return;
124
+ }
125
+
126
+ if (_self.items().toString().length + item.length + 1 > _self.options.maxInputLength) return;
127
+
128
+ var beforeItemAddEvent = $.Event('beforeItemAdd', {
129
+ item: item,
130
+ cancel: false,
131
+ options: options
132
+ });
133
+
134
+ _self.$element.trigger(beforeItemAddEvent);
135
+
136
+ if (beforeItemAddEvent.cancel) return;
137
+
138
+ _self.itemsArray.push(item);
139
+
140
+ var attrs = _self.getHtmlAttributes(item);
141
+ var $tag = $('<span ' +
142
+ _self.htmlEncode(attrs) +
143
+ ' class="tag ' +
144
+ _self.htmlEncode(tagClass) +
145
+ (itemTitle !== null ? ('" title="' + itemTitle) : '') +
146
+ '">' +
147
+ _self.htmlEncode(itemText) +
148
+ '<span data-role="remove"></span></span>');
149
+
150
+ $tag.data('item', item);
151
+
152
+ _self.findInputWrapper()
153
+ .before($tag);
154
+
155
+ $tag.after(' ');
156
+
157
+ var optionExists = (
158
+ $('option[value="' + encodeURIComponent(itemValue) + '"]', _self.$element).length ||
159
+ $('option[value="' + _self.htmlEncode(itemValue) + '"]', _self.$element).length
160
+ );
161
+
162
+ if (_self.isSelect && !optionExists) {
163
+ var $option = $('<option selected>' + _self.htmlEncode(itemText) + '</option>');
164
+
165
+ $option.data('item', item)
166
+ .attr('value', itemValue);
167
+ _self.$element.append($option);
168
+ }
169
+
170
+ if (!dontPushVal) _self.pushVal(_self.options.triggerChange);
171
+
172
+ if (_self.options.maxTags === _self.itemsArray.length || _self.items().toString().length === _self.options.maxInputLength) {
173
+ _self.$container
174
+ .addClass('form-tags-max');
175
+ }
176
+
177
+ if ($('.typeahead', _self.$container).length) {
178
+ setTimeout(function () {
179
+ _self.$input.val('');
180
+ }, 0);
181
+ }
182
+
183
+ if (this.isInit) {
184
+ _self.$element.trigger($.Event('itemAddedOnInit', {
185
+ item: item,
186
+ options: options
187
+ }));
188
+ } else {
189
+ _self.$element.trigger($.Event('itemAdded', {
190
+ item: item,
191
+ options: options
192
+ }));
193
+ }
194
+ };
195
+
196
+ Tag.prototype.remove = function(item, dontPushVal, options) {
197
+ var _self = this;
198
+
199
+ if (_self.objectItems) {
200
+ if (typeof item === 'object') {
201
+ item = $.grep(_self.itemsArray, function (other) {
202
+ return _self.options.itemValue(other) === _self.options.itemValue(item);
203
+ });
204
+ } else {
205
+ item = $.grep(_self.itemsArray, function (other) {
206
+ return _self.options.itemValue(other) === item;
207
+ });
208
+ }
209
+
210
+ item = item[item.length-1];
211
+ }
212
+
213
+ if (item) {
214
+ var beforeItemRemoveEvent = $.Event('beforeItemRemove', {
215
+ item: item,
216
+ cancel: false,
217
+ options: options
218
+ });
219
+
220
+ _self.$element.trigger(beforeItemRemoveEvent);
221
+
222
+ if (beforeItemRemoveEvent.cancel) return;
223
+
224
+ $('.tag', _self.$container).filter(function () {
225
+ return $(this).data('item') === item;
226
+ }).remove();
227
+ $('option', _self.$element).filter(function () {
228
+ return $(this).data('item') === item;
229
+ }).remove();
230
+
231
+ if ($.inArray(item, _self.itemsArray) !== -1) _self.itemsArray.splice($.inArray(item, _self.itemsArray), 1);
232
+ }
233
+
234
+ if (!dontPushVal) _self.pushVal(_self.options.triggerChange);
235
+
236
+ if (_self.options.maxTags > _self.itemsArray.length) _self.$container.removeClass('form-tags-max');
237
+
238
+ _self.$element
239
+ .trigger($.Event('itemRemoved', {
240
+ item: item,
241
+ options: options
242
+ }));
243
+ };
244
+
245
+ Tag.prototype.removeAll = function() {
246
+ $('.tag', this.$container).remove();
247
+ $('option', this.$element).remove();
248
+
249
+ while(this.itemsArray.length > 0) this.itemsArray.pop();
250
+
251
+ this.pushVal(this.options.triggerChange);
252
+ };
253
+
254
+ Tag.prototype.refresh = function() {
255
+ var _self = this;
256
+
257
+ $('.tag', _self.$container).each(function() {
258
+ var $tag = $(this);
259
+ var item = $tag.data('item');
260
+ var itemValue = _self.options.itemValue(item);
261
+ var itemText = _self.options.itemText(item);
262
+ var tagClass = _self.options.tagClass(item);
263
+
264
+ $tag.attr('class', null);
265
+ $tag.addClass('tag ' + _self.htmlEncode(tagClass));
266
+ $tag.contents()
267
+ .filter(function () {
268
+ return this.nodeType == 3;
269
+ })[0].nodeValue = _self.htmlEncode(itemText);
270
+
271
+ if (_self.isSelect) {
272
+ var option = $('option', _self.$element).filter(function () {
273
+ return $(this).data('item') === item;
274
+ });
275
+
276
+ option.attr('value', itemValue);
277
+ }
278
+ });
279
+ };
280
+
281
+ Tag.prototype.items = function() {
282
+ return this.itemsArray;
283
+ };
284
+
285
+ Tag.prototype.pushVal = function() {
286
+ var _self = this;
287
+ var val = $.map(_self.items(), function (item) {
288
+ return _self.options.itemValue(item).toString();
289
+ });
290
+
291
+ _self.$element.val(val, true);
292
+
293
+ if (_self.options.triggerChange) _self.$element.trigger('change');
294
+ };
295
+
296
+ Tag.prototype.build = function(options) {
297
+ var _self = this;
298
+
299
+ _self.options = $.extend({}, Tag.DEFAULTS, options);
300
+
301
+ if (_self.objectItems) _self.options.freeInput = false;
302
+
303
+ _self.makeOptionItemFunction(_self.options, 'itemValue');
304
+ _self.makeOptionItemFunction(_self.options, 'itemText');
305
+ _self.makeOptionFunction(_self.options, 'tagClass');
306
+
307
+ if (_self.$element.data('source') || _self.options.typeahead) {
308
+ var typeahead = _self.$element.data('source');
309
+
310
+ if (typeahead === undefined) {
311
+ typeahead = _self.options.typeahead || {};
312
+ } else {
313
+ typeahead = { source: typeahead };
314
+ }
315
+
316
+ _self.makeOptionFunction(typeahead, 'source');
317
+
318
+ _self.$input.typeahead($.extend({}, typeahead, {
319
+ source: function (query, process) {
320
+ function processItems(items) {
321
+ var texts = [];
322
+
323
+ for (var i = 0; i < items.length; i++) {
324
+ var text = _self.options.itemText(items[i]);
325
+ map[text] = items[i];
326
+ texts.push(text);
327
+ }
328
+ process(texts);
329
+ }
330
+
331
+ this.map = {};
332
+ var map = this.map;
333
+ var data = typeahead.source(query);
334
+
335
+ $.when(data).then(processItems);
336
+ },
337
+ updater: function (text) {
338
+ _self.add(this.map[text]);
339
+ return this.map[text];
340
+ },
341
+ matcher: function (text) {
342
+ return (text.toLowerCase().indexOf(this.query.trim().toLowerCase()) !== -1);
343
+ },
344
+ sorter: function (texts) {
345
+ return texts.sort();
346
+ },
347
+ highlighter: function (text) {
348
+ var i = text.indexOf('<small');
349
+ var old = '';
350
+
351
+ if (i > 0) {
352
+ old = text.substring(i, text.length);
353
+ text = text.substring(0, i - 1);
354
+ }
355
+
356
+ var regex = new RegExp('(' + this.query + ')', 'gi');
357
+ return text.replace(regex, '<strong>$1</strong>') + old;
358
+ }
359
+ }));
360
+ }
361
+
362
+ _self.$container.on('click', $.proxy(function(event) {
363
+ if (! _self.$element.attr('disabled')) _self.$input.removeAttr('disabled');
364
+
365
+ _self.$input.focus();
366
+ }, _self));
367
+
368
+ if (_self.options.addOnBlur && _self.options.freeInput) {
369
+ _self.$input.on('focusout', $.proxy(function(event) {
370
+ if ($('.typeahead', _self.$container).length === 0) {
371
+ _self.add(_self.$input.val());
372
+ _self.$input.val('');
373
+ }
374
+ }, _self));
375
+ }
376
+
377
+ _self.$container.on({
378
+ focusin: function() {
379
+ _self.$container.addClass(_self.options.focusClass);
380
+ },
381
+ focusout: function() {
382
+ _self.$container.removeClass(_self.options.focusClass);
383
+ },
384
+ });
385
+
386
+ _self.$container.on('keydown input', 'input', $.proxy(function(event) {
387
+ var $input = $(event.target);
388
+ var $inputWrapper = _self.findInputWrapper();
389
+
390
+ if (_self.$element.attr('disabled')) {
391
+ _self.$input.attr('disabled', 'disabled');
392
+ return;
393
+ }
394
+
395
+ switch (event.which) {
396
+ case 8:
397
+ if (_self.doGetCaretPosition($input[0]) === 0) {
398
+ var prev = $inputWrapper.prev();
399
+
400
+ if (prev.length) _self.remove(prev.data('item'));
401
+ }
402
+ break;
403
+ case 46:
404
+ if (_self.doGetCaretPosition($input[0]) === 0) {
405
+ var next = $inputWrapper.next();
406
+
407
+ if (next.length) _self.remove(next.data('item'));
408
+ }
409
+ break;
410
+ case 37:
411
+ var $prevTag = $inputWrapper.prev();
412
+
413
+ if ($input.val().length === 0 && $prevTag[0]) {
414
+ $prevTag.before($inputWrapper);
415
+ $input.focus();
416
+ }
417
+ break;
418
+ case 39:
419
+ var $nextTag = $inputWrapper.next();
420
+
421
+ if ($input.val().length === 0 && $nextTag[0]) {
422
+ $nextTag.after($inputWrapper);
423
+ $input.focus();
424
+ }
425
+ break;
426
+ default:
427
+ // ignore
428
+ }
429
+
430
+ var textLength = $input.val().length;
431
+ var wordSpace = Math.ceil(textLength / 5);
432
+ var size = textLength + wordSpace + 1;
433
+
434
+ $input.attr('size', Math.max(this.inputSize, $input.val().length));
435
+ }, _self));
436
+
437
+ _self.$container.on('keypress', 'input', $.proxy(function(event) {
438
+ var $input = $(event.target);
439
+
440
+ if (_self.$element.attr('disabled')) {
441
+ _self.$input.attr('disabled', 'disabled');
442
+ return;
443
+ }
444
+
445
+ var text = $input.val();
446
+ var maxLengthReached = _self.options.maxChars && text.length >= _self.options.maxChars;
447
+
448
+ if (_self.options.freeInput && (_self.keyCombinationInList(event, _self.options.confirmKeys) || maxLengthReached)) {
449
+ if (text.length !== 0) {
450
+ _self.add(maxLengthReached ? text.substr(0, _self.options.maxChars) : text);
451
+ $input.val('');
452
+ }
453
+
454
+ if (_self.options.cancelConfirmKeysOnEmpty === false) event.preventDefault();
455
+ }
456
+
457
+ var textLength = $input.val().length;
458
+ var wordSpace = Math.ceil(textLength / 5);
459
+ var size = textLength + wordSpace + 1;
460
+
461
+ $input.attr('size', Math.max(this.inputSize, $input.val().length));
462
+ }, _self));
463
+
464
+ _self.$container.on('click', '[data-role=remove]', $.proxy(function(event) {
465
+ if (_self.$element.attr('disabled')) return;
466
+
467
+ _self.remove($(event.target).closest('.tag').data('item'));
468
+ }, _self));
469
+
470
+ if (_self.options.itemValue === Tag.DEFAULTS.itemValue) {
471
+ if (_self.$element[0].tagName === 'INPUT') {
472
+ _self.add(_self.$element.val());
473
+ } else {
474
+ $('option', _self.$element).each(function() {
475
+ _self.add($(this).attr('value'), true);
476
+ });
477
+ }
478
+ }
479
+ };
480
+
481
+ Tag.prototype.destroy = function() {
482
+ var _self = this;
483
+
484
+ this.$container
485
+ .off('keypress', 'input')
486
+ .off('click', '[role=remove]')
487
+ .remove();
488
+
489
+ this.$element
490
+ .removeData('tagsinput')
491
+ .show();
492
+ };
493
+
494
+ Tag.prototype.focus = function() {
495
+ this.$input.focus();
496
+ };
497
+
498
+ Tag.prototype.input = function() {
499
+ return this.$input;
500
+ };
501
+
502
+ Tag.prototype.findInputWrapper = function() {
503
+ var elt = this.$input[0];
504
+ var container = this.$container[0];
505
+
506
+ while (elt && elt.parentNode !== container) {
507
+ elt = elt.parentNode;
508
+ }
509
+
510
+ return $(elt);
511
+ };
512
+
513
+ Tag.prototype.makeOptionItemFunction = function (options, key) {
514
+ if (typeof options[key] !== 'function') {
515
+ var propertyName = options[key];
516
+
517
+ options[key] = function(item) {
518
+ return item[propertyName];
519
+ };
520
+ }
521
+ };
522
+
523
+ Tag.prototype.makeOptionFunction = function (options, key) {
524
+ if (typeof options[key] !== 'function') {
525
+ var value = options[key];
526
+
527
+ options[key] = function() {
528
+ return value;
529
+ };
530
+ }
531
+ };
532
+
533
+ Tag.prototype.doGetCaretPosition = function (oField) {
534
+ var iCaretPos = 0;
535
+
536
+ if (document.selection) {
537
+ oField.focus ();
538
+
539
+ var oSel = document.selection.createRange();
540
+
541
+ oSel.moveStart('character', -oField.value.length);
542
+
543
+ iCaretPos = oSel.text.length;
544
+ } else if (oField.selectionStart || oField.selectionStart == '0') {
545
+ iCaretPos = oField.selectionStart;
546
+ }
547
+
548
+ return (iCaretPos);
549
+ };
550
+
551
+ Tag.prototype.keyCombinationInList = function (keyPressEvent, lookupList) {
552
+ var found = false;
553
+
554
+ $.each(lookupList, function (index, keyCombination) {
555
+ if (typeof (keyCombination) === 'number' && keyPressEvent.which === keyCombination) {
556
+ found = true;
557
+ return false;
558
+ }
559
+
560
+ if (keyPressEvent.which === keyCombination.which) {
561
+ var alt = !keyCombination.hasOwnProperty('altKey') || keyPressEvent.altKey === keyCombination.altKey;
562
+ var shift = !keyCombination.hasOwnProperty('shiftKey') || keyPressEvent.shiftKey === keyCombination.shiftKey;
563
+ var ctrl = !keyCombination.hasOwnProperty('ctrlKey') || keyPressEvent.ctrlKey === keyCombination.ctrlKey;
564
+
565
+ if (alt && shift && ctrl) {
566
+ found = true;
567
+ return false;
568
+ }
569
+ }
570
+ });
571
+
572
+ return found;
573
+ };
574
+
575
+ Tag.prototype.htmlEncode = function (value) {
576
+ if (value) {
577
+ return $('<div />').text(value).html();
578
+ } else {
579
+ return '';
580
+ }
581
+ };
582
+
583
+ // TAG PLUGIN DEFINITION
584
+ // =====================
585
+
586
+ function Plugin(arg1, arg2, arg3) {
587
+ var results = [];
588
+
589
+ this.each(function () {
590
+ var _self = $(this);
591
+ var tagsinput = _self.data('tagsinput');
592
+
593
+ if (!tagsinput) {
594
+ tagsinput = new Tag(this, arg1);
595
+
596
+ _self.data('tagsinput', tagsinput);
597
+
598
+ results.push(tagsinput);
599
+
600
+ if (this.tagName === 'SELECT') $('option', _self).attr('selected', 'selected');
601
+
602
+ _self.val(_self.val());
603
+ } else if (!arg1 && !arg2) {
604
+ results.push(tagsinput);
605
+ } else if (tagsinput[arg1] !== undefined) {
606
+ var retVal;
607
+
608
+ if (tagsinput[arg1].length === 3 && arg3 !== undefined){
609
+ retVal = tagsinput[arg1](arg2, null, arg3);
610
+ } else {
611
+ retVal = tagsinput[arg1](arg2);
612
+ }
613
+
614
+ if (retVal !== undefined) results.push(retVal);
615
+ }
616
+ });
617
+
618
+ if (typeof arg1 === 'string') {
619
+ return results.length > 1 ? results : results[0];
620
+ } else {
621
+ return results;
622
+ }
623
+ }
624
+
625
+ var old = $.fn.tag;
626
+
627
+ $.fn.tag = Plugin;
628
+ $.fn.tag.Constructor = Tag;
629
+
630
+ // TAG NO CONFLICT
631
+ // ===============
632
+
633
+ $.fn.tag.noConflict = function () {
634
+ $.fn.tag = old;
635
+ return this;
636
+ };
637
+
638
+ // TAG DATA-API
639
+ // ============
640
+
641
+ $(document).on('ready.bs.tag.data-api', function () {
642
+ $('[data-toggle="tag"]').each(function () {
643
+ var $this = $(this);
644
+ if ($this.data('tag')) return;
645
+ Plugin.call($this, $this.data());
646
+ });
647
+ });
648
+
649
+ }(jQuery);
@@ -0,0 +1,372 @@
1
+ (function (global, factory) {
2
+ 'use strict';
3
+
4
+ if (typeof define === 'function' && define.amd) {
5
+ define(function () {
6
+ return new (factory(global, global.document))();
7
+ });
8
+ } else if (typeof module !== 'undefined' && module.exports) {
9
+ module.exports = new (factory(global, global.document))();
10
+ } else {
11
+ global.Push = new (factory(global, global.document))();
12
+ }
13
+ })(typeof window !== 'undefined' ? window : this, function (w, d) {
14
+ var Push = function () {
15
+ var
16
+ self = this,
17
+ isUndefined = function (obj) { return obj === undefined; },
18
+ isString = function (obj) { return typeof obj === 'string'; },
19
+ isFunction = function (obj) { return obj && {}.toString.call(obj) === '[object Function]'; },
20
+ currentId = 0,
21
+ incompatibilityErrorMessage = 'PushError: push.js is incompatible with browser.',
22
+ notifications = {},
23
+ lastWorkerPath = null,
24
+
25
+ closeNotification = function (id) {
26
+ var errored = false;
27
+ var notification = notifications[id];
28
+
29
+ if (typeof notification !== 'undefined') {
30
+ if (notification.close) {
31
+ notification.close();
32
+ } else if (notification.cancel) {
33
+ notification.cancel();
34
+ } else if (w.external && w.external.msIsSiteMode) {
35
+ w.external.msSiteModeClearIconOverlay();
36
+ } else {
37
+ errored = true;
38
+ throw new Error('Unable to close notification: unknown interface');
39
+ }
40
+
41
+ if (!errored) return removeNotification(id);
42
+ }
43
+
44
+ return false;
45
+ },
46
+
47
+ addNotification = function (notification) {
48
+ var id = currentId;
49
+
50
+ notifications[id] = notification;
51
+ currentId++;
52
+
53
+ return id;
54
+ },
55
+
56
+ removeNotification = function (id) {
57
+ var dict = {};
58
+ var success = false;
59
+ var key;
60
+
61
+ for (key in notifications) {
62
+ if (notifications.hasOwnProperty(key)) {
63
+ if (key != id) {
64
+ dict[key] = notifications[key];
65
+ } else {
66
+ success = true;
67
+ }
68
+ }
69
+ }
70
+
71
+ notifications = dict;
72
+
73
+ return success;
74
+ },
75
+
76
+ prepareNotification = function (id, options) {
77
+ var wrapper;
78
+
79
+ wrapper = {
80
+ get: function () {
81
+ return notifications[id];
82
+ },
83
+ close: function () {
84
+ closeNotification(id);
85
+ }
86
+ };
87
+
88
+ if (options.timeout) {
89
+ setTimeout(function () {
90
+ wrapper.close();
91
+ }, options.timeout);
92
+ }
93
+
94
+ return wrapper;
95
+ },
96
+
97
+ createCallback = function (title, options, resolve) {
98
+ var notification;
99
+ var onClose;
100
+
101
+ options = options || {};
102
+
103
+ self.lastWorkerPath = options.serviceWorker || 'serviceWorker.js';
104
+
105
+ onClose = function (id) {
106
+ removeNotification(id);
107
+
108
+ if (isFunction(options.onClose)) {
109
+ options.onClose.call(this, notification);
110
+ }
111
+ };
112
+
113
+ if (w.Notification) {
114
+ try {
115
+ notification = new w.Notification(title, {
116
+ icon: (isString(options.icon) || isUndefined(options.icon)) ? options.icon : options.icon.x32,
117
+ body: options.body,
118
+ tag: options.tag,
119
+ requireInteraction: options.requireInteraction,
120
+ silent: options.silent
121
+ });
122
+ } catch (e) {
123
+ if (w.navigator) {
124
+ w.navigator.serviceWorker.register(self.lastWorkerPath);
125
+ w.navigator.serviceWorker.ready.then(function (registration) {
126
+ var localData = {
127
+ id: currentId,
128
+ link: options.link,
129
+ origin: document.location.href,
130
+ onClick: (isFunction(options.onClick)) ? options.onClick.toString() : '',
131
+ onClose: (isFunction(options.onClose)) ? options.onClose.toString() : ''
132
+ };
133
+
134
+ if (typeof options.data !== 'undefined' && options.data !== null) {
135
+ localData = Object.assign(localData, options.data);
136
+ }
137
+
138
+ registration.showNotification(title, {
139
+ icon: options.icon,
140
+ body: options.body,
141
+ vibrate: options.vibrate,
142
+ tag: options.tag,
143
+ data: localData,
144
+ requireInteraction: options.requireInteraction
145
+ }).then(function() {
146
+ var id;
147
+
148
+ registration.getNotifications().then(function(notifications) {
149
+ id = addNotification(notifications[notifications.length - 1]);
150
+
151
+ registration.active.postMessage('');
152
+ navigator.serviceWorker.addEventListener('message', function (event) {
153
+ var data = JSON.parse(event.data);
154
+
155
+ if (data.action === 'close' && Number.isInteger(data.id)) removeNotification(data.id);
156
+ });
157
+
158
+ resolve(prepareNotification(id, options));
159
+ });
160
+ });
161
+ });
162
+ }
163
+ }
164
+ } else if (w.webkitNotifications) {
165
+ notification = w.webkitNotifications.createNotification(
166
+ options.icon,
167
+ title,
168
+ options.body
169
+ );
170
+
171
+ notification.show();
172
+ } else if (navigator.mozNotification) {
173
+ notification = navigator.mozNotification.createNotification(
174
+ title,
175
+ options.body,
176
+ options.icon
177
+ );
178
+
179
+ notification.show();
180
+ } else if (w.external && w.external.msIsSiteMode()) {
181
+ w.external.msSiteModeClearIconOverlay();
182
+ w.external.msSiteModeSetIconOverlay(
183
+ ((isString(options.icon) || isUndefined(options.icon)) ? options.icon : options.icon.x16),
184
+ title
185
+ );
186
+ w.external.msSiteModeActivate();
187
+
188
+ notification = {};
189
+ } else {
190
+ throw new Error('Unable to create notification: unknown interface');
191
+ }
192
+
193
+ if (typeof(notification) !== 'undefined') {
194
+ var id = addNotification(notification);
195
+ var wrapper = prepareNotification(id, options);
196
+
197
+ if (isFunction(options.onShow)) notification.addEventListener('show', options.onShow);
198
+ if (isFunction(options.onError)) notification.addEventListener('error', options.onError);
199
+ if (isFunction(options.onClick)) notification.addEventListener('click', options.onClick);
200
+
201
+ notification.addEventListener('close', function() {
202
+ onClose(id);
203
+ });
204
+ notification.addEventListener('cancel', function() {
205
+ onClose(id);
206
+ });
207
+
208
+ resolve(wrapper);
209
+ }
210
+
211
+ resolve({});
212
+ },
213
+
214
+ Permission = {
215
+ DEFAULT: 'default',
216
+ GRANTED: 'granted',
217
+ DENIED: 'denied'
218
+ },
219
+
220
+ Permissions = [Permission.GRANTED, Permission.DEFAULT, Permission.DENIED];
221
+
222
+ self.Permission = Permission;
223
+
224
+ self.Permission.request = function (onGranted, onDenied) {
225
+ var existing = self.Permission.get();
226
+
227
+ if (!self.isSupported) {
228
+ throw new Error(incompatibilityErrorMessage);
229
+ }
230
+
231
+ callback = function (result) {
232
+ switch (result) {
233
+ case self.Permission.GRANTED:
234
+ if (onGranted) onGranted();
235
+ break;
236
+ case self.Permission.DENIED:
237
+ if (onDenied) onDenied();
238
+ break;
239
+ default:
240
+ // Nothing
241
+ }
242
+ };
243
+
244
+ if (existing !== self.Permission.DEFAULT) {
245
+ callback(existing);
246
+ } else if (w.Notification && w.Notification.requestPermission) {
247
+ Notification.requestPermission(callback);
248
+ } else if (w.webkitNotifications && w.webkitNotifications.checkPermission) {
249
+ w.webkitNotifications.requestPermission(callback);
250
+ } else {
251
+ throw new Error(incompatibilityErrorMessage);
252
+ }
253
+ };
254
+
255
+ self.Permission.has = function () {
256
+ return Permission.get() === Permission.GRANTED;
257
+ };
258
+
259
+ self.Permission.get = function () {
260
+ var permission;
261
+
262
+ if (!self.isSupported) {
263
+ throw new Error(incompatibilityErrorMessage);
264
+ }
265
+
266
+ if (w.Notification && w.Notification.permissionLevel) {
267
+ permission = w.Notification.permissionLevel;
268
+ } else if (w.webkitNotifications && w.webkitNotifications.checkPermission) {
269
+ permission = Permissions[w.webkitNotifications.checkPermission()];
270
+ } else if (w.Notification && w.Notification.permission) {
271
+ permission = w.Notification.permission;
272
+ } else if (navigator.mozNotification) {
273
+ permission = Permission.GRANTED;
274
+ } else if (w.external && w.external.msIsSiteMode() !== undefined) {
275
+ permission = w.external.msIsSiteMode() ? Permission.GRANTED : Permission.DEFAULT;
276
+ } else {
277
+ throw new Error(incompatibilityErrorMessage);
278
+ }
279
+
280
+ return permission;
281
+ };
282
+
283
+ self.isSupported = (function () {
284
+ var isSupported = false;
285
+
286
+ try {
287
+ isSupported = !!(w.Notification ||
288
+ w.webkitNotifications ||
289
+ navigator.mozNotification ||
290
+ (w.external && w.external.msIsSiteMode() !== undefined));
291
+ } catch (e) {
292
+ // Nothing
293
+ }
294
+
295
+ return isSupported;
296
+ })();
297
+
298
+ self.create = function (title, options) {
299
+ var promiseCallback;
300
+
301
+ if (!self.isSupported) {
302
+ throw new Error(incompatibilityErrorMessage);
303
+ }
304
+
305
+ if (!isString(title)) {
306
+ throw new Error('PushError: Title of notification must be a string');
307
+ }
308
+
309
+ if (!self.Permission.has()) {
310
+ promiseCallback = function(resolve, reject) {
311
+ self.Permission.request(function() {
312
+ try {
313
+ createCallback(title, options, resolve);
314
+ } catch (e) {
315
+ reject(e);
316
+ }
317
+ }, function() {
318
+ reject('Permission request declined');
319
+ });
320
+ };
321
+ } else {
322
+ promiseCallback = function(resolve, reject) {
323
+ try {
324
+ createCallback(title, options, resolve);
325
+ } catch (e) {
326
+ reject(e);
327
+ }
328
+ };
329
+ }
330
+
331
+ return new Promise(promiseCallback);
332
+ };
333
+
334
+ self.count = function () {
335
+ var count = 0;
336
+ var key;
337
+
338
+ for (key in notifications) {
339
+ count++;
340
+ }
341
+
342
+ return count;
343
+ },
344
+
345
+ self.__lastWorkerPath = function () {
346
+ return self.lastWorkerPath;
347
+ },
348
+
349
+ self.close = function (tag) {
350
+ var key;
351
+
352
+ for (key in notifications) {
353
+ notification = notifications[key];
354
+
355
+ if (notification.tag === tag) return closeNotification(key);
356
+ }
357
+ },
358
+
359
+ self.clear = function () {
360
+ var success = true;
361
+ var key;
362
+
363
+ for (key in notifications) {
364
+ success = success && closeNotification(key);
365
+ }
366
+
367
+ return success;
368
+ };
369
+ };
370
+
371
+ return Push;
372
+ });
@@ -46,6 +46,7 @@
46
46
  @import 'components/selectpicker';
47
47
  @import 'components/timepicker';
48
48
  @import 'components/typeahead';
49
+ @import 'components/tag';
49
50
  @import 'components/ad';
50
51
  @import 'components/label_and_badge';
51
52
  @import 'components/breadcrumb';
@@ -5,6 +5,7 @@
5
5
  // Selects
6
6
  // Checkboxes & Radios
7
7
  // Notes
8
+ // Tags
8
9
  // Labels
9
10
  // Addons
10
11
 
@@ -43,7 +44,8 @@ input { overflow: visible; }
43
44
  optgroup { font-weight: text-weight(semibold); }
44
45
  input,
45
46
  select,
46
- textarea {
47
+ textarea,
48
+ .form-tags {
47
49
  @include appearance(none);
48
50
  @include transition(all 0.3s ease-in-out);
49
51
  background: color(white);
@@ -59,7 +61,8 @@ textarea {
59
61
  }
60
62
  input:not([type='submit']),
61
63
  select,
62
- textarea {
64
+ textarea,
65
+ .form-tags {
63
66
  box-shadow: inset 0 2px 0 0 darkish-color(light-haze);
64
67
 
65
68
  &.dark {
@@ -80,11 +83,13 @@ textarea {
80
83
  color: color(gray);
81
84
  font-weight: text-weight(normal) !important;
82
85
  }
83
- &:focus {
86
+ &:focus,
87
+ &.focus {
84
88
  box-shadow: inset 0 2px 0 0 transparentize(color(blue), 0.5);
85
89
  border-color: color(blue);
86
90
  }
87
- &:focus:invalid {
91
+ &:focus:invalid,
92
+ &.focus:invalid {
88
93
  box-shadow: inset 0 2px 0 0 transparentize(color(red), 0.5);
89
94
  border-color: color(red);
90
95
  }
@@ -436,6 +441,24 @@ textarea {
436
441
  margin: -10px 0 10px;
437
442
  }
438
443
 
444
+ // Tags
445
+ // ==================================================
446
+ .form-tags {
447
+ white-space: normal;
448
+
449
+ input,
450
+ input:focus {
451
+ background: color(transparent);
452
+ border: 0;
453
+ box-shadow: none;
454
+ display: inline-block;
455
+ outline: none;
456
+ margin: 0;
457
+ padding: 0;
458
+ width: auto;
459
+ }
460
+ }
461
+
439
462
  // Labels
440
463
  // ==================================================
441
464
  .form-input,
@@ -0,0 +1,23 @@
1
+ // Table of Contents
2
+ // ==================================================
3
+ // Tag
4
+
5
+ // scss-lint:disable ImportantRule
6
+
7
+ // Tag
8
+ // ==================================================
9
+ .tag {
10
+ margin: 2px 2px 2px 0;
11
+ padding-right: 22px !important;
12
+
13
+ [data-role='remove'] {
14
+ cursor: pointer;
15
+ margin-left: 5px;
16
+
17
+ &::after {
18
+ content: '\39';
19
+ font-family: 'dripicons';
20
+ position: absolute;
21
+ }
22
+ }
23
+ }
@@ -10,11 +10,9 @@
10
10
  margin-top: 10px;
11
11
  z-index: 1060;
12
12
 
13
- > li > a b { color: color(blue); }
14
- }
15
- x {
16
- display: block;
17
- color: color(gray);
18
- font-style: italic;
19
- font-weight: normal;
13
+ > li > a b,
14
+ > li.active > a {
15
+ color: color(blue);
16
+ font-weight: text-weight(semibold);
17
+ }
20
18
  }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_frontend
3
3
  version: !ruby/object:Gem::Version
4
- version: 14.0.99
4
+ version: 14.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Juan Gomez
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-06-13 00:00:00.000000000 Z
11
+ date: 2017-06-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -238,6 +238,7 @@ files:
238
238
  - vendor/assets/javascripts/base/_switch.js
239
239
  - vendor/assets/javascripts/base/_tab.js
240
240
  - vendor/assets/javascripts/base/_table.js
241
+ - vendor/assets/javascripts/base/_tag.js
241
242
  - vendor/assets/javascripts/base/_timeago.js
242
243
  - vendor/assets/javascripts/base/_timepicker.js
243
244
  - vendor/assets/javascripts/base/_timezone.js
@@ -251,6 +252,7 @@ files:
251
252
  - vendor/assets/javascripts/extensions/_copy.js
252
253
  - vendor/assets/javascripts/extensions/_funnel.js
253
254
  - vendor/assets/javascripts/extensions/_map.js
255
+ - vendor/assets/javascripts/extensions/_push.js
254
256
  - vendor/assets/javascripts/extensions/_wysiwyg.js
255
257
  - vendor/assets/stylesheets/.DS_Store
256
258
  - vendor/assets/stylesheets/.keep
@@ -303,6 +305,7 @@ files:
303
305
  - vendor/assets/stylesheets/components/_sidebar.scss
304
306
  - vendor/assets/stylesheets/components/_spinner.scss
305
307
  - vendor/assets/stylesheets/components/_switch.scss
308
+ - vendor/assets/stylesheets/components/_tag.scss
306
309
  - vendor/assets/stylesheets/components/_timepicker.scss
307
310
  - vendor/assets/stylesheets/components/_tooltip.scss
308
311
  - vendor/assets/stylesheets/components/_transition.scss