[Libreoffice-commits] online.git: loleaflet/.eslintignore loleaflet/js loleaflet/Makefile.am
Henry Castro (via logerrit)
logerrit at kemper.freedesktop.org
Thu Feb 20 13:52:12 UTC 2020
loleaflet/.eslintignore | 1
loleaflet/Makefile.am | 9
loleaflet/js/vex.combined.js | 1628 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 1634 insertions(+), 4 deletions(-)
New commits:
commit 05d433b500e76e2a55c044d4c747fc06d8571d9f
Author: Henry Castro <hcastro at collabora.com>
AuthorDate: Thu Feb 20 08:25:27 2020 -0400
Commit: Henry Castro <hcastro at collabora.com>
CommitDate: Thu Feb 20 14:51:54 2020 +0100
loleaflet: import vex.combined.js library
The file was imported from node_modules/vex-js/dist/js/vex.combined.js
the main reason is to analyze the source code, debug and patch
if necessary
To get the source code from npm repository
make libs
Change-Id: I59e466e925d43bf4c599305898c656f69ec195d9
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/89099
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
Reviewed-by: Henry Castro <hcastro at collabora.com>
diff --git a/loleaflet/.eslintignore b/loleaflet/.eslintignore
index 04f898987..40ef65124 100644
--- a/loleaflet/.eslintignore
+++ b/loleaflet/.eslintignore
@@ -1,4 +1,5 @@
# We only directly edit toolbar.js in dist/
+**/js/vex.combined.js
**/js/sanitize-url.js
**/js/l10n.js
**/js/w2ui-1.5.rc1.js
diff --git a/loleaflet/Makefile.am b/loleaflet/Makefile.am
index 8eee500ab..09e0c1e89 100644
--- a/loleaflet/Makefile.am
+++ b/loleaflet/Makefile.am
@@ -72,8 +72,9 @@ define npm_source
endef
NODE_MODULES_SRC =\
- @braintree/sanitize-url at 3.0.0 \
- l10n-for-node at 0.0.1
+ vex-js at 4.1.0 \
+ l10n-for-node at 0.0.1 \
+ @braintree/sanitize-url at 3.0.0
LOLEAFLET_CSS =\
$(builddir)/node_modules/select2/dist/css/select2.css \
@@ -122,10 +123,10 @@ NODE_MODULES_JS =\
node_modules/smartmenus/dist/jquery.smartmenus.js \
node_modules/autolinker/dist/Autolinker.js \
node_modules/json-js/json2.js \
- node_modules/select2/dist/js/select2.js \
- node_modules/vex-js/dist/js/vex.combined.js
+ node_modules/select2/dist/js/select2.js
LOLEAFLET_LIBS_JS =\
+ vex.combined.js \
sanitize-url.js
if !ENABLE_MOBILEAPP
diff --git a/loleaflet/js/vex.combined.js b/loleaflet/js/vex.combined.js
new file mode 100644
index 000000000..2e09a5497
--- /dev/null
+++ b/loleaflet/js/vex.combined.js
@@ -0,0 +1,1628 @@
+(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(){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}return e})()({1:[function(require,module,exports){
+/*
+ * classList.js: Cross-browser full element.classList implementation.
+ * 1.1.20170427
+ *
+ * By Eli Grey, http://eligrey.com
+ * License: Dedicated to the public domain.
+ * See https://github.com/eligrey/classList.js/blob/master/LICENSE.md
+ */
+
+/*global self, document, DOMException */
+
+/*! @source http://purl.eligrey.com/github/classList.js/blob/master/classList.js */
+
+if ("document" in window.self) {
+
+// Full polyfill for browsers with no classList support
+// Including IE < Edge missing SVGElement.classList
+if (!("classList" in document.createElement("_"))
+ || document.createElementNS && !("classList" in document.createElementNS("http://www.w3.org/2000/svg","g"))) {
+
+(function (view) {
+
+"use strict";
+
+if (!('Element' in view)) return;
+
+var
+ classListProp = "classList"
+ , protoProp = "prototype"
+ , elemCtrProto = view.Element[protoProp]
+ , objCtr = Object
+ , strTrim = String[protoProp].trim || function () {
+ return this.replace(/^\s+|\s+$/g, "");
+ }
+ , arrIndexOf = Array[protoProp].indexOf || function (item) {
+ var
+ i = 0
+ , len = this.length
+ ;
+ for (; i < len; i++) {
+ if (i in this && this[i] === item) {
+ return i;
+ }
+ }
+ return -1;
+ }
+ // Vendors: please allow content code to instantiate DOMExceptions
+ , DOMEx = function (type, message) {
+ this.name = type;
+ this.code = DOMException[type];
+ this.message = message;
+ }
+ , checkTokenAndGetIndex = function (classList, token) {
+ if (token === "") {
+ throw new DOMEx(
+ "SYNTAX_ERR"
+ , "An invalid or illegal string was specified"
+ );
+ }
+ if (/\s/.test(token)) {
+ throw new DOMEx(
+ "INVALID_CHARACTER_ERR"
+ , "String contains an invalid character"
+ );
+ }
+ return arrIndexOf.call(classList, token);
+ }
+ , ClassList = function (elem) {
+ var
+ trimmedClasses = strTrim.call(elem.getAttribute("class") || "")
+ , classes = trimmedClasses ? trimmedClasses.split(/\s+/) : []
+ , i = 0
+ , len = classes.length
+ ;
+ for (; i < len; i++) {
+ this.push(classes[i]);
+ }
+ this._updateClassName = function () {
+ elem.setAttribute("class", this.toString());
+ };
+ }
+ , classListProto = ClassList[protoProp] = []
+ , classListGetter = function () {
+ return new ClassList(this);
+ }
+;
+// Most DOMException implementations don't allow calling DOMException's toString()
+// on non-DOMExceptions. Error's toString() is sufficient here.
+DOMEx[protoProp] = Error[protoProp];
+classListProto.item = function (i) {
+ return this[i] || null;
+};
+classListProto.contains = function (token) {
+ token += "";
+ return checkTokenAndGetIndex(this, token) !== -1;
+};
+classListProto.add = function () {
+ var
+ tokens = arguments
+ , i = 0
+ , l = tokens.length
+ , token
+ , updated = false
+ ;
+ do {
+ token = tokens[i] + "";
+ if (checkTokenAndGetIndex(this, token) === -1) {
+ this.push(token);
+ updated = true;
+ }
+ }
+ while (++i < l);
+
+ if (updated) {
+ this._updateClassName();
+ }
+};
+classListProto.remove = function () {
+ var
+ tokens = arguments
+ , i = 0
+ , l = tokens.length
+ , token
+ , updated = false
+ , index
+ ;
+ do {
+ token = tokens[i] + "";
+ index = checkTokenAndGetIndex(this, token);
+ while (index !== -1) {
+ this.splice(index, 1);
+ updated = true;
+ index = checkTokenAndGetIndex(this, token);
+ }
+ }
+ while (++i < l);
+
+ if (updated) {
+ this._updateClassName();
+ }
+};
+classListProto.toggle = function (token, force) {
+ token += "";
+
+ var
+ result = this.contains(token)
+ , method = result ?
+ force !== true && "remove"
+ :
+ force !== false && "add"
+ ;
+
+ if (method) {
+ this[method](token);
+ }
+
+ if (force === true || force === false) {
+ return force;
+ } else {
+ return !result;
+ }
+};
+classListProto.toString = function () {
+ return this.join(" ");
+};
+
+if (objCtr.defineProperty) {
+ var classListPropDesc = {
+ get: classListGetter
+ , enumerable: true
+ , configurable: true
+ };
+ try {
+ objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
+ } catch (ex) { // IE 8 doesn't support enumerable:true
+ // adding undefined to fight this issue https://github.com/eligrey/classList.js/issues/36
+ // modernie IE8-MSW7 machine has IE8 8.0.6001.18702 and is affected
+ if (ex.number === undefined || ex.number === -0x7FF5EC54) {
+ classListPropDesc.enumerable = false;
+ objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
+ }
+ }
+} else if (objCtr[protoProp].__defineGetter__) {
+ elemCtrProto.__defineGetter__(classListProp, classListGetter);
+}
+
+}(window.self));
+
+}
+
+// There is full or partial native classList support, so just check if we need
+// to normalize the add/remove and toggle APIs.
+
+(function () {
+ "use strict";
+
+ var testElement = document.createElement("_");
+
+ testElement.classList.add("c1", "c2");
+
+ // Polyfill for IE 10/11 and Firefox <26, where classList.add and
+ // classList.remove exist but support only one argument at a time.
+ if (!testElement.classList.contains("c2")) {
+ var createMethod = function(method) {
+ var original = DOMTokenList.prototype[method];
+
+ DOMTokenList.prototype[method] = function(token) {
+ var i, len = arguments.length;
+
+ for (i = 0; i < len; i++) {
+ token = arguments[i];
+ original.call(this, token);
+ }
+ };
+ };
+ createMethod('add');
+ createMethod('remove');
+ }
+
+ testElement.classList.toggle("c3", false);
+
+ // Polyfill for IE 10 and Firefox <24, where classList.toggle does not
+ // support the second argument.
+ if (testElement.classList.contains("c3")) {
+ var _toggle = DOMTokenList.prototype.toggle;
+
+ DOMTokenList.prototype.toggle = function(token, force) {
+ if (1 in arguments && !this.contains(token) === !force) {
+ return force;
+ } else {
+ return _toggle.call(this, token);
+ }
+ };
+
+ }
+
+ testElement = null;
+}());
+
+}
+
+},{}],2:[function(require,module,exports){
+
+/**
+ * Expose `parse`.
+ */
+
+module.exports = parse;
+
+/**
+ * Tests for browser support.
+ */
+
+var innerHTMLBug = false;
+var bugTestDiv;
+if (typeof document !== 'undefined') {
+ bugTestDiv = document.createElement('div');
+ // Setup
+ bugTestDiv.innerHTML = ' <link/><table></table><a href="/a">a</a><input type="checkbox"/>';
+ // Make sure that link elements get serialized correctly by innerHTML
+ // This requires a wrapper element in IE
+ innerHTMLBug = !bugTestDiv.getElementsByTagName('link').length;
+ bugTestDiv = undefined;
+}
+
+/**
+ * Wrap map from jquery.
+ */
+
+var map = {
+ legend: [1, '<fieldset>', '</fieldset>'],
+ tr: [2, '<table><tbody>', '</tbody></table>'],
+ col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
+ // for script/link/style tags to work in IE6-8, you have to wrap
+ // in a div with a non-whitespace character in front, ha!
+ _default: innerHTMLBug ? [1, 'X<div>', '</div>'] : [0, '', '']
+};
+
+map.td =
+map.th = [3, '<table><tbody><tr>', '</tr></tbody></table>'];
+
+map.option =
+map.optgroup = [1, '<select multiple="multiple">', '</select>'];
+
+map.thead =
+map.tbody =
+map.colgroup =
+map.caption =
+map.tfoot = [1, '<table>', '</table>'];
+
+map.polyline =
+map.ellipse =
+map.polygon =
+map.circle =
+map.text =
+map.line =
+map.path =
+map.rect =
+map.g = [1, '<svg xmlns="http://www.w3.org/2000/svg" version="1.1">','</svg>'];
+
+/**
+ * Parse `html` and return a DOM Node instance, which could be a TextNode,
+ * HTML DOM Node of some kind (<div> for example), or a DocumentFragment
+ * instance, depending on the contents of the `html` string.
+ *
+ * @param {String} html - HTML string to "domify"
+ * @param {Document} doc - The `document` instance to create the Node for
+ * @return {DOMNode} the TextNode, DOM Node, or DocumentFragment instance
+ * @api private
+ */
+
+function parse(html, doc) {
+ if ('string' != typeof html) throw new TypeError('String expected');
+
+ // default to the global `document` object
+ if (!doc) doc = document;
+
+ // tag name
+ var m = /<([\w:]+)/.exec(html);
+ if (!m) return doc.createTextNode(html);
+
+ html = html.replace(/^\s+|\s+$/g, ''); // Remove leading/trailing whitespace
+
+ var tag = m[1];
+
+ // body support
+ if (tag == 'body') {
+ var el = doc.createElement('html');
+ el.innerHTML = html;
+ return el.removeChild(el.lastChild);
+ }
+
+ // wrap map
+ var wrap = map[tag] || map._default;
+ var depth = wrap[0];
+ var prefix = wrap[1];
+ var suffix = wrap[2];
+ var el = doc.createElement('div');
+ el.innerHTML = prefix + html + suffix;
+ while (depth--) el = el.lastChild;
+
+ // one element
+ if (el.firstChild == el.lastChild) {
+ return el.removeChild(el.firstChild);
+ }
+
+ // several elements
+ var fragment = doc.createDocumentFragment();
+ while (el.firstChild) {
+ fragment.appendChild(el.removeChild(el.firstChild));
+ }
+
+ return fragment;
+}
+
+},{}],3:[function(require,module,exports){
+/**
+ * Code refactored from Mozilla Developer Network:
+ * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
+ */
+
+'use strict';
+
+function assign(target, firstSource) {
+ if (target === undefined || target === null) {
+ throw new TypeError('Cannot convert first argument to object');
+ }
+
+ var to = Object(target);
+ for (var i = 1; i < arguments.length; i++) {
+ var nextSource = arguments[i];
+ if (nextSource === undefined || nextSource === null) {
+ continue;
+ }
+
+ var keysArray = Object.keys(Object(nextSource));
+ for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {
+ var nextKey = keysArray[nextIndex];
+ var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
+ if (desc !== undefined && desc.enumerable) {
+ to[nextKey] = nextSource[nextKey];
+ }
+ }
+ }
+ return to;
+}
+
+function polyfill() {
+ if (!Object.assign) {
+ Object.defineProperty(Object, 'assign', {
+ enumerable: false,
+ configurable: true,
+ writable: true,
+ value: assign
+ });
+ }
+}
+
+module.exports = {
+ assign: assign,
+ polyfill: polyfill
+};
+
+},{}],4:[function(require,module,exports){
+// get successful control from form and assemble into object
+// http://www.w3.org/TR/html401/interact/forms.html#h-17.13.2
+
+// types which indicate a submit action and are not successful controls
+// these will be ignored
+var k_r_submitter = /^(?:submit|button|image|reset|file)$/i;
+
+// node names which could be successful controls
+var k_r_success_contrls = /^(?:input|select|textarea|keygen)/i;
+
+// Matches bracket notation.
+var brackets = /(\[[^\[\]]*\])/g;
+
+// serializes form fields
+// @param form MUST be an HTMLForm element
+// @param options is an optional argument to configure the serialization. Default output
+// with no options specified is a url encoded string
+// - hash: [true | false] Configure the output type. If true, the output will
+// be a js object.
+// - serializer: [function] Optional serializer function to override the default one.
+// The function takes 3 arguments (result, key, value) and should return new result
+// hash and url encoded str serializers are provided with this module
+// - disabled: [true | false]. If true serialize disabled fields.
+// - empty: [true | false]. If true serialize empty fields
+function serialize(form, options) {
+ if (typeof options != 'object') {
+ options = { hash: !!options };
+ }
+ else if (options.hash === undefined) {
+ options.hash = true;
+ }
+
+ var result = (options.hash) ? {} : '';
+ var serializer = options.serializer || ((options.hash) ? hash_serializer : str_serialize);
+
+ var elements = form && form.elements ? form.elements : [];
+
+ //Object store each radio and set if it's empty or not
+ var radio_store = Object.create(null);
+
+ for (var i=0 ; i<elements.length ; ++i) {
+ var element = elements[i];
+
+ // ingore disabled fields
+ if ((!options.disabled && element.disabled) || !element.name) {
+ continue;
+ }
+ // ignore anyhting that is not considered a success field
+ if (!k_r_success_contrls.test(element.nodeName) ||
+ k_r_submitter.test(element.type)) {
+ continue;
+ }
+
+ var key = element.name;
+ var val = element.value;
+
+ // we can't just use element.value for checkboxes cause some browsers lie to us
+ // they say "on" for value when the box isn't checked
+ if ((element.type === 'checkbox' || element.type === 'radio') && !element.checked) {
+ val = undefined;
+ }
+
+ // If we want empty elements
+ if (options.empty) {
+ // for checkbox
+ if (element.type === 'checkbox' && !element.checked) {
+ val = '';
+ }
+
+ // for radio
+ if (element.type === 'radio') {
+ if (!radio_store[element.name] && !element.checked) {
+ radio_store[element.name] = false;
+ }
+ else if (element.checked) {
+ radio_store[element.name] = true;
+ }
+ }
+
+ // if options empty is true, continue only if its radio
+ if (!val && element.type == 'radio') {
+ continue;
+ }
+ }
+ else {
+ // value-less fields are ignored unless options.empty is true
+ if (!val) {
+ continue;
+ }
+ }
+
+ // multi select boxes
+ if (element.type === 'select-multiple') {
+ val = [];
+
+ var selectOptions = element.options;
+ var isSelectedOptions = false;
+ for (var j=0 ; j<selectOptions.length ; ++j) {
+ var option = selectOptions[j];
+ var allowedEmpty = options.empty && !option.value;
+ var hasValue = (option.value || allowedEmpty);
+ if (option.selected && hasValue) {
+ isSelectedOptions = true;
+
+ // If using a hash serializer be sure to add the
+ // correct notation for an array in the multi-select
+ // context. Here the name attribute on the select element
+ // might be missing the trailing bracket pair. Both names
+ // "foo" and "foo[]" should be arrays.
+ if (options.hash && key.slice(key.length - 2) !== '[]') {
+ result = serializer(result, key + '[]', option.value);
+ }
+ else {
+ result = serializer(result, key, option.value);
+ }
+ }
+ }
+
+ // Serialize if no selected options and options.empty is true
+ if (!isSelectedOptions && options.empty) {
+ result = serializer(result, key, '');
+ }
+
+ continue;
+ }
+
+ result = serializer(result, key, val);
+ }
+
+ // Check for all empty radio buttons and serialize them with key=""
+ if (options.empty) {
+ for (var key in radio_store) {
+ if (!radio_store[key]) {
+ result = serializer(result, key, '');
+ }
+ }
+ }
+
+ return result;
+}
+
+function parse_keys(string) {
+ var keys = [];
+ var prefix = /^([^\[\]]*)/;
+ var children = new RegExp(brackets);
+ var match = prefix.exec(string);
+
+ if (match[1]) {
+ keys.push(match[1]);
+ }
+
+ while ((match = children.exec(string)) !== null) {
+ keys.push(match[1]);
+ }
+
+ return keys;
+}
+
+function hash_assign(result, keys, value) {
+ if (keys.length === 0) {
+ result = value;
+ return result;
+ }
+
+ var key = keys.shift();
+ var between = key.match(/^\[(.+?)\]$/);
+
+ if (key === '[]') {
+ result = result || [];
+
+ if (Array.isArray(result)) {
+ result.push(hash_assign(null, keys, value));
+ }
+ else {
+ // This might be the result of bad name attributes like "[][foo]",
+ // in this case the original `result` object will already be
+ // assigned to an object literal. Rather than coerce the object to
+ // an array, or cause an exception the attribute "_values" is
+ // assigned as an array.
+ result._values = result._values || [];
+ result._values.push(hash_assign(null, keys, value));
+ }
+
+ return result;
+ }
+
+ // Key is an attribute name and can be assigned directly.
+ if (!between) {
+ result[key] = hash_assign(result[key], keys, value);
+ }
+ else {
+ var string = between[1];
+ // +var converts the variable into a number
+ // better than parseInt because it doesn't truncate away trailing
+ // letters and actually fails if whole thing is not a number
+ var index = +string;
+
+ // If the characters between the brackets is not a number it is an
+ // attribute name and can be assigned directly.
+ if (isNaN(index)) {
+ result = result || {};
+ result[string] = hash_assign(result[string], keys, value);
+ }
+ else {
+ result = result || [];
+ result[index] = hash_assign(result[index], keys, value);
+ }
+ }
+
+ return result;
+}
+
+// Object/hash encoding serializer.
+function hash_serializer(result, key, value) {
+ var matches = key.match(brackets);
+
+ // Has brackets? Use the recursive assignment function to walk the keys,
+ // construct any missing objects in the result tree and make the assignment
+ // at the end of the chain.
+ if (matches) {
+ var keys = parse_keys(key);
+ hash_assign(result, keys, value);
+ }
+ else {
+ // Non bracket notation can make assignments directly.
+ var existing = result[key];
+
+ // If the value has been assigned already (for instance when a radio and
+ // a checkbox have the same name attribute) convert the previous value
+ // into an array before pushing into it.
+ //
+ // NOTE: If this requirement were removed all hash creation and
+ // assignment could go through `hash_assign`.
+ if (existing) {
+ if (!Array.isArray(existing)) {
+ result[key] = [ existing ];
+ }
+
+ result[key].push(value);
+ }
+ else {
+ result[key] = value;
+ }
+ }
+
+ return result;
+}
+
+// urlform encoding serializer
+function str_serialize(result, key, value) {
+ // encode newlines as \r\n cause the html spec says so
+ value = value.replace(/(\r)?\n/g, '\r\n');
+ value = encodeURIComponent(value);
+
+ // spaces should be '+' rather than '%20'.
+ value = value.replace(/%20/g, '+');
+ return result + (result ? '&' : '') + encodeURIComponent(key) + '=' + value;
+}
+
+module.exports = serialize;
+
+},{}],5:[function(require,module,exports){
+(function (global){
+(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){
+
+/**
+ * Expose `parse`.
+ */
+
+module.exports = parse;
+
+/**
+ * Tests for browser support.
+ */
+
+var innerHTMLBug = false;
+var bugTestDiv;
+if (typeof document !== 'undefined') {
+ bugTestDiv = document.createElement('div');
+ // Setup
+ bugTestDiv.innerHTML = ' <link/><table></table><a href="/a">a</a><input type="checkbox"/>';
+ // Make sure that link elements get serialized correctly by innerHTML
+ // This requires a wrapper element in IE
+ innerHTMLBug = !bugTestDiv.getElementsByTagName('link').length;
+ bugTestDiv = undefined;
+}
+
+/**
+ * Wrap map from jquery.
+ */
+
+var map = {
+ legend: [1, '<fieldset>', '</fieldset>'],
+ tr: [2, '<table><tbody>', '</tbody></table>'],
+ col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
+ // for script/link/style tags to work in IE6-8, you have to wrap
+ // in a div with a non-whitespace character in front, ha!
+ _default: innerHTMLBug ? [1, 'X<div>', '</div>'] : [0, '', '']
+};
+
+map.td =
+map.th = [3, '<table><tbody><tr>', '</tr></tbody></table>'];
+
+map.option =
+map.optgroup = [1, '<select multiple="multiple">', '</select>'];
+
+map.thead =
+map.tbody =
+map.colgroup =
+map.caption =
+map.tfoot = [1, '<table>', '</table>'];
+
+map.polyline =
+map.ellipse =
+map.polygon =
+map.circle =
+map.text =
+map.line =
+map.path =
+map.rect =
+map.g = [1, '<svg xmlns="http://www.w3.org/2000/svg" version="1.1">','</svg>'];
+
+/**
+ * Parse `html` and return a DOM Node instance, which could be a TextNode,
+ * HTML DOM Node of some kind (<div> for example), or a DocumentFragment
+ * instance, depending on the contents of the `html` string.
+ *
+ * @param {String} html - HTML string to "domify"
+ * @param {Document} doc - The `document` instance to create the Node for
+ * @return {DOMNode} the TextNode, DOM Node, or DocumentFragment instance
+ * @api private
+ */
+
+function parse(html, doc) {
+ if ('string' != typeof html) throw new TypeError('String expected');
+
+ // default to the global `document` object
+ if (!doc) doc = document;
+
+ // tag name
+ var m = /<([\w:]+)/.exec(html);
+ if (!m) return doc.createTextNode(html);
+
+ html = html.replace(/^\s+|\s+$/g, ''); // Remove leading/trailing whitespace
+
+ var tag = m[1];
+
+ // body support
+ if (tag == 'body') {
+ var el = doc.createElement('html');
+ el.innerHTML = html;
+ return el.removeChild(el.lastChild);
+ }
+
+ // wrap map
+ var wrap = map[tag] || map._default;
+ var depth = wrap[0];
+ var prefix = wrap[1];
+ var suffix = wrap[2];
+ var el = doc.createElement('div');
+ el.innerHTML = prefix + html + suffix;
+ while (depth--) el = el.lastChild;
+
+ // one element
+ if (el.firstChild == el.lastChild) {
+ return el.removeChild(el.firstChild);
+ }
+
+ // several elements
+ var fragment = doc.createDocumentFragment();
+ while (el.firstChild) {
+ fragment.appendChild(el.removeChild(el.firstChild));
+ }
+
+ return fragment;
+}
+
+},{}],2:[function(require,module,exports){
+// get successful control from form and assemble into object
+// http://www.w3.org/TR/html401/interact/forms.html#h-17.13.2
+
+// types which indicate a submit action and are not successful controls
+// these will be ignored
+var k_r_submitter = /^(?:submit|button|image|reset|file)$/i;
+
+// node names which could be successful controls
+var k_r_success_contrls = /^(?:input|select|textarea|keygen)/i;
+
+// Matches bracket notation.
+var brackets = /(\[[^\[\]]*\])/g;
+
+// serializes form fields
+// @param form MUST be an HTMLForm element
+// @param options is an optional argument to configure the serialization. Default output
+// with no options specified is a url encoded string
+// - hash: [true | false] Configure the output type. If true, the output will
+// be a js object.
+// - serializer: [function] Optional serializer function to override the default one.
+// The function takes 3 arguments (result, key, value) and should return new result
+// hash and url encoded str serializers are provided with this module
+// - disabled: [true | false]. If true serialize disabled fields.
+// - empty: [true | false]. If true serialize empty fields
+function serialize(form, options) {
+ if (typeof options != 'object') {
+ options = { hash: !!options };
+ }
+ else if (options.hash === undefined) {
+ options.hash = true;
+ }
+
+ var result = (options.hash) ? {} : '';
+ var serializer = options.serializer || ((options.hash) ? hash_serializer : str_serialize);
+
+ var elements = form && form.elements ? form.elements : [];
+
+ //Object store each radio and set if it's empty or not
+ var radio_store = Object.create(null);
+
+ for (var i=0 ; i<elements.length ; ++i) {
+ var element = elements[i];
+
+ // ingore disabled fields
+ if ((!options.disabled && element.disabled) || !element.name) {
+ continue;
+ }
+ // ignore anyhting that is not considered a success field
+ if (!k_r_success_contrls.test(element.nodeName) ||
+ k_r_submitter.test(element.type)) {
+ continue;
+ }
+
+ var key = element.name;
+ var val = element.value;
+
+ // we can't just use element.value for checkboxes cause some browsers lie to us
+ // they say "on" for value when the box isn't checked
+ if ((element.type === 'checkbox' || element.type === 'radio') && !element.checked) {
+ val = undefined;
+ }
+
+ // If we want empty elements
+ if (options.empty) {
+ // for checkbox
+ if (element.type === 'checkbox' && !element.checked) {
+ val = '';
+ }
+
+ // for radio
+ if (element.type === 'radio') {
+ if (!radio_store[element.name] && !element.checked) {
+ radio_store[element.name] = false;
+ }
+ else if (element.checked) {
+ radio_store[element.name] = true;
+ }
+ }
+
+ // if options empty is true, continue only if its radio
+ if (!val && element.type == 'radio') {
+ continue;
+ }
+ }
+ else {
+ // value-less fields are ignored unless options.empty is true
+ if (!val) {
+ continue;
+ }
+ }
+
+ // multi select boxes
+ if (element.type === 'select-multiple') {
+ val = [];
+
+ var selectOptions = element.options;
+ var isSelectedOptions = false;
+ for (var j=0 ; j<selectOptions.length ; ++j) {
+ var option = selectOptions[j];
+ var allowedEmpty = options.empty && !option.value;
+ var hasValue = (option.value || allowedEmpty);
+ if (option.selected && hasValue) {
+ isSelectedOptions = true;
+
+ // If using a hash serializer be sure to add the
+ // correct notation for an array in the multi-select
+ // context. Here the name attribute on the select element
+ // might be missing the trailing bracket pair. Both names
+ // "foo" and "foo[]" should be arrays.
+ if (options.hash && key.slice(key.length - 2) !== '[]') {
+ result = serializer(result, key + '[]', option.value);
+ }
+ else {
+ result = serializer(result, key, option.value);
+ }
+ }
+ }
+
+ // Serialize if no selected options and options.empty is true
+ if (!isSelectedOptions && options.empty) {
+ result = serializer(result, key, '');
+ }
+
+ continue;
+ }
+
+ result = serializer(result, key, val);
+ }
+
+ // Check for all empty radio buttons and serialize them with key=""
+ if (options.empty) {
+ for (var key in radio_store) {
+ if (!radio_store[key]) {
+ result = serializer(result, key, '');
+ }
+ }
+ }
+
+ return result;
+}
+
+function parse_keys(string) {
+ var keys = [];
+ var prefix = /^([^\[\]]*)/;
+ var children = new RegExp(brackets);
+ var match = prefix.exec(string);
+
+ if (match[1]) {
+ keys.push(match[1]);
+ }
+
+ while ((match = children.exec(string)) !== null) {
+ keys.push(match[1]);
+ }
+
+ return keys;
+}
+
+function hash_assign(result, keys, value) {
+ if (keys.length === 0) {
+ result = value;
+ return result;
+ }
+
+ var key = keys.shift();
+ var between = key.match(/^\[(.+?)\]$/);
+
+ if (key === '[]') {
+ result = result || [];
+
+ if (Array.isArray(result)) {
+ result.push(hash_assign(null, keys, value));
+ }
+ else {
+ // This might be the result of bad name attributes like "[][foo]",
+ // in this case the original `result` object will already be
+ // assigned to an object literal. Rather than coerce the object to
+ // an array, or cause an exception the attribute "_values" is
+ // assigned as an array.
+ result._values = result._values || [];
+ result._values.push(hash_assign(null, keys, value));
+ }
+
+ return result;
+ }
+
+ // Key is an attribute name and can be assigned directly.
+ if (!between) {
+ result[key] = hash_assign(result[key], keys, value);
+ }
+ else {
+ var string = between[1];
+ // +var converts the variable into a number
+ // better than parseInt because it doesn't truncate away trailing
+ // letters and actually fails if whole thing is not a number
+ var index = +string;
+
+ // If the characters between the brackets is not a number it is an
+ // attribute name and can be assigned directly.
+ if (isNaN(index)) {
+ result = result || {};
+ result[string] = hash_assign(result[string], keys, value);
+ }
+ else {
+ result = result || [];
+ result[index] = hash_assign(result[index], keys, value);
+ }
+ }
+
+ return result;
+}
+
+// Object/hash encoding serializer.
+function hash_serializer(result, key, value) {
+ var matches = key.match(brackets);
+
+ // Has brackets? Use the recursive assignment function to walk the keys,
+ // construct any missing objects in the result tree and make the assignment
+ // at the end of the chain.
+ if (matches) {
+ var keys = parse_keys(key);
+ hash_assign(result, keys, value);
+ }
+ else {
+ // Non bracket notation can make assignments directly.
+ var existing = result[key];
+
+ // If the value has been assigned already (for instance when a radio and
+ // a checkbox have the same name attribute) convert the previous value
+ // into an array before pushing into it.
+ //
+ // NOTE: If this requirement were removed all hash creation and
+ // assignment could go through `hash_assign`.
+ if (existing) {
+ if (!Array.isArray(existing)) {
+ result[key] = [ existing ];
+ }
+
+ result[key].push(value);
+ }
+ else {
+ result[key] = value;
+ }
+ }
+
+ return result;
+}
+
+// urlform encoding serializer
+function str_serialize(result, key, value) {
+ // encode newlines as \r\n cause the html spec says so
+ value = value.replace(/(\r)?\n/g, '\r\n');
+ value = encodeURIComponent(value);
+
+ // spaces should be '+' rather than '%20'.
+ value = value.replace(/%20/g, '+');
+ return result + (result ? '&' : '') + encodeURIComponent(key) + '=' + value;
+}
+
+module.exports = serialize;
+
+},{}],3:[function(require,module,exports){
+var domify = require('domify')
+var serialize = require('form-serialize')
+
+// Build DOM elements for the structure of the dialog
+var buildDialogForm = function buildDialogForm (options) {
+ var form = document.createElement('form')
+ form.classList.add('vex-dialog-form')
+
+ var message = document.createElement('div')
+ message.classList.add('vex-dialog-message')
+ message.appendChild(options.message instanceof window.Node ? options.message : domify(options.message))
+
+ var input = document.createElement('div')
+ input.classList.add('vex-dialog-input')
+ input.appendChild(options.input instanceof window.Node ? options.input : domify(options.input))
+
+ form.appendChild(message)
+ form.appendChild(input)
+
+ return form
+}
+
+// Take an array of buttons (see the default buttons below) and turn them into DOM elements
+var buttonsToDOM = function buttonsToDOM (buttons) {
+ var domButtons = document.createElement('div')
+ domButtons.classList.add('vex-dialog-buttons')
+
+ for (var i = 0; i < buttons.length; i++) {
+ var button = buttons[i]
+ var domButton = document.createElement('button')
+ domButton.type = button.type
+ domButton.textContent = button.text
+ domButton.className = button.className
+ domButton.classList.add('vex-dialog-button')
+ if (i === 0) {
+ domButton.classList.add('vex-first')
+ } else if (i === buttons.length - 1) {
+ domButton.classList.add('vex-last')
+ }
+ // Attach click listener to button with closure
+ (function (button) {
+ domButton.addEventListener('click', function (e) {
+ if (button.click) {
+ button.click.call(this, e)
+ }
+ }.bind(this))
+ }.bind(this)(button))
+
+ domButtons.appendChild(domButton)
+ }
+
+ return domButtons
+}
+
+var plugin = function plugin (vex) {
+ // Define the API first
+ var dialog = {
+ // Plugin name
+ name: 'dialog',
+
+ // Open
+ open: function open (opts) {
+ var options = Object.assign({}, this.defaultOptions, opts)
+
+ // `message` is unsafe internally, so translate
+ // safe default: HTML-escape the message before passing it through
+ if (options.unsafeMessage && !options.message) {
+ options.message = options.unsafeMessage
+ } else if (options.message) {
+ options.message = vex._escapeHtml(options.message)
+ }
+
+ // Build the form from the options
+ var form = options.unsafeContent = buildDialogForm(options)
+
+ // Open the dialog
+ var dialogInstance = vex.open(options)
+
+ // Quick comment - these options and appending buttons and everything
+ // would preferably be done _before_ opening the dialog. However, since
+ // they rely on the context of the vex instance, we have to do them
+ // after. A potential future fix would be to differentiate between
+ // a "created" vex instance and an "opened" vex instance, so any actions
+ // that rely on the specific context of the instance can do their stuff
+ // before opening the dialog on the page.
+
+ // Override the before close callback to also pass the value of the form
+ var beforeClose = options.beforeClose && options.beforeClose.bind(dialogInstance)
+ dialogInstance.options.beforeClose = function dialogBeforeClose () {
+ // Only call the callback once - when the validation in beforeClose, if present, is true
+ var shouldClose = beforeClose ? beforeClose() : true
+ if (shouldClose) {
+ options.callback(this.value || false)
+ }
+ // Return the result of beforeClose() to vex
+ return shouldClose
+ }.bind(dialogInstance)
+
+ // Append buttons to form with correct context
+ form.appendChild(buttonsToDOM.call(dialogInstance, options.buttons))
+
+ // Attach form to instance
+ dialogInstance.form = form
+
+ // Add submit listener to form
+ form.addEventListener('submit', options.onSubmit.bind(dialogInstance))
+
+ // Optionally focus the first input in the form
+ if (options.focusFirstInput) {
+ var el = dialogInstance.contentEl.querySelector('button, input, select, textarea')
+ if (el) {
+ el.focus()
+ }
+ }
+
+ // For chaining
+ return dialogInstance
+ },
+
+ // Alert
+ alert: function (options) {
+ // Allow string as message
+ if (typeof options === 'string') {
+ options = {
+ message: options
+ }
+ }
+ options = Object.assign({}, this.defaultOptions, this.defaultAlertOptions, options)
+ return this.open(options)
+ },
+
+ // Confirm
+ confirm: function (options) {
+ if (typeof options !== 'object' || typeof options.callback !== 'function') {
+ throw new Error('dialog.confirm(options) requires options.callback.')
+ }
+ options = Object.assign({}, this.defaultOptions, this.defaultConfirmOptions, options)
+ return this.open(options)
+ },
+
+ // Prompt
+ prompt: function (options) {
+ if (typeof options !== 'object' || typeof options.callback !== 'function') {
+ throw new Error('dialog.prompt(options) requires options.callback.')
+ }
+ var defaults = Object.assign({}, this.defaultOptions, this.defaultPromptOptions)
+ var dynamicDefaults = {
+ unsafeMessage: '<label for="vex">' + vex._escapeHtml(options.label || defaults.label) + '</label>',
+ 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) + '" />'
+ }
+ options = Object.assign(defaults, dynamicDefaults, options)
+ // Pluck the value of the "vex" input field as the return value for prompt's callback
+ // More closely mimics "window.prompt" in that a single string is returned
+ var callback = options.callback
+ options.callback = function promptCallback (value) {
+ if (typeof value === 'object') {
+ var keys = Object.keys(value)
+ value = keys.length ? value[keys[0]] : ''
+ }
+ callback(value)
+ }
+ return this.open(options)
+ }
+ }
+
+ // Now define any additional data that's not the direct dialog API
+ dialog.buttons = {
+ YES: {
+ text: 'OK',
+ type: 'submit',
+ className: 'vex-dialog-button-primary',
+ click: function yesClick () {
+ this.value = true
+ }
+ },
+
+ NO: {
+ text: 'Cancel',
+ type: 'button',
+ className: 'vex-dialog-button-secondary',
+ click: function noClick () {
+ this.value = false
+ this.close()
+ }
+ }
+ }
+
+ dialog.defaultOptions = {
+ callback: function () {},
+ afterOpen: function () {},
+ message: '',
+ input: '',
+ buttons: [
+ dialog.buttons.YES,
+ dialog.buttons.NO
+ ],
+ showCloseButton: false,
+ onSubmit: function onDialogSubmit (e) {
+ e.preventDefault()
+ if (this.options.input) {
+ this.value = serialize(this.form, { hash: true })
+ }
+ return this.close()
+ },
+ focusFirstInput: true
+ }
+
+ dialog.defaultAlertOptions = {
+ buttons: [
+ dialog.buttons.YES
+ ]
+ }
+
+ dialog.defaultPromptOptions = {
+ label: 'Prompt:',
+ placeholder: '',
+ value: ''
+ }
+
+ dialog.defaultConfirmOptions = {}
+
+ return dialog
+}
+
+module.exports = plugin
+
+},{"domify":1,"form-serialize":2}]},{},[3])(3)
+});
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+},{"domify":2,"form-serialize":4}],6:[function(require,module,exports){
+var vex = require('./vex')
+vex.registerPlugin(require('vex-dialog'))
+module.exports = vex
+
+},{"./vex":7,"vex-dialog":5}],7:[function(require,module,exports){
+// classList polyfill for old browsers
+require('classlist-polyfill')
+// Object.assign polyfill
+require('es6-object-assign').polyfill()
+
+// String to DOM function
+var domify = require('domify')
+
+// Use the DOM's HTML parsing to escape any dangerous strings
+var escapeHtml = function escapeHtml (str) {
+ if (typeof str !== 'undefined') {
+ var div = document.createElement('div')
+ div.appendChild(document.createTextNode(str))
+ return div.innerHTML
+ } else {
+ return ''
+ }
+}
+
+// Utility function to add space-delimited class strings to a DOM element's classList
+var addClasses = function addClasses (el, classStr) {
+ if (typeof classStr !== 'string' || classStr.length === 0) {
+ return
+ }
+ var classes = classStr.split(' ')
+ for (var i = 0; i < classes.length; i++) {
+ var className = classes[i]
+ if (className.length) {
+ el.classList.add(className)
+ }
+ }
+}
+
+// Detect CSS Animation End Support
+// https://github.com/limonte/sweetalert2/blob/99bd539f85e15ac170f69d35001d12e092ef0054/src/utils/dom.js#L194
+var animationEndEvent = (function detectAnimationEndEvent () {
+ var el = document.createElement('div')
+ var eventNames = {
+ 'animation': 'animationend',
+ 'WebkitAnimation': 'webkitAnimationEnd',
+ 'MozAnimation': 'animationend',
+ 'OAnimation': 'oanimationend',
+ 'msAnimation': 'MSAnimationEnd'
+ }
+ for (var i in eventNames) {
+ if (el.style[i] !== undefined) {
+ return eventNames[i]
+ }
+ }
+ return false
+})()
+
+// vex base CSS classes
+var baseClassNames = {
+ vex: 'vex',
+ content: 'vex-content',
+ overlay: 'vex-overlay',
+ close: 'vex-close',
+ closing: 'vex-closing',
+ open: 'vex-open'
+}
+
+// Private lookup table of all open vex objects, keyed by id
+var vexes = {}
+var globalId = 1
+
+// Private boolean to assist the escapeButtonCloses option
+var isEscapeActive = false
+
+// vex itself is an object that exposes a simple API to open and close vex objects in various ways
+var vex = {
+ open: function open (opts) {
+ // Check for usage of deprecated options, and log a warning
+ var warnDeprecated = function warnDeprecated (prop) {
+ console.warn('The "' + prop + '" property is deprecated in vex 3. Use CSS classes and the appropriate "ClassName" options, instead.')
+ console.warn('See http://github.hubspot.com/vex/api/advanced/#options')
+ }
+ if (opts.css) {
+ warnDeprecated('css')
+ }
+ if (opts.overlayCSS) {
+ warnDeprecated('overlayCSS')
+ }
+ if (opts.contentCSS) {
+ warnDeprecated('contentCSS')
+ }
+ if (opts.closeCSS) {
+ warnDeprecated('closeCSS')
+ }
+
+ // The dialog instance
+ var vexInstance = {}
+
+ // Set id
+ vexInstance.id = globalId++
+
+ // Store internally
+ vexes[vexInstance.id] = vexInstance
+
+ // Set state
+ vexInstance.isOpen = true
+
+ // Close function on the vex instance
+ // This is how all API functions should close individual vexes
+ vexInstance.close = function instanceClose () {
+ // Check state
+ if (!this.isOpen) {
+ return true
+ }
+
+ var options = this.options
+
+ // escapeButtonCloses is checked first
+ if (isEscapeActive && !options.escapeButtonCloses) {
+ return false
+ }
+
+ // Allow the user to validate any info or abort the close with the beforeClose callback
+ var shouldClose = (function shouldClose () {
+ // Call before close callback
+ if (options.beforeClose) {
+ return options.beforeClose.call(this)
+ }
+ // Otherwise indicate that it's ok to continue with close
+ return true
+ }.bind(this)())
+
+ // If beforeClose() fails, abort the close
+ if (shouldClose === false) {
+ return false
+ }
+
+ // Update state
+ this.isOpen = false
+
+ // Detect if the content el has any CSS animations defined
+ var style = window.getComputedStyle(this.contentEl)
+ function hasAnimationPre (prefix) {
+ return style.getPropertyValue(prefix + 'animation-name') !== 'none' && style.getPropertyValue(prefix + 'animation-duration') !== '0s'
+ }
+ var hasAnimation = hasAnimationPre('') || hasAnimationPre('-webkit-') || hasAnimationPre('-moz-') || hasAnimationPre('-o-')
+
+ // Define the function that will actually close the instance
+ var close = function close () {
+ if (!this.rootEl.parentNode) {
+ return
+ }
+ // Run once
+ this.rootEl.removeEventListener(animationEndEvent, close)
+ this.overlayEl.removeEventListener(animationEndEvent, close)
+ // Remove from lookup table (prevent memory leaks)
+ delete vexes[this.id]
+ // Remove the dialog from the DOM
+ this.rootEl.parentNode.removeChild(this.rootEl)
+ // Remove the overlay from the DOM
+ this.bodyEl.removeChild(this.overlayEl)
+ // Call after close callback
+ if (options.afterClose) {
+ options.afterClose.call(this)
+ }
+ // Remove styling from the body, if no more vexes are open
+ if (Object.keys(vexes).length === 0) {
+ document.body.classList.remove(baseClassNames.open)
+ }
+ }.bind(this)
+
+ // Close the vex
+ if (animationEndEvent && hasAnimation) {
+ // Setup the end event listener, to remove the el from the DOM
+ this.rootEl.addEventListener(animationEndEvent, close)
+ this.overlayEl.addEventListener(animationEndEvent, close)
+ // Add the closing class to the dialog, showing the close animation
+ this.rootEl.classList.add(baseClassNames.closing)
+ this.overlayEl.classList.add(baseClassNames.closing)
+ } else {
+ close()
+ }
+
+ return true
+ }
+
+ // Allow strings as content
+ if (typeof opts === 'string') {
+ opts = {
+ content: opts
+ }
+ }
+
+ // `content` is unsafe internally, so translate
+ // safe default: HTML-escape the content before passing it through
+ if (opts.unsafeContent && !opts.content) {
+ opts.content = opts.unsafeContent
+ } else if (opts.content) {
+ opts.content = escapeHtml(opts.content)
+ }
+
+ // Store options on instance for future reference
+ var options = vexInstance.options = Object.assign({}, vex.defaultOptions, opts)
+
+ // Get Body Element
+ var bodyEl = vexInstance.bodyEl = document.getElementsByTagName('body')[0]
+
+ // vex root
+ var rootEl = vexInstance.rootEl = document.createElement('div')
+ rootEl.classList.add(baseClassNames.vex)
+ addClasses(rootEl, options.className)
+
+ // Overlay
+ var overlayEl = vexInstance.overlayEl = document.createElement('div')
+ overlayEl.classList.add(baseClassNames.overlay)
+ addClasses(overlayEl, options.overlayClassName)
+ if (options.overlayClosesOnClick) {
+ rootEl.addEventListener('click', function overlayClickListener (e) {
+ if (e.target === rootEl) {
+ vexInstance.close()
+ }
+ })
+ }
+ bodyEl.appendChild(overlayEl)
+
+ // Content
+ var contentEl = vexInstance.contentEl = document.createElement('div')
+ contentEl.classList.add(baseClassNames.content)
+ addClasses(contentEl, options.contentClassName)
+ contentEl.appendChild(options.content instanceof window.Node ? options.content : domify(options.content))
+ rootEl.appendChild(contentEl)
+
+ // Close button
+ if (options.showCloseButton) {
+ var closeEl = vexInstance.closeEl = document.createElement('div')
+ closeEl.classList.add(baseClassNames.close)
+ addClasses(closeEl, options.closeClassName)
+ closeEl.addEventListener('click', vexInstance.close.bind(vexInstance))
+ contentEl.appendChild(closeEl)
+ }
+
+ // Add to DOM
+ document.querySelector(options.appendLocation).appendChild(rootEl)
+
+ // Call after open callback
+ if (options.afterOpen) {
+ options.afterOpen.call(vexInstance)
+ }
+
+ // Apply styling to the body
+ document.body.classList.add(baseClassNames.open)
+
+ // Return the created vex instance
+ return vexInstance
+ },
+
+ // A top-level vex.close function to close dialogs by reference or id
+ close: function close (vexOrId) {
+ var id
+ if (vexOrId.id) {
+ id = vexOrId.id
+ } else if (typeof vexOrId === 'string') {
+ id = vexOrId
+ } else {
+ throw new TypeError('close requires a vex object or id string')
+ }
+ if (!vexes[id]) {
+ return false
+ }
+ return vexes[id].close()
+ },
+
+ // Close the most recently created/opened vex
+ closeTop: function closeTop () {
+ var ids = Object.keys(vexes)
+ if (!ids.length) {
+ return false
+ }
+ return vexes[ids[ids.length - 1]].close()
+ },
+
+ // Close every vex!
+ closeAll: function closeAll () {
+ for (var id in vexes) {
+ this.close(id)
+ }
+ return true
+ },
+
+ // A getter for the internal lookup table
+ getAll: function getAll () {
+ return vexes
+ },
+
+ // A getter for the internal lookup table
+ getById: function getById (id) {
+ return vexes[id]
+ }
+}
+
+// Close top vex on escape
+window.addEventListener('keyup', function vexKeyupListener (e) {
+ if (e.keyCode === 27) {
+ isEscapeActive = true
+ vex.closeTop()
+ isEscapeActive = false
+ }
+})
+
+// Close all vexes on history pop state (useful in single page apps)
+window.addEventListener('popstate', function () {
+ if (vex.defaultOptions.closeAllOnPopState) {
+ vex.closeAll()
+ }
+})
+
+vex.defaultOptions = {
+ content: '',
+ showCloseButton: true,
+ escapeButtonCloses: true,
+ overlayClosesOnClick: true,
+ appendLocation: 'body',
+ className: '',
+ overlayClassName: '',
+ contentClassName: '',
+ closeClassName: '',
+ closeAllOnPopState: true
+}
+
+// TODO Loading symbols?
+
+// Include escapeHtml function on the library object
+Object.defineProperty(vex, '_escapeHtml', {
+ configurable: false,
+ enumerable: false,
+ writable: false,
+ value: escapeHtml
+})
+
+// Plugin system!
+vex.registerPlugin = function registerPlugin (pluginFn, name) {
+ var plugin = pluginFn(vex)
+ var pluginName = name || plugin.name
+ if (vex[pluginName]) {
+ throw new Error('Plugin ' + name + ' is already registered.')
+ }
+ vex[pluginName] = plugin
+}
+
+module.exports = vex
+
+},{"classlist-polyfill":1,"domify":2,"es6-object-assign":3}]},{},[6])(6)
+});
\ No newline at end of file
More information about the Libreoffice-commits
mailing list