UNPKG

oxe

Version:

A mighty tiny web components framework/library

1,710 lines (1,467 loc) 107 kB
/* Name: oxe Version: 5.2.4 License: MPL-2.0 Author: Alexander Elias Email: alex.steven.elis@gmail.com This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } (function (global, factory) { (typeof exports === "undefined" ? "undefined" : _typeof(exports)) === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = global || self, global.Oxe = factory()); })(this, function () { 'use strict'; var Utility = { PIPE: /\s?\|\s?/, PIPES: /\s?,\s?|\s+/, value: function value(element, model) { if (!model) throw new Error('Utility.value - requires model argument'); if (!element) throw new Error('Utility.value - requires element argument'); var type = this.type(element); if (type === 'radio' || type === 'checkbox') { var name = this.name(element); var query = 'input[type="' + type + '"][name="' + name + '"]'; var form = this.form(element); var elements = form ? this.form(element).querySelectorAll(query) : [element]; var multiple = elements.length > 1; var result = multiple ? [] : undefined; for (var i = 0, l = elements.length; i < l; i++) { var child = elements[i]; var checked = this.checked(child); if (!checked) continue; var value = this.value(child, model); if (multiple) { result.push(value); } else { result = value; break; } } return result; } else if (type === 'select-one' || type === 'select-multiple') { var _multiple = this.multiple(element); var options = element.options; var _result = _multiple ? [] : undefined; for (var _i = 0, _l = options.length; _i < _l; _i++) { var option = options[_i]; var selected = option.selected; var _value = this.value(option, model); var match = this[_multiple ? 'includes' : 'compare'](this.data, _value); if (selected && !match) { if (this.multiple) { _result.push(_value); } else { _result = _value; } } else if (!selected && match) { option.selected = true; } } return _result; } else { var attribute = element.attributes['o-value']; if (attribute) { var values = this.binderValues(attribute.value); var _value2 = this.getByPath(model, values); return _value2 || element.value; } else { return element.value; } } }, form: function form(element) { if (element.form) { return element.form; } else { while (element = element.parentElement) { if (element.nodeName === 'FORM' || element.nodeName.indexOf('-FORM') !== -1) { return element; } } } }, type: function type(element) { if (typeof element.type === 'string') { return element.type; } else { return element.getAttribute('type'); } }, name: function name(element) { if (typeof element.name === 'string') { return element.name; } else { return element.getAttribute('name'); } }, checked: function checked(element) { if (typeof element.checked === 'boolean') { return element.checked; } else { switch (element.getAttribute('checked')) { case undefined: return false; case 'true': return true; case null: return false; case '': return true; default: return false; } } }, multiple: function multiple(element) { if (typeof element.multiple === 'boolean') { return element.multiple; } else { switch (element.getAttribute('multiple')) { case undefined: return false; case 'true': return true; case null: return false; case '': return true; default: return false; } } }, disabled: function disabled(element) { if (typeof element.disabled === 'boolean') { return element.disabled; } else { switch (element.getAttribute('disabled')) { case undefined: return false; case 'true': return true; case null: return false; case '': return true; default: return false; } } }, index: function index(items, item) { for (var i = 0, l = items.length; i < l; i++) { if (this.match(items[i], item)) { return i; } } return -1; }, includes: function includes(items, item) { for (var i = 0, l = items.length; i < l; i++) { if (this.match(items[i], item)) { return true; } } return false; }, match: function match(source, target) { if (source === target) { return true; } if (_typeof(source) !== _typeof(target)) { return false; } if (source.constructor !== target.constructor) { return false; } if (_typeof(source) !== 'object' || _typeof(target) !== 'object') { return source === target; } var sourceKeys = Object.keys(source); var targetKeys = Object.keys(target); if (sourceKeys.length !== targetKeys.length) { return false; } for (var i = 0, l = sourceKeys.length; i < l; i++) { var name = sourceKeys[i]; if (!this.match(source[name], target[name])) { return false; } } return true; }, binderNames: function binderNames(data) { data = data.split('o-')[1]; return data ? data.split('-') : []; }, binderValues: function binderValues(data) { data = data.split(this.PIPE)[0]; return data ? data.split('.') : []; }, binderPipes: function binderPipes(data) { data = data.split(this.PIPE)[1]; return data ? data.split(this.PIPES) : []; }, ensureElement: function ensureElement(data) { data.query = data.query || ''; data.scope = data.scope || document.body; data.position = data.position || 'beforeend'; var element = data.scope.querySelector("".concat(data.name).concat(data.query)); if (!element) { element = document.createElement(data.name); data.scope.insertAdjacentElement(data.position, element); } for (var i = 0, l = data.attributes.length; i < l; i++) { var _data$attributes$i = data.attributes[i], name = _data$attributes$i.name, value = _data$attributes$i.value; element.setAttribute(name, value); } return element; }, setByPath: function setByPath(data, path, value) { var keys = typeof path === 'string' ? path.split('.') : path; var last = keys.length - 1; for (var i = 0; i < last; i++) { var key = keys[i]; if (!(key in data)) { if (isNaN(keys[i + 1])) { data[key] = {}; } else { data[key] = []; } } data = data[key]; } return data[keys[last]] = value; }, getByPath: function getByPath(data, path) { var keys = typeof path === 'string' ? path.split('.') : path; var last = keys.length - 1; if (keys[last] === '$key' || keys[last] === '$index') { return keys[last - 1]; } for (var i = 0; i < last; i++) { var key = keys[i]; if (key in data === false) { return undefined; } else { data = data[key]; } } return data[keys[last]]; }, clone: function clone(source) { if (source === null || source === undefined || source.constructor !== Array && source.constructor !== Object) { return source; } var target = source.constructor(); for (var name in source) { var descriptor = Object.getOwnPropertyDescriptor(source, name); if (descriptor) { if ('value' in descriptor) { descriptor.value = this.clone(descriptor.value); } Object.defineProperty(target, name, descriptor); } } return target; } }; var Batcher = { reads: [], writes: [], time: 1000 / 30, pending: false, setup: function setup(options) { options = options || {}; this.time = options.time || this.time; }, tick: function tick(callback) { window.requestAnimationFrame(callback.bind(this, null)); }, schedule: function schedule() { if (this.pending) return; this.pending = true; this.tick(this.flush); }, flush: function flush(time) { time = time || performance.now(); var task; if (this.writes.length === 0) { while (task = this.reads.shift()) { if (task) { task(); } if (performance.now() - time > this.time) { return this.tick(this.flush); } } } while (task = this.writes.shift()) { if (task) { task(); } if (performance.now() - time > this.time) { return this.tick(this.flush); } } if (this.reads.length === 0 && this.writes.length === 0) { this.pending = false; } else if (performance.now() - time > this.time) { this.tick(this.flush); } else { this.flush(time); } }, remove: function remove(tasks, task) { var index = tasks.indexOf(task); return !!~index && !!tasks.splice(index, 1); }, clear: function clear(task) { return this.remove(this.reads, task) || this.remove(this.writes, task); }, batch: function batch(data) { var self = this; if (!data) return; if (!data.read && !data.write) return; data.context = data.context || {}; var read = function read() { var result; if (data.read) { result = data.read.call(data.context, data.context); } if (data.write && result !== false) { var write = data.write.bind(data.context, data.context); self.writes.push(write); } }; self.reads.push(read); self.schedule(); } }; function Piper(binder, data) { if (binder.type === 'on') { return data; } if (!binder.pipes.length) { return data; } var methods = binder.container.methods; if (!methods) { return data; } for (var i = 0, l = binder.pipes.length; i < l; i++) { var name = binder.pipes[i]; if (name in methods) { var method = methods[name]; if (method && method.constructor === Function) { data = methods[name].call(binder.container, data); } else { console.warn("Oxe.piper - pipe ".concat(name, " invalid type")); } } else { console.warn("Oxe.piper - pipe ".concat(name, " not found")); } } return data; } function Class(binder) { return { read: function read() { this.data = binder.data; if (binder.names.length > 1) { this.name = binder.names.slice(1).join('-'); } }, write: function write() { if (this.name) { if (this.data === undefined || this.data === null) { binder.target.classList.remove(this.name); } else { binder.target.classList.toggle(this.name, this.data); } } else { if (this.data === undefined || this.data === null) { binder.target.setAttribute('class', ''); } else { binder.target.setAttribute('class', this.data); } } } }; } function Default(binder) { return { read: function read() { this.data = binder.data; if (this.data === undefined || this.data === null) { this.data = ''; } else if (_typeof(this.data) === 'object') { this.data = JSON.stringify(this.data); } else if (typeof this.data !== 'string') { this.data = this.data.toString(); } if (this.data === binder.target[binder.type]) { return false; } }, write: function write() { binder.target[binder.type] = this.data; } }; } function Disable(binder) { return { read: function read() { this.data = binder.data; if (this.data === binder.target.disabled) { return false; } }, write: function write() { binder.target.disabled = this.data; } }; } function Each(binder) { var self = this; var render = { read: function read() { this.data = binder.data || []; if (binder.meta.keys === undefined) { binder.meta.keys = []; binder.meta.pending = false; binder.meta.targetLength = 0; binder.meta.currentLength = 0; if (binder.target.firstElementChild) { binder.meta.template = binder.target.removeChild(binder.target.firstElementChild); } else { var element = document.createElement('div'); var text = document.createTextNode("{{$".concat(binder.names[1], "}}")); element.appendChild(text); binder.meta.template = element; } } binder.meta.keys = Object.keys(this.data); binder.meta.targetLength = binder.meta.keys.length; if (binder.meta.currentLength === binder.meta.targetLength) { return false; } }, write: function write() { if (binder.meta.currentLength === binder.meta.targetLength) { binder.meta.pending = false; return; } if (binder.meta.currentLength > binder.meta.targetLength) { var element = binder.target.lastElementChild; binder.target.removeChild(element); self.remove(element); binder.meta.currentLength--; } else if (binder.meta.currentLength < binder.meta.targetLength) { var _element = binder.meta.template.cloneNode(true); var _index = binder.meta.currentLength++; self.add(_element, { index: _index, path: binder.path, variable: binder.names[1], container: binder.container, scope: binder.container.scope, key: binder.meta.keys[_index] }); binder.target.appendChild(_element); } if (binder.meta.pending && render.read) { return; } else { binder.meta.pending = true; } delete render.read; Batcher.batch(render); } }; return render; } function Enable(binder) { return { read: function read() { this.data = !binder.data; if (this.data === binder.target.disabled) { return false; } }, write: function write() { binder.target.disabled = this.data; } }; } function Hide(binder) { return { read: function read() { this.data = binder.data; if (this.data === binder.target.hidden) { return false; } }, write: function write() { binder.target.hidden = this.data; } }; } function Href(binder) { return { read: function read() { this.data = binder.data || ''; if (this.data === binder.target.href) { return false; } }, write: function write() { binder.target.href = this.data; } }; } function Html(binder) { var self = this; return { read: function read() { this.data = binder.data; if (this.data === undefined || this.data === null) { this.data = ''; } else if (_typeof(this.data) === 'object') { this.data = JSON.stringify(this.data); } else if (typeof this.data !== 'string') { this.data = String(this.data); } }, write: function write() { while (binder.target.firstChild) { var node = binder.target.removeChild(binder.target.firstChild); self.remove(node); } var fragment = document.createDocumentFragment(); var parser = document.createElement('div'); parser.innerHTML = this.data; while (parser.firstElementChild) { self.add(parser.firstElementChild, { container: binder.container, scope: binder.container.scope }); fragment.appendChild(parser.firstElementChild); } binder.target.appendChild(fragment); } }; } function Label(binder) { return { read: function read() { this.data = binder.data; if (this.data === undefined || this.data === null) { this.data = ''; } else if (_typeof(this.data) === 'object') { this.data = JSON.stringify(this.data); } else if (typeof this.data !== 'string') { this.data = this.data.toString(); } if (this.data === binder.target.getAttribute('label')) { return false; } }, write: function write() { binder.target.setAttribute('label', this.data); } }; } function On(binder) { return { read: function read(context) { context.data = binder.data; if (typeof context.data !== 'function') { console.warn("Oxe - binder o-on=\"".concat(binder.keys.join('.'), "\" invalid type function required")); return; } if (binder.meta.method) { binder.target.removeEventListener(binder.names[1], binder.meta.method); } else { binder.meta.method = function (events) { var parameters = []; for (var i = 0, l = binder.pipes.length; i < l; i++) { var keys = binder.pipes[i].split('.'); var parameter = Utility.getByPath(binder.container.model, keys); parameters.push(parameter); } parameters.push(events); parameters.push(this); Promise.resolve(context.data.bind(binder.container).apply(null, parameters)); }; } binder.target.addEventListener(binder.names[1], binder.meta.method); } }; } function Read(binder) { return { read: function read() { this.data = binder.data; if (this.data === binder.target.readOnly) { return false; } }, write: function write() { binder.target.readOnly = this.data; } }; } function Require(binder) { return { read: function read() { this.data = binder.data; if (this.data === binder.target.required) { return false; } }, write: function write() { binder.target.required = this.data; } }; } function Show(binder) { return { read: function read() { this.data = binder.data; if (!this.data === binder.target.hidden) { return false; } }, write: function write() { binder.target.hidden = !this.data; } }; } function Style(binder) { return { read: function read() { this.data = binder.data; if (binder.names.length > 1) { this.name = ''; this.names = binder.names.slice(1); for (var i = 0, l = this.names.length; i < l; i++) { if (i === 0) { this.name = this.names[i].toLowerCase(); } else { this.name += this.names[i].charAt(0).toUpperCase() + this.names[i].slice(1).toLowerCase(); } } } }, write: function write() { if (binder.names.length > 1) { if (this.data) { binder.target.style[this.name] = this.data; } else { binder.target.style[this.name] = ''; } } else { if (this.data) { binder.target.style.cssText = this.data; } else { binder.target.style.cssText = ''; } } } }; } function Text(binder) { return { read: function read() { this.data = binder.data; if (this.data === undefined || this.data === null) { this.data = ''; } else if (_typeof(this.data) === 'object') { this.data = JSON.stringify(this.data); } else if (typeof this.data !== 'string') { this.data = this.data.toString(); } if (this.data === binder.target.textContent) { return false; } }, write: function write() { binder.target.textContent = this.data; } }; } function Value(binder, caller) { var self = this; var type = binder.target.type; if (binder.meta.busy) return;else binder.meta.busy = true; if (type === 'select-one' || type === 'select-multiple') { return { read: function read() { this.data = binder.data; this.model = binder.model; this.options = binder.target.options; this.multiple = Utility.multiple(binder.target); if (this.multiple && (!this.data || this.data.constructor !== Array)) { binder.meta.busy = false; throw new Error("Oxe - invalid o-value ".concat(binder.keys.join('.'), " multiple select requires array")); } }, write: function write() { var fallback = false; var fallbackSelectedAtrribute = false; var fallbackValue = this.multiple ? [] : null; var fallbackOption = this.multiple ? [] : null; for (var i = 0, l = this.options.length; i < l; i++) { var option = this.options[i]; var selected = option.selected; var optionBinder = self.get('attribute', option, 'o-value'); var optionValue = optionBinder ? optionBinder.data : option.value; var selectedAtrribute = option.hasAttribute('selected'); if (this.multiple) { if (selectedAtrribute) { fallback = true; fallbackOption.push(option); fallbackValue.push(optionValue); } } else { if (i === 0 || selectedAtrribute) { fallback = true; fallbackOption = option; fallbackValue = optionValue; fallbackSelectedAtrribute = selectedAtrribute; } } if (caller === 'view') { if (selected) { if (this.multiple) { var includes = Utility.includes(this.data, optionValue); if (!includes) { this.selected = true; binder.data.push(optionValue); } } else if (!this.selected) { this.selected = true; binder.data = optionValue; } } else { if (this.multiple) { var _index2 = Utility.index(this.data, optionValue); if (_index2 !== -1) { binder.data.splice(_index2, 1); } } else if (!this.selected && i === l - 1) { binder.data = null; } } } else { if (this.multiple) { var _includes = Utility.includes(this.data, optionValue); if (_includes) { this.selected = true; option.selected = true; } else { option.selected = false; } } else { if (!this.selected) { var match = Utility.match(this.data, optionValue); if (match) { this.selected = true; option.selected = true; } else { option.selected = false; } } else { option.selected = false; } } } } if (!this.selected && fallback) { if (this.multiple) { for (var _i2 = 0, _l2 = fallbackOption.length; _i2 < _l2; _i2++) { fallbackOption[_i2].selected = true; binder.data.push(fallbackValue[_i2]); } } else if (fallbackSelectedAtrribute || this.nodeName === 'OPTION') { binder.data = fallbackValue; fallbackOption.selected = true; } } binder.meta.busy = false; } }; } else if (type === 'radio') { return { read: function read() { this.form = binder.target.form || binder.container; this.query = "input[type=\"radio\"][o-value=\"".concat(binder.value, "\"]"); this.nodes = this.form.querySelectorAll(this.query); this.radios = Array.prototype.slice.call(this.nodes); if (caller === 'view') { binder.data = this.radios.indexOf(binder.target); binder.meta.busy = false; return false; } this.data = binder.data; if (typeof this.data !== 'number') { binder.meta.busy = false; return false; } }, write: function write() { for (var i = 0, l = this.radios.length; i < l; i++) { var radio = this.radios[i]; if (i === this.data) { radio.checked = true; } else { radio.checked = false; } } binder.meta.busy = false; } }; } else if (type === 'checkbox') { return { read: function read() { if (caller === 'view') { binder.data = binder.target.checked; binder.meta.busy = false; return false; } this.data = binder.data; if (typeof this.data !== 'boolean') { binder.meta.busy = false; return false; } }, write: function write() { binder.target.checked = this.data; binder.meta.busy = false; } }; } else { return { read: function read() { if (caller === 'view') { binder.data = binder.target.value; binder.meta.busy = false; return false; } this.data = binder.data; if (this.data === binder.target.value) { binder.meta.busy = false; return false; } }, write: function write() { binder.target.value = this.data === undefined || this.data === null ? '' : this.data; binder.meta.busy = false; } }; } } function Write(binder) { return { read: function read() { this.data = binder.data; if (!this.data === binder.target.readOnly) { return false; } }, write: function write() { binder.target.readOnly = !this.data; } }; } var DATA = new Map(); var BINDERS = { class: Class, css: Style, default: Default, disable: Disable, disabled: Disable, each: Each, enable: Enable, enabled: Enable, hide: Hide, hidden: Hide, href: Href, html: Html, label: Label, on: On, read: Read, require: Require, required: Require, show: Show, showed: Show, style: Style, text: Text, value: Value, write: Write }; var Binder = { get data() { return DATA; }, get binders() { return BINDERS; }, setup: function setup(options) { return new Promise(function ($return, $error) { options = options || {}; this.data.set('location', new Map()); this.data.set('attribute', new Map()); for (var name in this.binders) { this.binders[name] = this.binders[name].bind(this); } if (options.binders) { for (var _name in options.binders) { if (_name in this.binders === false) { this.binders[_name] = options.binders[_name].bind(this); } } } return $return(); }.bind(this)); }, get: function get(type) { if (!type) throw new Error('Oxe.binder.get - type argument required'); var result = this.data.get(type); if (!result) return result; for (var i = 1, l = arguments.length; i < l; i++) { var argument = arguments[i]; result = result.get(argument); if (!result) { return result; } } return result; }, create: function create(data) { if (data.name === undefined) throw new Error('Oxe.binder.create - missing name'); if (data.value === undefined) throw new Error('Oxe.binder.create - missing value'); if (data.target === undefined) throw new Error('Oxe.binder.create - missing target'); if (data.container === undefined) throw new Error('Oxe.binder.create - missing container'); var originalValue = data.value; if (data.value.slice(0, 2) === '{{' && data.value.slice(-2) === '}}') { data.value = data.value.slice(2, -2); } if (data.value.indexOf('$') !== -1 && data.context && data.context.variable && data.context.path && data.context.key) { var pattern = new RegExp("\\$".concat(data.context.variable, "(,|\\s+|\\.|\\|)?(.*)?$"), 'ig'); data.value = data.value.replace(pattern, "".concat(data.context.path, ".").concat(data.context.key, "$1$2")); } var scope = data.container.scope; var names = data.names || Utility.binderNames(data.name); var pipes = data.pipes || Utility.binderPipes(data.value); var values = data.values || Utility.binderValues(data.value); var type = names[0]; var path = values.join('.'); var keys = [scope].concat(values); var location = keys.join('.'); var meta = data.meta || {}; var context = data.context || {}; var source = type === 'on' || type === 'submit' ? data.container.methods : data.container.model; return { get location() { return location; }, get type() { return type; }, get path() { return path; }, get scope() { return scope; }, get name() { return data.name; }, get value() { return data.value; }, get target() { return data.target; }, get container() { return data.container; }, get model() { return data.container.model; }, get methods() { return data.container.methods; }, get keys() { return keys; }, get names() { return names; }, get pipes() { return pipes; }, get values() { return values; }, get meta() { return meta; }, get context() { return context; }, get originalValue() { return originalValue; }, get data() { var data = Utility.getByPath(source, values); return Piper(this, data); }, set data(value) { var data = Piper(this, value); return Utility.setByPath(source, values, data); } }; }, render: function render(binder, caller) { if (binder.type === 'submit') return; var type = binder.type in this.binders ? binder.type : 'default'; var render = this.binders[type](binder, caller); Batcher.batch(render); }, unbind: function unbind(node) { this.data.get('location').forEach(function (scopes) { scopes.forEach(function (binders) { binders.forEach(function (binder, index) { if (binder.target === node) { binders.splice(index, 1); } }); }); }); this.data.get('attribute').delete(node); }, bind: function bind(node, name, value, context) { if (value === "$".concat(context.variable, ".$key") || value === "{{$".concat(context.variable, ".$key}}")) { return Batcher.batch({ write: function write() { node.textContent = context.key; } }); } if (value === "$".concat(context.variable, ".$index") || value === "{{$".concat(context.variable, ".$index}}")) { return Batcher.batch({ write: function write() { node.textContent = context.index; } }); } var binder = this.create({ name: name, value: value, target: node, context: context, container: context.container, scope: context.container.scope }); if (!this.data.get('attribute').has(binder.target)) { this.data.get('attribute').set(binder.target, new Map()); } if (!this.data.get('location').has(binder.scope)) { this.data.get('location').set(binder.scope, new Map()); } if (!this.data.get('location').get(binder.scope).has(binder.path)) { this.data.get('location').get(binder.scope).set(binder.path, []); } this.data.get('attribute').get(binder.target).set(binder.name, binder); this.data.get('location').get(binder.scope).get(binder.path).push(binder); this.render(binder); }, remove: function remove(node) { this.unbind(node); for (var i = 0; i < node.childNodes.length; i++) { this.remove(node.childNodes[i]); } }, add: function add(node, context) { if (node.nodeType === Node.TEXT_NODE) { if (node.textContent.indexOf('{{') === -1 || node.textContent.indexOf('}}') === -1) { return; } var start = node.textContent.indexOf('{{'); if (start !== -1 && start !== 0) { node = node.splitText(start); } var end = node.textContent.indexOf('}}'); var length = node.textContent.length; if (end !== -1 && end !== length - 2) { var split = node.splitText(end + 2); this.add(split, context); } this.bind(node, 'o-text', node.textContent, context); } else if (node.nodeType === Node.ELEMENT_NODE) { var skipChildren = false; var attributes = node.attributes; for (var i = 0, l = attributes.length; i < l; i++) { var attribute = attributes[i]; if (attribute.name === 'o-html' || attribute.name === 'o-scope' || attribute.name.indexOf('o-each') === 0) { skipChildren = true; } if (attribute.name === 'o-value' || attribute.name === 'o-scope' || attribute.name === 'o-reset' || attribute.name === 'o-action' || attribute.name === 'o-method' || attribute.name === 'o-enctype' || attribute.name.indexOf('o-') !== 0) { continue; } this.bind(node, attribute.name, attribute.value, context); } if ('o-value' in attributes) { this.bind(node, 'o-value', attributes['o-value'].value, context); } if (skipChildren) return; for (var _i3 = 0; _i3 < node.childNodes.length; _i3++) { this.add(node.childNodes[_i3], context); } } } }; function Change(event) { return new Promise(function ($return, $error) { if ('attributes' in event.target && 'o-value' in event.target.attributes) { var binder = Binder.get('attribute', event.target, 'o-value'); Binder.render(binder, 'view'); } return $return(); }); } var Fetcher = { headers: null, method: 'get', mime: { xml: 'text/xml; charset=utf-8', html: 'text/html; charset=utf-8', text: 'text/plain; charset=utf-8', json: 'application/json; charset=utf-8', js: 'application/javascript; charset=utf-8' }, setup: function setup(options) { return new Promise(function ($return, $error) { options = options || {}; this.path = options.path; this.origin = options.origin; this.request = options.request; this.response = options.response; this.acceptType = options.acceptType; this.credentials = options.credentials; this.contentType = options.contentType; this.responseType = options.responseType; this.method = options.method || this.method; this.headers = options.headers || this.headers; return $return(); }.bind(this)); }, serialize: function serialize(data) { return new Promise(function ($return, $error) { var query = ''; for (var name in data) { query = query.length > 0 ? query + '&' : query; query = query + encodeURIComponent(name) + '=' + encodeURIComponent(data[name]); } return $return(query); }); }, fetch: function fetch(options) { return new Promise(function ($return, $error) { var data, copy, result, fetched, _copy, _result2; data = Object.assign({}, options); data.path = data.path || this.path; data.origin = data.origin || this.origin; if (data.path && typeof data.path === 'string' && data.path.charAt(0) === '/') data.path = data.path.slice(1); if (data.origin && typeof data.origin === 'string' && data.origin.charAt(data.origin.length - 1) === '/') data.origin = data.origin.slice(0, -1); if (data.path && data.origin && !data.url) data.url = data.origin + '/' + data.path; if (!data.method) return $error(new Error('Oxe.fetcher - requires method option')); if (!data.url) return $error(new Error('Oxe.fetcher - requires url or origin and path option')); if (!data.headers && this.headers) data.headers = this.headers; if (typeof data.method === 'string') data.method = data.method.toUpperCase() || this.method; if (!data.acceptType && this.acceptType) data.acceptType = this.acceptType; if (!data.contentType && this.contentType) data.contentType = this.contentType; if (!data.responseType && this.responseType) data.responseType = this.responseType; if (!data.credentials && this.credentials) data.credentials = this.credentials; if (!data.mode && this.mode) data.mode = this.mode; if (!data.cache && this.cache) data.cahce = this.cache; if (!data.redirect && this.redirect) data.redirect = this.redirect; if (!data.referrer && this.referrer) data.referrer = this.referrer; if (!data.referrerPolicy && this.referrerPolicy) data.referrerPolicy = this.referrerPolicy; if (!data.signal && this.signal) data.signal = this.signal; if (!data.integrity && this.integrity) data.integrity = this.integrity; if (!data.keepAlive && this.keepAlive) data.keepAlive = this.keepAlive; if (data.contentType) { data.headers = data.headers || {}; switch (data.contentType) { case 'js': data.headers['Content-Type'] = this.mime.js; break; case 'xml': data.headers['Content-Type'] = this.mime.xml; break; case 'html': data.headers['Content-Type'] = this.mime.html; break; case 'json': data.headers['Content-Type'] = this.mime.json; break; default: data.headers['Content-Type'] = data.contentType; } } if (data.acceptType) { data.headers = data.headers || {}; switch (data.acceptType) { case 'js': data.headers['Accept'] = this.mime.js; break; case 'xml': data.headers['Accept'] = this.mime.xml; break; case 'html': data.headers['Accept'] = this.mime.html; break; case 'json': data.headers['Accept'] = this.mime.json; break; default: data.headers['Accept'] = data.acceptType; } } if (typeof this.request === 'function') { copy = Object.assign({}, data); return Promise.resolve(this.request(copy)).then(function ($await_29) { try { result = $await_29; if (result === false) { return $return(data); } if (_typeof(result) === 'object') { Object.assign(data, result); } return $If_1.call(this); } catch ($boundEx) { return $error($boundEx); } }.bind(this), $error); } function $If_1() { if (data.body) { if (data.method === 'GET') { return Promise.resolve(this.serialize(data.body)).then(function ($await_30) { try { data.url = data.url + '?' + $await_30; return $If_5.call(this); } catch ($boundEx) { return $error($boundEx); } }.bind(this), $error); } else { if (data.contentType === 'json') { data.body = JSON.stringify(data.body); } return $If_5.call(this); } function $If_5() { return $If_2.call(this); } } function $If_2() { return Promise.resolve(window.fetch(data.url, Object.assign({}, data))).then(function ($await_31) { try { fetched = $await_31; data.code = fetched.status; data.message = fetched.statusText; if (!data.responseType) { data.body = fetched.body; return $If_3.call(this); } else { return Promise.resolve(fetched[data.responseType === 'buffer' ? 'arrayBuffer' : data.responseType]()).then(function ($await_32) { try { data.body = $await_32; return $If_3.call(this); } catch ($boundEx) { return $error($boundEx); } }.bind(this), $error); } function $If_3() { if (this.response) { _copy = Object.assign({}, data); return Promise.resolve(this.response(_copy)).then(function ($await_33) { try { _result2 = $await_33; if (_result2 === false) { return $return(data); } if (_typeof(_result2) === 'object') { Object.assign(data, _result2); } return $If_4.call(this); } catch ($boundEx) { return $error($boundEx); } }.bind(this), $error); } function $If_4() { return $return(data); } return $If_4.call(this); } } catch ($boundEx) { return $error($boundEx); } }.bind(this), $error); } return $If_2.call(this); } return $If_1.call(this); }.bind(this)); }, post: function post(data) { return new Promise(function ($return, $error) { data = typeof data === 'string' ? { url: data } : data; data.method = 'post'; return $return(this.fetch(data)); }.bind(this)); }, get: function get(data) { return new Promise(function ($return, $error) { data = typeof data === 'string' ? { url: data } : data; data.method = 'get'; return $return(this.fetch(data)); }.bind(this)); }, put: function put(data) { return new Promise(function ($return, $error) { data = typeof data === 'string' ? { url: data } : data; data.method = 'put'; return $return(this.fetch(data)); }.bind(this)); }, head: function head(data) { return new Promise(function ($return, $error) { data = typeof data === 'string' ? { url: data } : data; data.method = 'head'; return $return(this.fetch(data)); }.bind(this)); }, patch: function patch(data) { return new Promise(function ($return, $error) { data = typeof data === 'string' ? { url: data } : data; data.method = 'patch'; return $return(this.fetch(data)); }.bind(this)); }, delete: function _delete(data) { return new Promise(function ($return, $error) { data = typeof data === 'string' ? { url: data } : data; data.method = 'delete'; return $return(this.fetch(data)); }.bind(this)); }, options: function options(data) { return new Promise(function ($return, $error) { data = typeof data === 'string' ? { url: data } : data; data.method = 'options'; return $return(this.fetch(data)); }.bind(this)); }, connect: function connect(data) { return new Promise(function ($return, $error) { data = typeof data === 'string' ? { url: data } : data; data.method = 'connect'; return $return(this.fetch(data)); }.bind(this)); } }; function Submit(event) { return new Promise(function ($return, $error) { var data, elements, i, l, element, type, binder, value, name, submit, options, result; if (event.target.hasAttribute('o-submit') === false) { return $return(); } event.preventDefault(); data = {}; elements = event.target.querySelectorAll('*'); for (i = 0, l = elements.length; i < l; i++) { element = elements[i]; type = element.type; if (!type && name !== 'TEXTAREA' || type === 'submit' || type === 'button' || !type) { continue; } binder = Binder.get('attribute', element, 'o-value'); value = binder ? binder.data : element.files ? Array.prototype.slice.call(element.files) : element.value; name = element.name || (binder ? binder.values[binder.values.length - 1] : null); if (!name) continue; data[name] = value; } submit = Binder.get('attribute', event.target, 'o-submit'); return Promise.resolve(submit.data.call(submit.container, data, event)).then(function ($await_34) { try { options = $await_34; if (_typeof(options) === 'object') { options.url = options.url || event.target.getAttribute('o-action'); options.method = options.method || event.target.getAttribute('o-method'); options.contentType = options.contentType || event.target.getAttribute('o-enctype'); return Promise.resolve(Fetcher.fetch(options)).then(function ($await_35) { try { result = $await_35; if (options.handler) { return Promise.resolve(options.handler(result)).then(function ($await_36) { try { return $If_7.call(this); } catch ($boundEx) { return $error($boundEx); } }.bind(this), $error); } function $If_7() { return $If_6.call(this); } return $If_7.call(this); } catch ($boundEx) { return $error($boundEx); } }.bind(this), $error); } function $If_6() { if (event.target.hasAttribute('o-reset') || _typeof(options) === 'object' && options.reset) { event.target.reset(); } return $return(); } return $If_6.call(this); } catch ($boundEx) { return $error($boundEx); } }.bind(this), $error); }); } function Input(event) { return new Promise(function ($return, $error) { if (event.target.type !== 'radio' && event.target.type !== 'option' && event.target.type !== 'checkbox' && event.target.type !== 'select-one'