unforassets 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +3 -0
  3. data/LICENSE.md +21 -0
  4. data/README.md +41 -0
  5. data/lib/unforassets.rb +8 -0
  6. data/lib/unforassets/engine.rb +4 -0
  7. data/lib/unforassets/version.rb +3 -0
  8. data/vendor/assets/javascripts/big.js +1 -0
  9. data/vendor/assets/javascripts/fancybox.js +12 -0
  10. data/vendor/assets/javascripts/jquery.blockui.js +620 -0
  11. data/vendor/assets/javascripts/tooltipster-plugin-scrollable-tip.js +187 -0
  12. data/vendor/assets/javascripts/tooltipster-plugin-svg.js +171 -0
  13. data/vendor/assets/javascripts/tooltipster.bundle.js +4260 -0
  14. data/vendor/assets/javascripts/vex.combined.js +1621 -0
  15. data/vendor/assets/stylesheets/fancybox.css +1 -0
  16. data/vendor/assets/stylesheets/tooltipster-sidetip-borderless.min.css +1 -0
  17. data/vendor/assets/stylesheets/tooltipster-sidetip-light.min.css +1 -0
  18. data/vendor/assets/stylesheets/tooltipster-sidetip-noir.min.css +1 -0
  19. data/vendor/assets/stylesheets/tooltipster-sidetip-punk.min.css +1 -0
  20. data/vendor/assets/stylesheets/tooltipster-sidetip-shadow.min.css +1 -0
  21. data/vendor/assets/stylesheets/tooltipster.bundle.css +388 -0
  22. data/vendor/assets/stylesheets/vex-theme-bottom-right-corner.css +437 -0
  23. data/vendor/assets/stylesheets/vex-theme-default.css +368 -0
  24. data/vendor/assets/stylesheets/vex-theme-flat-attack.css +325 -0
  25. data/vendor/assets/stylesheets/vex-theme-os.css +373 -0
  26. data/vendor/assets/stylesheets/vex-theme-plain.css +173 -0
  27. data/vendor/assets/stylesheets/vex-theme-top.css +432 -0
  28. data/vendor/assets/stylesheets/vex-theme-wireframe.css +174 -0
  29. data/vendor/assets/stylesheets/vex.css +231 -0
  30. metadata +100 -0
@@ -0,0 +1,1621 @@
1
+ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.vex = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
2
+ /*
3
+ * classList.js: Cross-browser full element.classList implementation.
4
+ * 2014-07-23
5
+ *
6
+ * By Eli Grey, http://eligrey.com
7
+ * Public Domain.
8
+ * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
9
+ */
10
+
11
+ /*global self, document, DOMException */
12
+
13
+ /*! @source http://purl.eligrey.com/github/classList.js/blob/master/classList.js*/
14
+
15
+ /* Copied from MDN:
16
+ * https://developer.mozilla.org/en-US/docs/Web/API/Element/classList
17
+ */
18
+
19
+ if ("document" in window.self) {
20
+
21
+ // Full polyfill for browsers with no classList support
22
+ // Including IE < Edge missing SVGElement.classList
23
+ if (!("classList" in document.createElement("_"))
24
+ || document.createElementNS && !("classList" in document.createElementNS("http://www.w3.org/2000/svg","g"))) {
25
+
26
+ (function (view) {
27
+
28
+ "use strict";
29
+
30
+ if (!('Element' in view)) return;
31
+
32
+ var
33
+ classListProp = "classList"
34
+ , protoProp = "prototype"
35
+ , elemCtrProto = view.Element[protoProp]
36
+ , objCtr = Object
37
+ , strTrim = String[protoProp].trim || function () {
38
+ return this.replace(/^\s+|\s+$/g, "");
39
+ }
40
+ , arrIndexOf = Array[protoProp].indexOf || function (item) {
41
+ var
42
+ i = 0
43
+ , len = this.length
44
+ ;
45
+ for (; i < len; i++) {
46
+ if (i in this && this[i] === item) {
47
+ return i;
48
+ }
49
+ }
50
+ return -1;
51
+ }
52
+ // Vendors: please allow content code to instantiate DOMExceptions
53
+ , DOMEx = function (type, message) {
54
+ this.name = type;
55
+ this.code = DOMException[type];
56
+ this.message = message;
57
+ }
58
+ , checkTokenAndGetIndex = function (classList, token) {
59
+ if (token === "") {
60
+ throw new DOMEx(
61
+ "SYNTAX_ERR"
62
+ , "An invalid or illegal string was specified"
63
+ );
64
+ }
65
+ if (/\s/.test(token)) {
66
+ throw new DOMEx(
67
+ "INVALID_CHARACTER_ERR"
68
+ , "String contains an invalid character"
69
+ );
70
+ }
71
+ return arrIndexOf.call(classList, token);
72
+ }
73
+ , ClassList = function (elem) {
74
+ var
75
+ trimmedClasses = strTrim.call(elem.getAttribute("class") || "")
76
+ , classes = trimmedClasses ? trimmedClasses.split(/\s+/) : []
77
+ , i = 0
78
+ , len = classes.length
79
+ ;
80
+ for (; i < len; i++) {
81
+ this.push(classes[i]);
82
+ }
83
+ this._updateClassName = function () {
84
+ elem.setAttribute("class", this.toString());
85
+ };
86
+ }
87
+ , classListProto = ClassList[protoProp] = []
88
+ , classListGetter = function () {
89
+ return new ClassList(this);
90
+ }
91
+ ;
92
+ // Most DOMException implementations don't allow calling DOMException's toString()
93
+ // on non-DOMExceptions. Error's toString() is sufficient here.
94
+ DOMEx[protoProp] = Error[protoProp];
95
+ classListProto.item = function (i) {
96
+ return this[i] || null;
97
+ };
98
+ classListProto.contains = function (token) {
99
+ token += "";
100
+ return checkTokenAndGetIndex(this, token) !== -1;
101
+ };
102
+ classListProto.add = function () {
103
+ var
104
+ tokens = arguments
105
+ , i = 0
106
+ , l = tokens.length
107
+ , token
108
+ , updated = false
109
+ ;
110
+ do {
111
+ token = tokens[i] + "";
112
+ if (checkTokenAndGetIndex(this, token) === -1) {
113
+ this.push(token);
114
+ updated = true;
115
+ }
116
+ }
117
+ while (++i < l);
118
+
119
+ if (updated) {
120
+ this._updateClassName();
121
+ }
122
+ };
123
+ classListProto.remove = function () {
124
+ var
125
+ tokens = arguments
126
+ , i = 0
127
+ , l = tokens.length
128
+ , token
129
+ , updated = false
130
+ , index
131
+ ;
132
+ do {
133
+ token = tokens[i] + "";
134
+ index = checkTokenAndGetIndex(this, token);
135
+ while (index !== -1) {
136
+ this.splice(index, 1);
137
+ updated = true;
138
+ index = checkTokenAndGetIndex(this, token);
139
+ }
140
+ }
141
+ while (++i < l);
142
+
143
+ if (updated) {
144
+ this._updateClassName();
145
+ }
146
+ };
147
+ classListProto.toggle = function (token, force) {
148
+ token += "";
149
+
150
+ var
151
+ result = this.contains(token)
152
+ , method = result ?
153
+ force !== true && "remove"
154
+ :
155
+ force !== false && "add"
156
+ ;
157
+
158
+ if (method) {
159
+ this[method](token);
160
+ }
161
+
162
+ if (force === true || force === false) {
163
+ return force;
164
+ } else {
165
+ return !result;
166
+ }
167
+ };
168
+ classListProto.toString = function () {
169
+ return this.join(" ");
170
+ };
171
+
172
+ if (objCtr.defineProperty) {
173
+ var classListPropDesc = {
174
+ get: classListGetter
175
+ , enumerable: true
176
+ , configurable: true
177
+ };
178
+ try {
179
+ objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
180
+ } catch (ex) { // IE 8 doesn't support enumerable:true
181
+ if (ex.number === -0x7FF5EC54) {
182
+ classListPropDesc.enumerable = false;
183
+ objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
184
+ }
185
+ }
186
+ } else if (objCtr[protoProp].__defineGetter__) {
187
+ elemCtrProto.__defineGetter__(classListProp, classListGetter);
188
+ }
189
+
190
+ }(window.self));
191
+
192
+ } else {
193
+ // There is full or partial native classList support, so just check if we need
194
+ // to normalize the add/remove and toggle APIs.
195
+
196
+ (function () {
197
+ "use strict";
198
+
199
+ var testElement = document.createElement("_");
200
+
201
+ testElement.classList.add("c1", "c2");
202
+
203
+ // Polyfill for IE 10/11 and Firefox <26, where classList.add and
204
+ // classList.remove exist but support only one argument at a time.
205
+ if (!testElement.classList.contains("c2")) {
206
+ var createMethod = function(method) {
207
+ var original = DOMTokenList.prototype[method];
208
+
209
+ DOMTokenList.prototype[method] = function(token) {
210
+ var i, len = arguments.length;
211
+
212
+ for (i = 0; i < len; i++) {
213
+ token = arguments[i];
214
+ original.call(this, token);
215
+ }
216
+ };
217
+ };
218
+ createMethod('add');
219
+ createMethod('remove');
220
+ }
221
+
222
+ testElement.classList.toggle("c3", false);
223
+
224
+ // Polyfill for IE 10 and Firefox <24, where classList.toggle does not
225
+ // support the second argument.
226
+ if (testElement.classList.contains("c3")) {
227
+ var _toggle = DOMTokenList.prototype.toggle;
228
+
229
+ DOMTokenList.prototype.toggle = function(token, force) {
230
+ if (1 in arguments && !this.contains(token) === !force) {
231
+ return force;
232
+ } else {
233
+ return _toggle.call(this, token);
234
+ }
235
+ };
236
+
237
+ }
238
+
239
+ testElement = null;
240
+ }());
241
+ }
242
+ }
243
+
244
+ },{}],2:[function(require,module,exports){
245
+
246
+ /**
247
+ * Expose `parse`.
248
+ */
249
+
250
+ module.exports = parse;
251
+
252
+ /**
253
+ * Tests for browser support.
254
+ */
255
+
256
+ var innerHTMLBug = false;
257
+ var bugTestDiv;
258
+ if (typeof document !== 'undefined') {
259
+ bugTestDiv = document.createElement('div');
260
+ // Setup
261
+ bugTestDiv.innerHTML = ' <link/><table></table><a href="/a">a</a><input type="checkbox"/>';
262
+ // Make sure that link elements get serialized correctly by innerHTML
263
+ // This requires a wrapper element in IE
264
+ innerHTMLBug = !bugTestDiv.getElementsByTagName('link').length;
265
+ bugTestDiv = undefined;
266
+ }
267
+
268
+ /**
269
+ * Wrap map from jquery.
270
+ */
271
+
272
+ var map = {
273
+ legend: [1, '<fieldset>', '</fieldset>'],
274
+ tr: [2, '<table><tbody>', '</tbody></table>'],
275
+ col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
276
+ // for script/link/style tags to work in IE6-8, you have to wrap
277
+ // in a div with a non-whitespace character in front, ha!
278
+ _default: innerHTMLBug ? [1, 'X<div>', '</div>'] : [0, '', '']
279
+ };
280
+
281
+ map.td =
282
+ map.th = [3, '<table><tbody><tr>', '</tr></tbody></table>'];
283
+
284
+ map.option =
285
+ map.optgroup = [1, '<select multiple="multiple">', '</select>'];
286
+
287
+ map.thead =
288
+ map.tbody =
289
+ map.colgroup =
290
+ map.caption =
291
+ map.tfoot = [1, '<table>', '</table>'];
292
+
293
+ map.polyline =
294
+ map.ellipse =
295
+ map.polygon =
296
+ map.circle =
297
+ map.text =
298
+ map.line =
299
+ map.path =
300
+ map.rect =
301
+ map.g = [1, '<svg xmlns="http://www.w3.org/2000/svg" version="1.1">','</svg>'];
302
+
303
+ /**
304
+ * Parse `html` and return a DOM Node instance, which could be a TextNode,
305
+ * HTML DOM Node of some kind (<div> for example), or a DocumentFragment
306
+ * instance, depending on the contents of the `html` string.
307
+ *
308
+ * @param {String} html - HTML string to "domify"
309
+ * @param {Document} doc - The `document` instance to create the Node for
310
+ * @return {DOMNode} the TextNode, DOM Node, or DocumentFragment instance
311
+ * @api private
312
+ */
313
+
314
+ function parse(html, doc) {
315
+ if ('string' != typeof html) throw new TypeError('String expected');
316
+
317
+ // default to the global `document` object
318
+ if (!doc) doc = document;
319
+
320
+ // tag name
321
+ var m = /<([\w:]+)/.exec(html);
322
+ if (!m) return doc.createTextNode(html);
323
+
324
+ html = html.replace(/^\s+|\s+$/g, ''); // Remove leading/trailing whitespace
325
+
326
+ var tag = m[1];
327
+
328
+ // body support
329
+ if (tag == 'body') {
330
+ var el = doc.createElement('html');
331
+ el.innerHTML = html;
332
+ return el.removeChild(el.lastChild);
333
+ }
334
+
335
+ // wrap map
336
+ var wrap = map[tag] || map._default;
337
+ var depth = wrap[0];
338
+ var prefix = wrap[1];
339
+ var suffix = wrap[2];
340
+ var el = doc.createElement('div');
341
+ el.innerHTML = prefix + html + suffix;
342
+ while (depth--) el = el.lastChild;
343
+
344
+ // one element
345
+ if (el.firstChild == el.lastChild) {
346
+ return el.removeChild(el.firstChild);
347
+ }
348
+
349
+ // several elements
350
+ var fragment = doc.createDocumentFragment();
351
+ while (el.firstChild) {
352
+ fragment.appendChild(el.removeChild(el.firstChild));
353
+ }
354
+
355
+ return fragment;
356
+ }
357
+
358
+ },{}],3:[function(require,module,exports){
359
+ /**
360
+ * Code refactored from Mozilla Developer Network:
361
+ * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
362
+ */
363
+
364
+ 'use strict';
365
+
366
+ function assign(target, firstSource) {
367
+ if (target === undefined || target === null) {
368
+ throw new TypeError('Cannot convert first argument to object');
369
+ }
370
+
371
+ var to = Object(target);
372
+ for (var i = 1; i < arguments.length; i++) {
373
+ var nextSource = arguments[i];
374
+ if (nextSource === undefined || nextSource === null) {
375
+ continue;
376
+ }
377
+
378
+ var keysArray = Object.keys(Object(nextSource));
379
+ for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {
380
+ var nextKey = keysArray[nextIndex];
381
+ var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
382
+ if (desc !== undefined && desc.enumerable) {
383
+ to[nextKey] = nextSource[nextKey];
384
+ }
385
+ }
386
+ }
387
+ return to;
388
+ }
389
+
390
+ function polyfill() {
391
+ if (!Object.assign) {
392
+ Object.defineProperty(Object, 'assign', {
393
+ enumerable: false,
394
+ configurable: true,
395
+ writable: true,
396
+ value: assign
397
+ });
398
+ }
399
+ }
400
+
401
+ module.exports = {
402
+ assign: assign,
403
+ polyfill: polyfill
404
+ };
405
+
406
+ },{}],4:[function(require,module,exports){
407
+ // get successful control from form and assemble into object
408
+ // http://www.w3.org/TR/html401/interact/forms.html#h-17.13.2
409
+
410
+ // types which indicate a submit action and are not successful controls
411
+ // these will be ignored
412
+ var k_r_submitter = /^(?:submit|button|image|reset|file)$/i;
413
+
414
+ // node names which could be successful controls
415
+ var k_r_success_contrls = /^(?:input|select|textarea|keygen)/i;
416
+
417
+ // Matches bracket notation.
418
+ var brackets = /(\[[^\[\]]*\])/g;
419
+
420
+ // serializes form fields
421
+ // @param form MUST be an HTMLForm element
422
+ // @param options is an optional argument to configure the serialization. Default output
423
+ // with no options specified is a url encoded string
424
+ // - hash: [true | false] Configure the output type. If true, the output will
425
+ // be a js object.
426
+ // - serializer: [function] Optional serializer function to override the default one.
427
+ // The function takes 3 arguments (result, key, value) and should return new result
428
+ // hash and url encoded str serializers are provided with this module
429
+ // - disabled: [true | false]. If true serialize disabled fields.
430
+ // - empty: [true | false]. If true serialize empty fields
431
+ function serialize(form, options) {
432
+ if (typeof options != 'object') {
433
+ options = { hash: !!options };
434
+ }
435
+ else if (options.hash === undefined) {
436
+ options.hash = true;
437
+ }
438
+
439
+ var result = (options.hash) ? {} : '';
440
+ var serializer = options.serializer || ((options.hash) ? hash_serializer : str_serialize);
441
+
442
+ var elements = form && form.elements ? form.elements : [];
443
+
444
+ //Object store each radio and set if it's empty or not
445
+ var radio_store = Object.create(null);
446
+
447
+ for (var i=0 ; i<elements.length ; ++i) {
448
+ var element = elements[i];
449
+
450
+ // ingore disabled fields
451
+ if ((!options.disabled && element.disabled) || !element.name) {
452
+ continue;
453
+ }
454
+ // ignore anyhting that is not considered a success field
455
+ if (!k_r_success_contrls.test(element.nodeName) ||
456
+ k_r_submitter.test(element.type)) {
457
+ continue;
458
+ }
459
+
460
+ var key = element.name;
461
+ var val = element.value;
462
+
463
+ // we can't just use element.value for checkboxes cause some browsers lie to us
464
+ // they say "on" for value when the box isn't checked
465
+ if ((element.type === 'checkbox' || element.type === 'radio') && !element.checked) {
466
+ val = undefined;
467
+ }
468
+
469
+ // If we want empty elements
470
+ if (options.empty) {
471
+ // for checkbox
472
+ if (element.type === 'checkbox' && !element.checked) {
473
+ val = '';
474
+ }
475
+
476
+ // for radio
477
+ if (element.type === 'radio') {
478
+ if (!radio_store[element.name] && !element.checked) {
479
+ radio_store[element.name] = false;
480
+ }
481
+ else if (element.checked) {
482
+ radio_store[element.name] = true;
483
+ }
484
+ }
485
+
486
+ // if options empty is true, continue only if its radio
487
+ if (!val && element.type == 'radio') {
488
+ continue;
489
+ }
490
+ }
491
+ else {
492
+ // value-less fields are ignored unless options.empty is true
493
+ if (!val) {
494
+ continue;
495
+ }
496
+ }
497
+
498
+ // multi select boxes
499
+ if (element.type === 'select-multiple') {
500
+ val = [];
501
+
502
+ var selectOptions = element.options;
503
+ var isSelectedOptions = false;
504
+ for (var j=0 ; j<selectOptions.length ; ++j) {
505
+ var option = selectOptions[j];
506
+ var allowedEmpty = options.empty && !option.value;
507
+ var hasValue = (option.value || allowedEmpty);
508
+ if (option.selected && hasValue) {
509
+ isSelectedOptions = true;
510
+
511
+ // If using a hash serializer be sure to add the
512
+ // correct notation for an array in the multi-select
513
+ // context. Here the name attribute on the select element
514
+ // might be missing the trailing bracket pair. Both names
515
+ // "foo" and "foo[]" should be arrays.
516
+ if (options.hash && key.slice(key.length - 2) !== '[]') {
517
+ result = serializer(result, key + '[]', option.value);
518
+ }
519
+ else {
520
+ result = serializer(result, key, option.value);
521
+ }
522
+ }
523
+ }
524
+
525
+ // Serialize if no selected options and options.empty is true
526
+ if (!isSelectedOptions && options.empty) {
527
+ result = serializer(result, key, '');
528
+ }
529
+
530
+ continue;
531
+ }
532
+
533
+ result = serializer(result, key, val);
534
+ }
535
+
536
+ // Check for all empty radio buttons and serialize them with key=""
537
+ if (options.empty) {
538
+ for (var key in radio_store) {
539
+ if (!radio_store[key]) {
540
+ result = serializer(result, key, '');
541
+ }
542
+ }
543
+ }
544
+
545
+ return result;
546
+ }
547
+
548
+ function parse_keys(string) {
549
+ var keys = [];
550
+ var prefix = /^([^\[\]]*)/;
551
+ var children = new RegExp(brackets);
552
+ var match = prefix.exec(string);
553
+
554
+ if (match[1]) {
555
+ keys.push(match[1]);
556
+ }
557
+
558
+ while ((match = children.exec(string)) !== null) {
559
+ keys.push(match[1]);
560
+ }
561
+
562
+ return keys;
563
+ }
564
+
565
+ function hash_assign(result, keys, value) {
566
+ if (keys.length === 0) {
567
+ result = value;
568
+ return result;
569
+ }
570
+
571
+ var key = keys.shift();
572
+ var between = key.match(/^\[(.+?)\]$/);
573
+
574
+ if (key === '[]') {
575
+ result = result || [];
576
+
577
+ if (Array.isArray(result)) {
578
+ result.push(hash_assign(null, keys, value));
579
+ }
580
+ else {
581
+ // This might be the result of bad name attributes like "[][foo]",
582
+ // in this case the original `result` object will already be
583
+ // assigned to an object literal. Rather than coerce the object to
584
+ // an array, or cause an exception the attribute "_values" is
585
+ // assigned as an array.
586
+ result._values = result._values || [];
587
+ result._values.push(hash_assign(null, keys, value));
588
+ }
589
+
590
+ return result;
591
+ }
592
+
593
+ // Key is an attribute name and can be assigned directly.
594
+ if (!between) {
595
+ result[key] = hash_assign(result[key], keys, value);
596
+ }
597
+ else {
598
+ var string = between[1];
599
+ // +var converts the variable into a number
600
+ // better than parseInt because it doesn't truncate away trailing
601
+ // letters and actually fails if whole thing is not a number
602
+ var index = +string;
603
+
604
+ // If the characters between the brackets is not a number it is an
605
+ // attribute name and can be assigned directly.
606
+ if (isNaN(index)) {
607
+ result = result || {};
608
+ result[string] = hash_assign(result[string], keys, value);
609
+ }
610
+ else {
611
+ result = result || [];
612
+ result[index] = hash_assign(result[index], keys, value);
613
+ }
614
+ }
615
+
616
+ return result;
617
+ }
618
+
619
+ // Object/hash encoding serializer.
620
+ function hash_serializer(result, key, value) {
621
+ var matches = key.match(brackets);
622
+
623
+ // Has brackets? Use the recursive assignment function to walk the keys,
624
+ // construct any missing objects in the result tree and make the assignment
625
+ // at the end of the chain.
626
+ if (matches) {
627
+ var keys = parse_keys(key);
628
+ hash_assign(result, keys, value);
629
+ }
630
+ else {
631
+ // Non bracket notation can make assignments directly.
632
+ var existing = result[key];
633
+
634
+ // If the value has been assigned already (for instance when a radio and
635
+ // a checkbox have the same name attribute) convert the previous value
636
+ // into an array before pushing into it.
637
+ //
638
+ // NOTE: If this requirement were removed all hash creation and
639
+ // assignment could go through `hash_assign`.
640
+ if (existing) {
641
+ if (!Array.isArray(existing)) {
642
+ result[key] = [ existing ];
643
+ }
644
+
645
+ result[key].push(value);
646
+ }
647
+ else {
648
+ result[key] = value;
649
+ }
650
+ }
651
+
652
+ return result;
653
+ }
654
+
655
+ // urlform encoding serializer
656
+ function str_serialize(result, key, value) {
657
+ // encode newlines as \r\n cause the html spec says so
658
+ value = value.replace(/(\r)?\n/g, '\r\n');
659
+ value = encodeURIComponent(value);
660
+
661
+ // spaces should be '+' rather than '%20'.
662
+ value = value.replace(/%20/g, '+');
663
+ return result + (result ? '&' : '') + encodeURIComponent(key) + '=' + value;
664
+ }
665
+
666
+ module.exports = serialize;
667
+
668
+ },{}],5:[function(require,module,exports){
669
+ (function (global){
670
+ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.vexDialog = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
671
+
672
+ /**
673
+ * Expose `parse`.
674
+ */
675
+
676
+ module.exports = parse;
677
+
678
+ /**
679
+ * Tests for browser support.
680
+ */
681
+
682
+ var innerHTMLBug = false;
683
+ var bugTestDiv;
684
+ if (typeof document !== 'undefined') {
685
+ bugTestDiv = document.createElement('div');
686
+ // Setup
687
+ bugTestDiv.innerHTML = ' <link/><table></table><a href="/a">a</a><input type="checkbox"/>';
688
+ // Make sure that link elements get serialized correctly by innerHTML
689
+ // This requires a wrapper element in IE
690
+ innerHTMLBug = !bugTestDiv.getElementsByTagName('link').length;
691
+ bugTestDiv = undefined;
692
+ }
693
+
694
+ /**
695
+ * Wrap map from jquery.
696
+ */
697
+
698
+ var map = {
699
+ legend: [1, '<fieldset>', '</fieldset>'],
700
+ tr: [2, '<table><tbody>', '</tbody></table>'],
701
+ col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
702
+ // for script/link/style tags to work in IE6-8, you have to wrap
703
+ // in a div with a non-whitespace character in front, ha!
704
+ _default: innerHTMLBug ? [1, 'X<div>', '</div>'] : [0, '', '']
705
+ };
706
+
707
+ map.td =
708
+ map.th = [3, '<table><tbody><tr>', '</tr></tbody></table>'];
709
+
710
+ map.option =
711
+ map.optgroup = [1, '<select multiple="multiple">', '</select>'];
712
+
713
+ map.thead =
714
+ map.tbody =
715
+ map.colgroup =
716
+ map.caption =
717
+ map.tfoot = [1, '<table>', '</table>'];
718
+
719
+ map.polyline =
720
+ map.ellipse =
721
+ map.polygon =
722
+ map.circle =
723
+ map.text =
724
+ map.line =
725
+ map.path =
726
+ map.rect =
727
+ map.g = [1, '<svg xmlns="http://www.w3.org/2000/svg" version="1.1">','</svg>'];
728
+
729
+ /**
730
+ * Parse `html` and return a DOM Node instance, which could be a TextNode,
731
+ * HTML DOM Node of some kind (<div> for example), or a DocumentFragment
732
+ * instance, depending on the contents of the `html` string.
733
+ *
734
+ * @param {String} html - HTML string to "domify"
735
+ * @param {Document} doc - The `document` instance to create the Node for
736
+ * @return {DOMNode} the TextNode, DOM Node, or DocumentFragment instance
737
+ * @api private
738
+ */
739
+
740
+ function parse(html, doc) {
741
+ if ('string' != typeof html) throw new TypeError('String expected');
742
+
743
+ // default to the global `document` object
744
+ if (!doc) doc = document;
745
+
746
+ // tag name
747
+ var m = /<([\w:]+)/.exec(html);
748
+ if (!m) return doc.createTextNode(html);
749
+
750
+ html = html.replace(/^\s+|\s+$/g, ''); // Remove leading/trailing whitespace
751
+
752
+ var tag = m[1];
753
+
754
+ // body support
755
+ if (tag == 'body') {
756
+ var el = doc.createElement('html');
757
+ el.innerHTML = html;
758
+ return el.removeChild(el.lastChild);
759
+ }
760
+
761
+ // wrap map
762
+ var wrap = map[tag] || map._default;
763
+ var depth = wrap[0];
764
+ var prefix = wrap[1];
765
+ var suffix = wrap[2];
766
+ var el = doc.createElement('div');
767
+ el.innerHTML = prefix + html + suffix;
768
+ while (depth--) el = el.lastChild;
769
+
770
+ // one element
771
+ if (el.firstChild == el.lastChild) {
772
+ return el.removeChild(el.firstChild);
773
+ }
774
+
775
+ // several elements
776
+ var fragment = doc.createDocumentFragment();
777
+ while (el.firstChild) {
778
+ fragment.appendChild(el.removeChild(el.firstChild));
779
+ }
780
+
781
+ return fragment;
782
+ }
783
+
784
+ },{}],2:[function(require,module,exports){
785
+ // get successful control from form and assemble into object
786
+ // http://www.w3.org/TR/html401/interact/forms.html#h-17.13.2
787
+
788
+ // types which indicate a submit action and are not successful controls
789
+ // these will be ignored
790
+ var k_r_submitter = /^(?:submit|button|image|reset|file)$/i;
791
+
792
+ // node names which could be successful controls
793
+ var k_r_success_contrls = /^(?:input|select|textarea|keygen)/i;
794
+
795
+ // Matches bracket notation.
796
+ var brackets = /(\[[^\[\]]*\])/g;
797
+
798
+ // serializes form fields
799
+ // @param form MUST be an HTMLForm element
800
+ // @param options is an optional argument to configure the serialization. Default output
801
+ // with no options specified is a url encoded string
802
+ // - hash: [true | false] Configure the output type. If true, the output will
803
+ // be a js object.
804
+ // - serializer: [function] Optional serializer function to override the default one.
805
+ // The function takes 3 arguments (result, key, value) and should return new result
806
+ // hash and url encoded str serializers are provided with this module
807
+ // - disabled: [true | false]. If true serialize disabled fields.
808
+ // - empty: [true | false]. If true serialize empty fields
809
+ function serialize(form, options) {
810
+ if (typeof options != 'object') {
811
+ options = { hash: !!options };
812
+ }
813
+ else if (options.hash === undefined) {
814
+ options.hash = true;
815
+ }
816
+
817
+ var result = (options.hash) ? {} : '';
818
+ var serializer = options.serializer || ((options.hash) ? hash_serializer : str_serialize);
819
+
820
+ var elements = form && form.elements ? form.elements : [];
821
+
822
+ //Object store each radio and set if it's empty or not
823
+ var radio_store = Object.create(null);
824
+
825
+ for (var i=0 ; i<elements.length ; ++i) {
826
+ var element = elements[i];
827
+
828
+ // ingore disabled fields
829
+ if ((!options.disabled && element.disabled) || !element.name) {
830
+ continue;
831
+ }
832
+ // ignore anyhting that is not considered a success field
833
+ if (!k_r_success_contrls.test(element.nodeName) ||
834
+ k_r_submitter.test(element.type)) {
835
+ continue;
836
+ }
837
+
838
+ var key = element.name;
839
+ var val = element.value;
840
+
841
+ // we can't just use element.value for checkboxes cause some browsers lie to us
842
+ // they say "on" for value when the box isn't checked
843
+ if ((element.type === 'checkbox' || element.type === 'radio') && !element.checked) {
844
+ val = undefined;
845
+ }
846
+
847
+ // If we want empty elements
848
+ if (options.empty) {
849
+ // for checkbox
850
+ if (element.type === 'checkbox' && !element.checked) {
851
+ val = '';
852
+ }
853
+
854
+ // for radio
855
+ if (element.type === 'radio') {
856
+ if (!radio_store[element.name] && !element.checked) {
857
+ radio_store[element.name] = false;
858
+ }
859
+ else if (element.checked) {
860
+ radio_store[element.name] = true;
861
+ }
862
+ }
863
+
864
+ // if options empty is true, continue only if its radio
865
+ if (!val && element.type == 'radio') {
866
+ continue;
867
+ }
868
+ }
869
+ else {
870
+ // value-less fields are ignored unless options.empty is true
871
+ if (!val) {
872
+ continue;
873
+ }
874
+ }
875
+
876
+ // multi select boxes
877
+ if (element.type === 'select-multiple') {
878
+ val = [];
879
+
880
+ var selectOptions = element.options;
881
+ var isSelectedOptions = false;
882
+ for (var j=0 ; j<selectOptions.length ; ++j) {
883
+ var option = selectOptions[j];
884
+ var allowedEmpty = options.empty && !option.value;
885
+ var hasValue = (option.value || allowedEmpty);
886
+ if (option.selected && hasValue) {
887
+ isSelectedOptions = true;
888
+
889
+ // If using a hash serializer be sure to add the
890
+ // correct notation for an array in the multi-select
891
+ // context. Here the name attribute on the select element
892
+ // might be missing the trailing bracket pair. Both names
893
+ // "foo" and "foo[]" should be arrays.
894
+ if (options.hash && key.slice(key.length - 2) !== '[]') {
895
+ result = serializer(result, key + '[]', option.value);
896
+ }
897
+ else {
898
+ result = serializer(result, key, option.value);
899
+ }
900
+ }
901
+ }
902
+
903
+ // Serialize if no selected options and options.empty is true
904
+ if (!isSelectedOptions && options.empty) {
905
+ result = serializer(result, key, '');
906
+ }
907
+
908
+ continue;
909
+ }
910
+
911
+ result = serializer(result, key, val);
912
+ }
913
+
914
+ // Check for all empty radio buttons and serialize them with key=""
915
+ if (options.empty) {
916
+ for (var key in radio_store) {
917
+ if (!radio_store[key]) {
918
+ result = serializer(result, key, '');
919
+ }
920
+ }
921
+ }
922
+
923
+ return result;
924
+ }
925
+
926
+ function parse_keys(string) {
927
+ var keys = [];
928
+ var prefix = /^([^\[\]]*)/;
929
+ var children = new RegExp(brackets);
930
+ var match = prefix.exec(string);
931
+
932
+ if (match[1]) {
933
+ keys.push(match[1]);
934
+ }
935
+
936
+ while ((match = children.exec(string)) !== null) {
937
+ keys.push(match[1]);
938
+ }
939
+
940
+ return keys;
941
+ }
942
+
943
+ function hash_assign(result, keys, value) {
944
+ if (keys.length === 0) {
945
+ result = value;
946
+ return result;
947
+ }
948
+
949
+ var key = keys.shift();
950
+ var between = key.match(/^\[(.+?)\]$/);
951
+
952
+ if (key === '[]') {
953
+ result = result || [];
954
+
955
+ if (Array.isArray(result)) {
956
+ result.push(hash_assign(null, keys, value));
957
+ }
958
+ else {
959
+ // This might be the result of bad name attributes like "[][foo]",
960
+ // in this case the original `result` object will already be
961
+ // assigned to an object literal. Rather than coerce the object to
962
+ // an array, or cause an exception the attribute "_values" is
963
+ // assigned as an array.
964
+ result._values = result._values || [];
965
+ result._values.push(hash_assign(null, keys, value));
966
+ }
967
+
968
+ return result;
969
+ }
970
+
971
+ // Key is an attribute name and can be assigned directly.
972
+ if (!between) {
973
+ result[key] = hash_assign(result[key], keys, value);
974
+ }
975
+ else {
976
+ var string = between[1];
977
+ // +var converts the variable into a number
978
+ // better than parseInt because it doesn't truncate away trailing
979
+ // letters and actually fails if whole thing is not a number
980
+ var index = +string;
981
+
982
+ // If the characters between the brackets is not a number it is an
983
+ // attribute name and can be assigned directly.
984
+ if (isNaN(index)) {
985
+ result = result || {};
986
+ result[string] = hash_assign(result[string], keys, value);
987
+ }
988
+ else {
989
+ result = result || [];
990
+ result[index] = hash_assign(result[index], keys, value);
991
+ }
992
+ }
993
+
994
+ return result;
995
+ }
996
+
997
+ // Object/hash encoding serializer.
998
+ function hash_serializer(result, key, value) {
999
+ var matches = key.match(brackets);
1000
+
1001
+ // Has brackets? Use the recursive assignment function to walk the keys,
1002
+ // construct any missing objects in the result tree and make the assignment
1003
+ // at the end of the chain.
1004
+ if (matches) {
1005
+ var keys = parse_keys(key);
1006
+ hash_assign(result, keys, value);
1007
+ }
1008
+ else {
1009
+ // Non bracket notation can make assignments directly.
1010
+ var existing = result[key];
1011
+
1012
+ // If the value has been assigned already (for instance when a radio and
1013
+ // a checkbox have the same name attribute) convert the previous value
1014
+ // into an array before pushing into it.
1015
+ //
1016
+ // NOTE: If this requirement were removed all hash creation and
1017
+ // assignment could go through `hash_assign`.
1018
+ if (existing) {
1019
+ if (!Array.isArray(existing)) {
1020
+ result[key] = [ existing ];
1021
+ }
1022
+
1023
+ result[key].push(value);
1024
+ }
1025
+ else {
1026
+ result[key] = value;
1027
+ }
1028
+ }
1029
+
1030
+ return result;
1031
+ }
1032
+
1033
+ // urlform encoding serializer
1034
+ function str_serialize(result, key, value) {
1035
+ // encode newlines as \r\n cause the html spec says so
1036
+ value = value.replace(/(\r)?\n/g, '\r\n');
1037
+ value = encodeURIComponent(value);
1038
+
1039
+ // spaces should be '+' rather than '%20'.
1040
+ value = value.replace(/%20/g, '+');
1041
+ return result + (result ? '&' : '') + encodeURIComponent(key) + '=' + value;
1042
+ }
1043
+
1044
+ module.exports = serialize;
1045
+
1046
+ },{}],3:[function(require,module,exports){
1047
+ var domify = require('domify')
1048
+ var serialize = require('form-serialize')
1049
+
1050
+ // Build DOM elements for the structure of the dialog
1051
+ var buildDialogForm = function buildDialogForm (options) {
1052
+ var form = document.createElement('form')
1053
+ form.classList.add('vex-dialog-form')
1054
+
1055
+ var message = document.createElement('div')
1056
+ message.classList.add('vex-dialog-message')
1057
+ message.appendChild(options.message instanceof window.Node ? options.message : domify(options.message))
1058
+
1059
+ var input = document.createElement('div')
1060
+ input.classList.add('vex-dialog-input')
1061
+ input.appendChild(options.input instanceof window.Node ? options.input : domify(options.input))
1062
+
1063
+ form.appendChild(message)
1064
+ form.appendChild(input)
1065
+
1066
+ return form
1067
+ }
1068
+
1069
+ // Take an array of buttons (see the default buttons below) and turn them into DOM elements
1070
+ var buttonsToDOM = function buttonsToDOM (buttons) {
1071
+ var domButtons = document.createElement('div')
1072
+ domButtons.classList.add('vex-dialog-buttons')
1073
+
1074
+ for (var i = 0; i < buttons.length; i++) {
1075
+ var button = buttons[i]
1076
+ var domButton = document.createElement('button')
1077
+ domButton.type = button.type
1078
+ domButton.textContent = button.text
1079
+ domButton.className = button.className
1080
+ domButton.classList.add('vex-dialog-button')
1081
+ if (i === 0) {
1082
+ domButton.classList.add('vex-first')
1083
+ } else if (i === buttons.length - 1) {
1084
+ domButton.classList.add('vex-last')
1085
+ }
1086
+ // Attach click listener to button with closure
1087
+ (function (button) {
1088
+ domButton.addEventListener('click', function (e) {
1089
+ if (button.click) {
1090
+ button.click.call(this, e)
1091
+ }
1092
+ }.bind(this))
1093
+ }.bind(this)(button))
1094
+
1095
+ domButtons.appendChild(domButton)
1096
+ }
1097
+
1098
+ return domButtons
1099
+ }
1100
+
1101
+ var plugin = function plugin (vex) {
1102
+ // Define the API first
1103
+ var dialog = {
1104
+ // Plugin name
1105
+ name: 'dialog',
1106
+
1107
+ // Open
1108
+ open: function open (opts) {
1109
+ var options = Object.assign({}, this.defaultOptions, opts)
1110
+
1111
+ // `message` is unsafe internally, so translate
1112
+ // safe default: HTML-escape the message before passing it through
1113
+ if (options.unsafeMessage && !options.message) {
1114
+ options.message = options.unsafeMessage
1115
+ } else if (options.message) {
1116
+ options.message = vex._escapeHtml(options.message)
1117
+ }
1118
+
1119
+ // Build the form from the options
1120
+ var form = options.unsafeContent = buildDialogForm(options)
1121
+
1122
+ // Open the dialog
1123
+ var dialogInstance = vex.open(options)
1124
+
1125
+ // Quick comment - these options and appending buttons and everything
1126
+ // would preferably be done _before_ opening the dialog. However, since
1127
+ // they rely on the context of the vex instance, we have to do them
1128
+ // after. A potential future fix would be to differentiate between
1129
+ // a "created" vex instance and an "opened" vex instance, so any actions
1130
+ // that rely on the specific context of the instance can do their stuff
1131
+ // before opening the dialog on the page.
1132
+
1133
+ // Override the before close callback to also pass the value of the form
1134
+ var beforeClose = options.beforeClose && options.beforeClose.bind(dialogInstance)
1135
+ dialogInstance.options.beforeClose = function dialogBeforeClose () {
1136
+ // Only call the callback once - when the validation in beforeClose, if present, is true
1137
+ var shouldClose = beforeClose ? beforeClose() : true
1138
+ if (shouldClose) {
1139
+ options.callback(this.value || false)
1140
+ }
1141
+ // Return the result of beforeClose() to vex
1142
+ return shouldClose
1143
+ }.bind(dialogInstance)
1144
+
1145
+ // Append buttons to form with correct context
1146
+ form.appendChild(buttonsToDOM.call(dialogInstance, options.buttons))
1147
+
1148
+ // Attach form to instance
1149
+ dialogInstance.form = form
1150
+
1151
+ // Add submit listener to form
1152
+ form.addEventListener('submit', options.onSubmit.bind(dialogInstance))
1153
+
1154
+ // Optionally focus the first input in the form
1155
+ if (options.focusFirstInput) {
1156
+ var el = dialogInstance.contentEl.querySelector('button, input, select, textarea')
1157
+ if (el) {
1158
+ el.focus()
1159
+ }
1160
+ }
1161
+
1162
+ // For chaining
1163
+ return dialogInstance
1164
+ },
1165
+
1166
+ // Alert
1167
+ alert: function (options) {
1168
+ // Allow string as message
1169
+ if (typeof options === 'string') {
1170
+ options = {
1171
+ message: options
1172
+ }
1173
+ }
1174
+ options = Object.assign({}, this.defaultOptions, this.defaultAlertOptions, options)
1175
+ return this.open(options)
1176
+ },
1177
+
1178
+ // Confirm
1179
+ confirm: function (options) {
1180
+ if (typeof options !== 'object' || typeof options.callback !== 'function') {
1181
+ throw new Error('dialog.confirm(options) requires options.callback.')
1182
+ }
1183
+ options = Object.assign({}, this.defaultOptions, this.defaultConfirmOptions, options)
1184
+ return this.open(options)
1185
+ },
1186
+
1187
+ // Prompt
1188
+ prompt: function (options) {
1189
+ if (typeof options !== 'object' || typeof options.callback !== 'function') {
1190
+ throw new Error('dialog.prompt(options) requires options.callback.')
1191
+ }
1192
+ var defaults = Object.assign({}, this.defaultOptions, this.defaultPromptOptions)
1193
+ var dynamicDefaults = {
1194
+ unsafeMessage: '<label for="vex">' + vex._escapeHtml(options.label || defaults.label) + '</label>',
1195
+ input: '<input name="vex" type="text" class="vex-dialog-prompt-input" placeholder="' + vex._escapeHtml(options.placeholder || defaults.placeholder) + '" value="' + vex._escapeHtml(options.value || defaults.value) + '" />'
1196
+ }
1197
+ options = Object.assign(defaults, dynamicDefaults, options)
1198
+ // Pluck the value of the "vex" input field as the return value for prompt's callback
1199
+ // More closely mimics "window.prompt" in that a single string is returned
1200
+ var callback = options.callback
1201
+ options.callback = function promptCallback (value) {
1202
+ if (typeof value === 'object') {
1203
+ var keys = Object.keys(value)
1204
+ value = keys.length ? value[keys[0]] : ''
1205
+ }
1206
+ callback(value)
1207
+ }
1208
+ return this.open(options)
1209
+ }
1210
+ }
1211
+
1212
+ // Now define any additional data that's not the direct dialog API
1213
+ dialog.buttons = {
1214
+ YES: {
1215
+ text: 'OK',
1216
+ type: 'submit',
1217
+ className: 'vex-dialog-button-primary',
1218
+ click: function yesClick () {
1219
+ this.value = true
1220
+ }
1221
+ },
1222
+
1223
+ NO: {
1224
+ text: 'Cancel',
1225
+ type: 'button',
1226
+ className: 'vex-dialog-button-secondary',
1227
+ click: function noClick () {
1228
+ this.value = false
1229
+ this.close()
1230
+ }
1231
+ }
1232
+ }
1233
+
1234
+ dialog.defaultOptions = {
1235
+ callback: function () {},
1236
+ afterOpen: function () {},
1237
+ message: '',
1238
+ input: '',
1239
+ buttons: [
1240
+ dialog.buttons.YES,
1241
+ dialog.buttons.NO
1242
+ ],
1243
+ showCloseButton: false,
1244
+ onSubmit: function onDialogSubmit (e) {
1245
+ e.preventDefault()
1246
+ if (this.options.input) {
1247
+ this.value = serialize(this.form, { hash: true })
1248
+ }
1249
+ return this.close()
1250
+ },
1251
+ focusFirstInput: true
1252
+ }
1253
+
1254
+ dialog.defaultAlertOptions = {
1255
+ buttons: [
1256
+ dialog.buttons.YES
1257
+ ]
1258
+ }
1259
+
1260
+ dialog.defaultPromptOptions = {
1261
+ label: 'Prompt:',
1262
+ placeholder: '',
1263
+ value: ''
1264
+ }
1265
+
1266
+ dialog.defaultConfirmOptions = {}
1267
+
1268
+ return dialog
1269
+ }
1270
+
1271
+ module.exports = plugin
1272
+
1273
+ },{"domify":1,"form-serialize":2}]},{},[3])(3)
1274
+ });
1275
+ }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
1276
+ },{"domify":2,"form-serialize":4}],6:[function(require,module,exports){
1277
+ var vex = require('./vex')
1278
+ vex.registerPlugin(require('vex-dialog'))
1279
+ module.exports = vex
1280
+
1281
+ },{"./vex":7,"vex-dialog":5}],7:[function(require,module,exports){
1282
+ // classList polyfill for old browsers
1283
+ require('classlist-polyfill')
1284
+ // Object.assign polyfill
1285
+ require('es6-object-assign').polyfill()
1286
+
1287
+ // String to DOM function
1288
+ var domify = require('domify')
1289
+
1290
+ // Use the DOM's HTML parsing to escape any dangerous strings
1291
+ var escapeHtml = function escapeHtml (str) {
1292
+ if (typeof str !== 'undefined') {
1293
+ var div = document.createElement('div')
1294
+ div.appendChild(document.createTextNode(str))
1295
+ return div.innerHTML
1296
+ } else {
1297
+ return ''
1298
+ }
1299
+ }
1300
+
1301
+ // Utility function to add space-delimited class strings to a DOM element's classList
1302
+ var addClasses = function addClasses (el, classStr) {
1303
+ if (typeof classStr !== 'string' || classStr.length === 0) {
1304
+ return
1305
+ }
1306
+ var classes = classStr.split(' ')
1307
+ for (var i = 0; i < classes.length; i++) {
1308
+ var className = classes[i]
1309
+ if (className.length) {
1310
+ el.classList.add(className)
1311
+ }
1312
+ }
1313
+ }
1314
+
1315
+ // Detect CSS Animation End Support
1316
+ // https://github.com/limonte/sweetalert2/blob/99bd539f85e15ac170f69d35001d12e092ef0054/src/utils/dom.js#L194
1317
+ var animationEndEvent = (function detectAnimationEndEvent () {
1318
+ var el = document.createElement('div')
1319
+ var eventNames = {
1320
+ 'WebkitAnimation': 'webkitAnimationEnd',
1321
+ 'MozAnimation': 'animationend',
1322
+ 'OAnimation': 'oanimationend',
1323
+ 'msAnimation': 'MSAnimationEnd',
1324
+ 'animation': 'animationend'
1325
+ }
1326
+ for (var i in eventNames) {
1327
+ if (el.style[i] !== undefined) {
1328
+ return eventNames[i]
1329
+ }
1330
+ }
1331
+ return false
1332
+ })()
1333
+
1334
+ // vex base CSS classes
1335
+ var baseClassNames = {
1336
+ vex: 'vex',
1337
+ content: 'vex-content',
1338
+ overlay: 'vex-overlay',
1339
+ close: 'vex-close',
1340
+ closing: 'vex-closing',
1341
+ open: 'vex-open'
1342
+ }
1343
+
1344
+ // Private lookup table of all open vex objects, keyed by id
1345
+ var vexes = {}
1346
+ var globalId = 1
1347
+
1348
+ // Private boolean to assist the escapeButtonCloses option
1349
+ var isEscapeActive = false
1350
+
1351
+ // vex itself is an object that exposes a simple API to open and close vex objects in various ways
1352
+ var vex = {
1353
+ open: function open (opts) {
1354
+ // Check for usage of deprecated options, and log a warning
1355
+ var warnDeprecated = function warnDeprecated (prop) {
1356
+ console.warn('The "' + prop + '" property is deprecated in vex 3. Use CSS classes and the appropriate "ClassName" options, instead.')
1357
+ console.warn('See http://github.hubspot.com/vex/api/advanced/#options')
1358
+ }
1359
+ if (opts.css) {
1360
+ warnDeprecated('css')
1361
+ }
1362
+ if (opts.overlayCSS) {
1363
+ warnDeprecated('overlayCSS')
1364
+ }
1365
+ if (opts.contentCSS) {
1366
+ warnDeprecated('contentCSS')
1367
+ }
1368
+ if (opts.closeCSS) {
1369
+ warnDeprecated('closeCSS')
1370
+ }
1371
+
1372
+ // The dialog instance
1373
+ var vexInstance = {}
1374
+
1375
+ // Set id
1376
+ vexInstance.id = globalId++
1377
+
1378
+ // Store internally
1379
+ vexes[vexInstance.id] = vexInstance
1380
+
1381
+ // Set state
1382
+ vexInstance.isOpen = true
1383
+
1384
+ // Close function on the vex instance
1385
+ // This is how all API functions should close individual vexes
1386
+ vexInstance.close = function instanceClose () {
1387
+ // Check state
1388
+ if (!this.isOpen) {
1389
+ return true
1390
+ }
1391
+
1392
+ var options = this.options
1393
+
1394
+ // escapeButtonCloses is checked first
1395
+ if (isEscapeActive && !options.escapeButtonCloses) {
1396
+ return false
1397
+ }
1398
+
1399
+ // Allow the user to validate any info or abort the close with the beforeClose callback
1400
+ var shouldClose = (function shouldClose () {
1401
+ // Call before close callback
1402
+ if (options.beforeClose) {
1403
+ return options.beforeClose.call(this)
1404
+ }
1405
+ // Otherwise indicate that it's ok to continue with close
1406
+ return true
1407
+ }.bind(this)())
1408
+
1409
+ // If beforeClose() fails, abort the close
1410
+ if (shouldClose === false) {
1411
+ return false
1412
+ }
1413
+
1414
+ // Update state
1415
+ this.isOpen = false
1416
+
1417
+ // Detect if the content el has any CSS animations defined
1418
+ var style = window.getComputedStyle(this.contentEl)
1419
+ function hasAnimationPre (prefix) {
1420
+ return style.getPropertyValue(prefix + 'animation-name') !== 'none' && style.getPropertyValue(prefix + 'animation-duration') !== '0s'
1421
+ }
1422
+ var hasAnimation = hasAnimationPre('') || hasAnimationPre('-webkit-') || hasAnimationPre('-moz-') || hasAnimationPre('-o-')
1423
+
1424
+ // Define the function that will actually close the instance
1425
+ var close = function close () {
1426
+ if (!this.rootEl.parentNode) {
1427
+ return
1428
+ }
1429
+ // Run once
1430
+ this.rootEl.removeEventListener(animationEndEvent, close)
1431
+ // Remove from lookup table (prevent memory leaks)
1432
+ delete vexes[this.id]
1433
+ // Remove the dialog from the DOM
1434
+ this.rootEl.parentNode.removeChild(this.rootEl)
1435
+ // Call after close callback
1436
+ if (options.afterClose) {
1437
+ options.afterClose.call(this)
1438
+ }
1439
+ // Remove styling from the body, if no more vexes are open
1440
+ if (Object.keys(vexes).length === 0) {
1441
+ document.body.classList.remove(baseClassNames.open)
1442
+ }
1443
+ }.bind(this)
1444
+
1445
+ // Close the vex
1446
+ if (animationEndEvent && hasAnimation) {
1447
+ // Setup the end event listener, to remove the el from the DOM
1448
+ this.rootEl.addEventListener(animationEndEvent, close)
1449
+ // Add the closing class to the dialog, showing the close animation
1450
+ this.rootEl.classList.add(baseClassNames.closing)
1451
+ } else {
1452
+ close()
1453
+ }
1454
+
1455
+ return true
1456
+ }
1457
+
1458
+ // Allow strings as content
1459
+ if (typeof opts === 'string') {
1460
+ opts = {
1461
+ content: opts
1462
+ }
1463
+ }
1464
+
1465
+ // `content` is unsafe internally, so translate
1466
+ // safe default: HTML-escape the content before passing it through
1467
+ if (opts.unsafeContent && !opts.content) {
1468
+ opts.content = opts.unsafeContent
1469
+ } else if (opts.content) {
1470
+ opts.content = escapeHtml(opts.content)
1471
+ }
1472
+
1473
+ // Store options on instance for future reference
1474
+ var options = vexInstance.options = Object.assign({}, vex.defaultOptions, opts)
1475
+
1476
+ // vex root
1477
+ var rootEl = vexInstance.rootEl = document.createElement('div')
1478
+ rootEl.classList.add(baseClassNames.vex)
1479
+ addClasses(rootEl, options.className)
1480
+
1481
+ // Overlay
1482
+ var overlayEl = vexInstance.overlayEl = document.createElement('div')
1483
+ overlayEl.classList.add(baseClassNames.overlay)
1484
+ addClasses(overlayEl, options.overlayClassName)
1485
+ if (options.overlayClosesOnClick) {
1486
+ overlayEl.addEventListener('click', function overlayClickListener (e) {
1487
+ if (e.target === overlayEl) {
1488
+ vexInstance.close()
1489
+ }
1490
+ })
1491
+ }
1492
+ rootEl.appendChild(overlayEl)
1493
+
1494
+ // Content
1495
+ var contentEl = vexInstance.contentEl = document.createElement('div')
1496
+ contentEl.classList.add(baseClassNames.content)
1497
+ addClasses(contentEl, options.contentClassName)
1498
+ contentEl.appendChild(options.content instanceof window.Node ? options.content : domify(options.content))
1499
+ rootEl.appendChild(contentEl)
1500
+
1501
+ // Close button
1502
+ if (options.showCloseButton) {
1503
+ var closeEl = vexInstance.closeEl = document.createElement('div')
1504
+ closeEl.classList.add(baseClassNames.close)
1505
+ addClasses(closeEl, options.closeClassName)
1506
+ closeEl.addEventListener('click', vexInstance.close.bind(vexInstance))
1507
+ contentEl.appendChild(closeEl)
1508
+ }
1509
+
1510
+ // Add to DOM
1511
+ document.querySelector(options.appendLocation).appendChild(rootEl)
1512
+
1513
+ // Call after open callback
1514
+ if (options.afterOpen) {
1515
+ options.afterOpen.call(vexInstance)
1516
+ }
1517
+
1518
+ // Apply styling to the body
1519
+ document.body.classList.add(baseClassNames.open)
1520
+
1521
+ // Return the created vex instance
1522
+ return vexInstance
1523
+ },
1524
+
1525
+ // A top-level vex.close function to close dialogs by reference or id
1526
+ close: function close (vexOrId) {
1527
+ var id
1528
+ if (vexOrId.id) {
1529
+ id = vexOrId.id
1530
+ } else if (typeof vexOrId === 'string') {
1531
+ id = vexOrId
1532
+ } else {
1533
+ throw new TypeError('close requires a vex object or id string')
1534
+ }
1535
+ if (!vexes[id]) {
1536
+ return false
1537
+ }
1538
+ return vexes[id].close()
1539
+ },
1540
+
1541
+ // Close the most recently created/opened vex
1542
+ closeTop: function closeTop () {
1543
+ var ids = Object.keys(vexes)
1544
+ if (!ids.length) {
1545
+ return false
1546
+ }
1547
+ return vexes[ids[ids.length - 1]].close()
1548
+ },
1549
+
1550
+ // Close every vex!
1551
+ closeAll: function closeAll () {
1552
+ for (var id in vexes) {
1553
+ this.close(id)
1554
+ }
1555
+ return true
1556
+ },
1557
+
1558
+ // A getter for the internal lookup table
1559
+ getAll: function getAll () {
1560
+ return vexes
1561
+ },
1562
+
1563
+ // A getter for the internal lookup table
1564
+ getById: function getById (id) {
1565
+ return vexes[id]
1566
+ }
1567
+ }
1568
+
1569
+ // Close top vex on escape
1570
+ window.addEventListener('keyup', function vexKeyupListener (e) {
1571
+ if (e.keyCode === 27) {
1572
+ isEscapeActive = true
1573
+ vex.closeTop()
1574
+ isEscapeActive = false
1575
+ }
1576
+ })
1577
+
1578
+ // Close all vexes on history pop state (useful in single page apps)
1579
+ window.addEventListener('popstate', function () {
1580
+ if (vex.defaultOptions.closeAllOnPopState) {
1581
+ vex.closeAll()
1582
+ }
1583
+ })
1584
+
1585
+ vex.defaultOptions = {
1586
+ content: '',
1587
+ showCloseButton: true,
1588
+ escapeButtonCloses: true,
1589
+ overlayClosesOnClick: true,
1590
+ appendLocation: 'body',
1591
+ className: '',
1592
+ overlayClassName: '',
1593
+ contentClassName: '',
1594
+ closeClassName: '',
1595
+ closeAllOnPopState: true
1596
+ }
1597
+
1598
+ // TODO Loading symbols?
1599
+
1600
+ // Include escapeHtml function on the library object
1601
+ Object.defineProperty(vex, '_escapeHtml', {
1602
+ configurable: false,
1603
+ enumerable: false,
1604
+ writable: false,
1605
+ value: escapeHtml
1606
+ })
1607
+
1608
+ // Plugin system!
1609
+ vex.registerPlugin = function registerPlugin (pluginFn, name) {
1610
+ var plugin = pluginFn(vex)
1611
+ var pluginName = name || plugin.name
1612
+ if (vex[pluginName]) {
1613
+ throw new Error('Plugin ' + name + ' is already registered.')
1614
+ }
1615
+ vex[pluginName] = plugin
1616
+ }
1617
+
1618
+ module.exports = vex
1619
+
1620
+ },{"classlist-polyfill":1,"domify":2,"es6-object-assign":3}]},{},[6])(6)
1621
+ });