UNPKG

platypusui

Version:

A front-end set of UI controls for PlatypusTS written in TypeScript

1,148 lines (1,147 loc) 337 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); /* tslint:disable */ /** * PlatypusUI v0.16.9 (https://platypi.io) * Copyright 2015 Platypi, LLC. All rights reserved. * * PlatypusUI is licensed under the MIT license found at * https://github.com/Platypi/platypusui/blob/master/LICENSE * */ /** * The entry point into the platypus UI controls library. */ var platui; (function (platui) { 'use strict'; /* tslint:disable:no-unused-variable */ /* */ var __prefix = '$', __Promise = __prefix + "Promise", __Compat = __prefix + "Compat", __Regex = __prefix + "Regex", __Window = __prefix + "Window", __Document = __prefix + "Document", __Utils = __prefix + "Utils", __Animator = __prefix + "Animator", __DomEventInstance = __prefix + "DomEventInstance", __TemplateControlFactory = __prefix + "TemplateControlFactory", __NodeManagerStatic = __prefix + "NodeManagerStatic", /** */ __CONTEXT = 'context', /** */ __PlatPrefix = 'plat', __Plat = __PlatPrefix + "-", __Button = __Plat + "button", __Checkbox = __Plat + "checkbox", __Drawer = __Plat + "drawer", __DrawerController = __Drawer + "-controller", __Modal = __Plat + "modal", __ProgressBar = __Plat + "progress", __ProgressRing = __Plat + "ring", __Radio = __Plat + "radio", __Toggle = __Plat + "toggle", __Slider = __Plat + "slider", __Range = __Plat + "range", __Select = __Plat + "select", __Input = __Plat + "input", __File = __Plat + "file", __Carousel = __Plat + "carousel", __Listview = __Plat + "listview", __Navbar = __Plat + "navbar", __Image = __Plat + "image", /** */ __Hide = __Plat + "hide", __Hidden = __Plat + "hidden", __Context = __Plat + __CONTEXT, __ForEach = __Plat + "foreach", __Html = __Plat + "html", __Disabled = __Plat + "disabled", __Readonly = __Plat + "readonly", __CamelContext = __PlatPrefix + "Context", __CamelChecked = __PlatPrefix + "Checked", __CamelBind = __PlatPrefix + "Bind", __CamelSrc = __PlatPrefix + "Src", /** */ __listviewAliasOptions = { index: 'index', even: 'even', odd: 'odd', first: 'first', last: 'last', group: 'group' }, /** */ __Transition = __Plat + "transition", __Enter = __Plat + "enter", __Leave = __Plat + "leave", /** */ __$tap = '$tap', __$touchstart = '$touchstart', __$touchend = '$touchend', __$touchcancel = '$touchcancel', __$swipe = '$swipe', __$track = '$track', __$trackend = '$trackend', __ButtonPrefix = '__plat-button-', __RadioPrefix = '__plat-radio-', __DrawerControllerInitEvent = '__platDrawerControllerInit', __DrawerControllerFetchEvent = '__platDrawerControllerFetch', __DrawerFoundEvent = '__platDrawerFound', /** */ __Reversed = '-reversed', __NAME_ATTRIBUTE = 'name', __LITERAL_RESOURCE = 'literal', __transitionNegate = { right: 'left', left: 'right', up: 'down', down: 'up' }, __src = 'src', __preventDefault = function (ev) { ev.preventDefault(); return false; }, noop = function () { }; /* tslint:enable:no-unused-variable */ if (typeof window !== 'undefined') { if (typeof window.platui === 'undefined') { window.platui = platui; } if (typeof window.module === 'undefined') { window.module = {}; } } /** * An BindControl that standardizes an HTML5 button. */ var Button = /** @class */ (function (_super) { __extends(Button, _super); function Button() { var _this = _super !== null && _super.apply(this, arguments) || this; /** * Replaces the <plat-button> node with * a <button> node. */ _this.replaceWith = 'button'; /** * A boolean value showing the selected state of this Button. */ _this._isSelected = false; return _this; } /** * Sets the classes on the proper elements. * @param {string} className? An optional, additional class name or class names to set on the control * in addition to its standard set. * @param {Element} element? The element to set the class name on. Should default to * the control's element if not specified. */ Button.prototype.setClasses = function (className, element) { this.dom.addClass(element || this.element, __Button + " " + (className || '')); }; /** * Sets default classes. */ Button.prototype.initialize = function () { this.setClasses(); }; /** * Determine the button style and apply the proper classes. */ Button.prototype.loaded = function () { var element = this.element, optionObj = this.options || {}, options = optionObj.value || {}, group = options.group, isString = this.utils.isString; if (!isString(group)) { group = this.attributes[__CamelBind]; if (isString(group)) { this._group = group; if (this.dom.hasClass(element, __Plat + "selected")) { this._onTap(); } this._addEventListeners(); } return; } this._group = group; if (this.dom.hasClass(element, __Plat + "selected")) { this._onTap(); } this._addEventListeners(); }; /** * A function that allows this control to observe both the bound property itself as well as * potential child properties if being bound to an object. * @param {plat.observable.IImplementTwoWayBinding} binder The control that facilitates the * databinding. */ Button.prototype.observeProperties = function (binder) { binder.observeProperty(this._setBoundProperty); }; /** * The function called when the bindable property is set externally. * @param {string} newValue The new value of the bindable property. * @param {string} oldValue The old value of the bindable property. * @param {string} identifier The identifier of the property being observed. * @param {boolean} firstTime? A boolean value indicating whether this is the first time its being set. */ Button.prototype._setBoundProperty = function (newValue, oldValue, identifier, firstTime) { if (!this.utils.isString(newValue) || newValue !== this.element.textContent) { return; } this._onTap(); }; /** * Add event listeners for selection. */ Button.prototype._addEventListeners = function () { var _this = this; this.addEventListener(this.element, __$tap, this._onTap, false); this.on(__ButtonPrefix + this._group, function () { if (_this._isSelected) { _this.dom.removeClass(_this.element, __Plat + "selected"); _this._isSelected = false; } }); }; /** * Place the pushed button in a selected state. */ Button.prototype._onTap = function () { if (this._isSelected) { return; } var element = this.element; this.dom.addClass(element, __Plat + "selected"); this.dispatchEvent(__ButtonPrefix + this._group, plat.events.EventManager.DIRECT); this._isSelected = true; this.inputChanged(element.hasAttribute('value') ? element.getAttribute('value').trim() : element.textContent.trim()); }; Button._inject = { _document: __Document }; return Button; }(plat.ui.BindControl)); platui.Button = Button; plat.register.control(__Button, Button); /** * An BindControl that simulates a toggle switch. */ var Toggle = /** @class */ (function (_super) { __extends(Toggle, _super); function Toggle() { var _this = _super !== null && _super.apply(this, arguments) || this; /** * The HTML template represented as a string. */ _this.templateString = '<div class="plat-toggle-container">\n' + ' <div class="plat-knob"></div>\n' + '</div>\n'; /** * A boolean value indicating whether the control is actively selected. */ _this.isActive = false; /** * The type of the control's activated element. */ _this._targetType = 'slide'; return _this; } /** * Sets the classes on the proper elements. * @param {string} className? An optional, additional class name or class names to set on the control * in addition to its standard set. * @param {Element} element? The element to set the class name on. Should default to * the control's element if not specified. */ Toggle.prototype.setClasses = function (className, element) { this.dom.addClass(element || this.element, __Toggle + " " + (className || '')); }; /** * Set the class name. */ Toggle.prototype.initialize = function () { this.setClasses(); }; /** * Adds the inner template to the DOM making sure to wrap text nodes in spans. */ Toggle.prototype.setTemplate = function () { var isNull = this.utils.isNull, innerTemplate = this.innerTemplate; if (isNull(innerTemplate)) { return; } var span = this._document.createElement('span'); this.dom.appendChildren(innerTemplate.childNodes, span); this.element.insertBefore(span, null); }; /** * Adds a listener for the tap event. */ Toggle.prototype.loaded = function () { var element = this.element; this._targetElement = element.firstElementChild; this.addEventListener(element, __$tap, this._onTap); this._convertChecked(); }; /** * Toggles the active state of the control. */ Toggle.prototype.toggle = function () { this._toggle(true); }; /** * A function that allows this control to observe both the bound property itself as well as * potential child properties if being bound to an object. * @param {plat.observable.IImplementTwoWayBinding} binder The control that facilitates the * databinding. */ Toggle.prototype.observeProperties = function (binder) { binder.observeProperty(this._setBoundProperty); }; /** * The function called when the bindable property is set externally. * @param {any} newValue The new value of the bindable property. * @param {any} oldValue The old value of the bindable property. * @param {string} identifier The identifier of the property being observed. * @param {boolean} setProperty? A boolean value indicating whether we should set * the property if we need to toggle the state. */ Toggle.prototype._setBoundProperty = function (newValue, oldValue, identifier, setProperty) { if (newValue === oldValue) { return; } else if (setProperty === true && this.utils.isNull(newValue)) { this.inputChanged(this.isActive); return; } var isActive = !!newValue; if (isActive === this.isActive) { return; } this._toggle(setProperty); }; /** * A function for checking "checked" attributes and handling them accordingly. * @param {any} newValue The newValue of the attribute to convert. * @param {any} oldValue? The oldValue of the attribute to convert. */ Toggle.prototype._convertChecked = function () { var element = this.element; if (!this.utils.isNull(this.attributes[__CamelChecked])) { this._convertAttribute(this.attributes[__CamelChecked]); this.attributes.observe(this._convertAttribute, __CamelChecked); } else if (element.hasAttribute('checked')) { this._convertAttribute(true); } }; /** * A function for handling the attribute value conversion for updating the * bound property. * @param {any} newValue The newValue of the attribute to convert. * @param {any} oldValue? The oldValue of the attribute to convert. */ Toggle.prototype._convertAttribute = function (newValue, oldValue) { var utils = this.utils; if (utils.isBoolean(newValue)) { return this._setBoundProperty(newValue, oldValue, null, true); } else if (!utils.isString(newValue)) { return; } this._setBoundProperty(newValue === 'true', oldValue === 'true', null, true); }; /** * The callback for a tap event. * @param {plat.ui.IGestureEvent} ev The tap event object. */ Toggle.prototype._onTap = function (ev) { if (this.element.hasAttribute('disabled')) { return; } this._toggle(true); this._trigger('change'); }; /** * Triggers an event starting from this control's element. * @param {string} event The event name to trigger. */ Toggle.prototype._trigger = function (event) { var domEvent = plat.acquire(__DomEventInstance); domEvent.initialize(this.element, event); domEvent.trigger(); }; /** * Toggles the mark and updates the bindable property if needed. * @param {boolean} setProperty? A boolean value stating whether the bindable * property should be updated. */ Toggle.prototype._toggle = function (setProperty) { var wasActive = this.isActive, isActive = !wasActive, element = this.element; this._activate(this._targetElement || (this._targetElement = element.firstElementChild)); this.isActive = element.checked = isActive; if (isActive) { element.setAttribute('checked', 'checked'); } else { element.removeAttribute('checked'); } if (setProperty === true) { this.inputChanged(isActive, wasActive); } }; /** * A function to activate the given element by toggling the * class specified as the target type. * @param {Element} element The element to activate. */ Toggle.prototype._activate = function (element) { this.dom.toggleClass(element, __Plat + this._targetType); }; Toggle._inject = { _document: __Document }; return Toggle; }(plat.ui.BindControl)); platui.Toggle = Toggle; plat.register.control(__Toggle, Toggle); /** * An IBindablePropertyControl that standardizes the HTML5 checkbox. */ var Checkbox = /** @class */ (function (_super) { __extends(Checkbox, _super); function Checkbox() { var _this = _super !== null && _super.apply(this, arguments) || this; /** * The HTML template represented as a string. */ _this.templateString = '<div class="plat-checkbox-container">\n' + ' <span class="plat-mark"></span>\n' + '</div>\n'; /** * Whether the target type has been set already or not. */ _this._targetTypeSet = false; return _this; } /** * Sets the classes on the proper elements. * @param {string} className? An optional, additional class name or class names to set on the control * in addition to its standard set. * @param {Element} element? The element to set the class name on. Should default to * the control's element if not specified. */ Checkbox.prototype.setClasses = function (className, element) { this.dom.addClass(element || this.element, __Checkbox + " " + (className || '')); }; /** * Checks for checked attributes and handles them accordingly. Also, * initializes the mark and adds a listener for the tap event. */ Checkbox.prototype.loaded = function () { _super.prototype.loaded.call(this); var optionObj = this.options || {}, options = optionObj.value || {}, previousType = this._targetType, mark = this._targetType = options.mark || 'check'; switch (mark.toLowerCase()) { case 'check': case 'x': break; default: this._log.debug("Invalid mark option specified for " + this.type + ". Defaulting to checkmark."); this._targetType = 'check'; break; } if (this._targetTypeSet) { var target = this._targetElement; this.dom.removeClass(target, previousType); this._activate(target); } this._targetTypeSet = true; }; /** * A function to activate the given element by toggling the * class specified as the target type. * @param {Element} element The element to activate. */ Checkbox.prototype._activate = function (element) { if (this._targetTypeSet) { this.dom.toggleClass(element, __Plat + this._targetType); return; } this._targetTypeSet = true; }; return Checkbox; }(Toggle)); platui.Checkbox = Checkbox; plat.register.control(__Checkbox, Checkbox); /** * An IBindablePropertyControl that standardizes the HTML5 radio button. */ var Radio = /** @class */ (function (_super) { __extends(Radio, _super); function Radio() { var _this = _super !== null && _super.apply(this, arguments) || this; /** * The HTML template represented as a string. */ _this.templateString = '<div class="plat-radio-container">\n' + ' <div class="plat-mark"></div>\n' + '</div>\n'; /** * The radio groups name if a radio group is present. */ _this.groupName = ''; /** * The check type to be placed in the element. */ _this._targetType = 'bullet'; /** * Whether the target type has been set already or not. */ _this._targetTypeSet = true; return _this; } /** * Sets the classes on the proper elements. * @param {string} className? An optional, additional class name or class names to set on the control * in addition to its standard set. * @param {Element} element? The element to set the class name on. Should default to * the control's element if not specified. */ Radio.prototype.setClasses = function (className, element) { this.dom.addClass(element || this.element, __Radio + " " + (className || '')); }; /** * Checks for a radio group and converts "checked" attributes. */ Radio.prototype.loaded = function () { var element = this.element; this._targetElement = element.firstElementChild; this.addEventListener(element, __$tap, this._onTap); if (element.hasAttribute(__NAME_ATTRIBUTE)) { this.groupName = element.getAttribute(__NAME_ATTRIBUTE); } else if (!this.utils.isNull(this.attributes[__CamelBind])) { this.groupName = this.attributes[__CamelBind]; } this._convertChecked(); }; /** * Checks if the radio has been selected and only notifies of a bindable * property changed if it has. * @param {any} newValue? The new value of the property after the change. * @param {any} oldValue? The old value of the property prior to the change. */ Radio.prototype.inputChanged = function (newValue, oldValue) { if (this.isActive) { _super.prototype.inputChanged.call(this, this._getValue()); } }; /** * The function called when the bindable property is set externally. * @param {any} newValue The new value of the bindable property. * @param {any} oldValue The old value of the bindable property. * @param {string} identifier The identifier of the property being observed. * @param {boolean} setProperty? A boolean value indicating whether we should set * the property if we need to toggle the mark. */ Radio.prototype._setBoundProperty = function (newValue, oldValue, identifier, setProperty) { var utils = this.utils; if (newValue === oldValue) { return; } else if (setProperty === true && utils.isNull(newValue)) { this.inputChanged(); return; } var value = this._getValue(), isChecked = newValue === value, wasChecked = this.isActive; if (isChecked) { if (wasChecked) { return; } } else if (utils.isNull(newValue)) { if (!wasChecked) { return; } } else { var newValueStr = utils.isFunction(newValue.toString) ? newValue.toString() : Object.prototype.toString.call(newValue); if (wasChecked) { if (newValueStr === value) { return; } } else { if (newValueStr !== value) { return; } } } this._toggle(setProperty); }; /** * The callback for a tap event. Only fires the event if the Radio * has been selected. * @param {plat.ui.IGestureEvent} ev The tap event object. */ Radio.prototype._onTap = function (ev) { if (this.isActive) { return; } _super.prototype._onTap.call(this, ev); }; /** * Toggles the mark and updates the bindable property if needed. * @param {boolean} setProperty? A boolean value stating whether the bindable * property should be updated. */ Radio.prototype._toggle = function (setProperty) { var _this = this; _super.prototype._toggle.call(this, setProperty); if (this.utils.isFunction(this._removeListener)) { this._removeListener(); this._removeListener = null; } if (this.isActive) { var name_1 = this.groupName; this.dispatchEvent(__RadioPrefix + name_1, plat.events.EventManager.DIRECT); var remover_1 = this._removeListener = this.on(__RadioPrefix + name_1, function () { _this._toggle(); remover_1(); }); } }; /** * A function for handling the attribute value conversion for updating the * bound property. * @param {any} newValue The newValue of the attribute to convert. * @param {any} oldValue? The oldValue of the attribute to convert. */ Radio.prototype._convertAttribute = function (newValue, oldValue) { var utils = this.utils; if (utils.isBoolean(newValue)) { if (newValue) { this._setBoundProperty(this._getValue(), null, null, true); } return; } else if (!utils.isString(newValue)) { return; } if (newValue === 'true') { this._setBoundProperty(this._getValue(), null, null, true); } }; /** * Grabs the value of this Radio's bindable property. It first checks for * the "value" attribute, and defaults to the elements textContent if it's unavailable. */ Radio.prototype._getValue = function () { var element = this.element; return element.hasAttribute('value') ? element.getAttribute('value').trim() : element.textContent.trim(); }; return Radio; }(Checkbox)); platui.Radio = Radio; plat.register.control(__Radio, Radio); /** * An ITemplateControl for showing indeterminate progress. */ var ProgressRing = /** @class */ (function (_super) { __extends(ProgressRing, _super); function ProgressRing() { var _this = _super !== null && _super.apply(this, arguments) || this; /** * The HTML template represented as a string. */ _this.templateString = '<div class="plat-animated-ring"></div>'; return _this; } /** * Sets the classes on the proper elements. * @param {string} className? An optional, additional class name or class names to set on the control * in addition to its standard set. * @param {Element} element? The element to set the class name on. Should default to * the control's element if not specified. */ ProgressRing.prototype.setClasses = function (className, element) { this.dom.addClass(element || this.element, __ProgressRing + " " + (className || '')); }; /** * Set the class name. */ ProgressRing.prototype.initialize = function () { this.setClasses(); }; /** * Set the animation. */ ProgressRing.prototype.loaded = function () { var options = this.options, utils = this.utils, isObject = utils.isObject, style = 0; if (isObject(options) && isObject(options.value)) { style = options.value.style; if (!utils.isNumber(style)) { style = 0; } } this.dom.addClass(this.element, __ProgressRing + "-" + style); if (style === 0) { return; } this._addAnimatedElements(style); }; /** * Adds any needed DOM for the animation. */ ProgressRing.prototype._addAnimatedElements = function (style) { var _document = plat.acquire(__Document), fragment = _document.createDocumentFragment(), count = style === 2 ? 12 : 4, div = 'div', classPrefix = __Plat + "animated-child " + __Plat + "animated-child-", child; for (var i = 0; i < count; ++i) { child = _document.createElement(div); child.className = classPrefix + i; fragment.insertBefore(child, null); } this.element.firstElementChild.insertBefore(fragment, null); }; return ProgressRing; }(plat.ui.TemplateControl)); platui.ProgressRing = ProgressRing; plat.register.control(__ProgressRing, ProgressRing); /** * An ITemplateControl for showing incremental progress. */ var ProgressBar = /** @class */ (function (_super) { __extends(ProgressBar, _super); function ProgressBar() { var _this = _super !== null && _super.apply(this, arguments) || this; /** * The HTML template represented as a string. */ _this.templateString = '<div class="plat-progress-container">\n' + ' <div class="plat-animated-bar"></div>\n' + '</div>\n'; /** * A function that will stop listening for visibility if applicable. */ _this._removeVisibilityListener = noop; return _this; } /** * Sets the classes on the proper elements. * @param {string} className? An optional, additional class name or class names to set on the control * in addition to its standard set. * @param {Element} element? The element to set the class name on. Should default to * the control's element if not specified. */ ProgressBar.prototype.setClasses = function (className, element) { this.dom.addClass(element || this.element, __ProgressBar + " " + (className || '')); }; /** * Set the class name. */ ProgressBar.prototype.initialize = function () { this.setClasses(); }; /** * Grabs the bar element then sets any initial progress. */ ProgressBar.prototype.loaded = function () { var _this = this; this._barElement = this.element.firstElementChild.firstElementChild; this.addEventListener(this._window, 'resize', function () { _this.setProgress(_this.context); }); this.setProgress(this.context); }; /** * Removes the visibility listener if applicable. */ ProgressBar.prototype.dispose = function () { this._removeVisibilityListener(); }; /** * Animates the bar on a context changed. */ ProgressBar.prototype.contextChanged = function () { this.setProgress(this.context); }; /** * Sets the progress bar value. * @param {number} value The decimal number between 0 and 1 to set as the * bar percentage (e.g. - 0.5 would be 50% complete). */ ProgressBar.prototype.setProgress = function (value) { var _this = this; return new this._Promise(function (resolve, reject) { if (!_this.utils.isNumber(value) || value > 1 || value < 0) { var msg = "The value of a \"" + _this.type + "\" control must be a number between 0 and 1."; _this._log.debug(msg); reject(msg); return; } var barElement = _this._barElement, barMax = barElement.parentElement.clientWidth; if (!barMax) { _this._removeVisibilityListener(); _this._removeVisibilityListener = _this.dom.whenVisible(function () { _this.setProgress(value).then(resolve); }, _this.element); return; } _this._animator.animate(barElement, __Transition, { properties: { width: Math.ceil(barMax * value) + "px" } }).then(function () { resolve(); }); }); }; ProgressBar._inject = { _window: __Window, _Promise: __Promise, _animator: __Animator }; return ProgressBar; }(plat.ui.TemplateControl)); platui.ProgressBar = ProgressBar; plat.register.control(__ProgressBar, ProgressBar); /** * An BindControl that acts as a global drawer. */ var Drawer = /** @class */ (function (_super) { __extends(Drawer, _super); /** * The constructor for a Drawer. Creates the ready Promise. */ function Drawer() { var _this = _super.call(this) || this; /** * References to all the DrawerControllers used to control this Drawer. */ _this._controllers = []; /** * Whether or not the this control has been paired with a corresponding Drawer. */ _this._isInitialized = false; /** * A bound value that may have come through prior to initialization. */ _this._preInitializedValue = false; /** * A private variable that tells the Drawer its last open or closed state. */ _this.__state = false; /** * A private variable that tells the Drawer its next open or closed state. */ _this.__nextState = false; _this.ready = _this._Promise.resolve(); return _this; } /** * Sets the classes on the proper elements. * @param {string} className? An optional, additional class name or class names to set on the control * in addition to its standard set. * @param {Element} element? The element to set the class name on. Should default to * the control's element if not specified. */ Drawer.prototype.setClasses = function (className, element) { this.dom.addClass(element || this.element, __Drawer + " " + (className || '')); }; /** * Set the class name and hides the element and * removes the innerHTML from the DOM and saves it. */ Drawer.prototype.initialize = function () { this.setClasses(); }; /** * Removes the innerHTML from the DOM and saves it. */ Drawer.prototype.setTemplate = function () { this.innerTemplate = this.dom.appendChildren(this.element.childNodes); }; /** * Check for a position and initialize event handling. */ Drawer.prototype.loaded = function () { var _this = this; var element = this.element, utils = this.utils, optionObj = this.options || {}, options = optionObj.value || {}, position = this._currentPosition = options.position || 'left', id = options.id || '', templateUrl = options.templateUrl, isElastic = options.elastic === true; element.setAttribute(__Hide, ''); this.dom.addClass(element, __Plat + position); if (utils.isString(templateUrl)) { plat.ui.TemplateControl.determineTemplate(this, templateUrl).then(function (template) { _this.innerTemplate = template; _this._initializeEvents(id, position, isElastic); }); return; } this._initializeEvents(id, position, isElastic); }; /** * Opens the Drawer. */ Drawer.prototype.open = function () { var controller = this._controllers[0]; if (this.utils.isNull(controller)) { this._log.debug("No controller, such as a " + __DrawerController + ", found for the " + this.type + " attempting to open."); return this._Promise.resolve(); } return controller.open(); }; /** * Closes the Drawer. */ Drawer.prototype.close = function () { var controller = this._controllers[0]; if (this.utils.isNull(controller)) { this._log.debug("No controller, such as a " + __DrawerController + ", found for the " + this.type + " attempting to close."); return this._Promise.resolve(); } return controller.close(); }; /** * Toggles the Drawer's open/closed state. */ Drawer.prototype.toggle = function () { var controller = this._controllers[0]; if (this.utils.isNull(controller)) { this._log.debug("No controller, such as a " + __DrawerController + ", found for the " + this.type + " attempting to toggle."); return this._Promise.resolve(); } return controller.toggle(); }; /** * Indicates whether the Drawer is currently open. */ Drawer.prototype.isOpen = function () { var controller = this._controllers[0]; if (this.utils.isNull(controller)) { this._log.debug("No controller, such as a " + __DrawerController + ", found for the " + this.type + " attempting to check if open."); return false; } return controller.isOpen(); }; /** * Adds and binds the added HTML template to this control's inherited context. * @param {string} name The template name to both add and bind. * @param {Node} node The node to add as a bindable template. */ Drawer.prototype.bindTemplate = function (name, node) { var _this = this; var bindableTemplates = this.bindableTemplates; bindableTemplates.add(name, node); return bindableTemplates.bind(name).then(function (template) { var element = _this.element; _this.dom.clearNode(element); element.appendChild(template); }).catch(function (error) { _this._log.debug("Error binding template for " + _this.type + ": " + error); }); }; /** * Returns the number of DrawerControllers linked to this * Drawer. */ Drawer.prototype.controllerCount = function () { return this._controllers.length; }; /** * Removes a specified DrawerController from this control's Array of * linked DrawerControllers. * @param {platui.DrawerController} controller The DrawerController * to splice. */ Drawer.prototype.spliceController = function (controller) { var controllers = this._controllers, index = controllers.indexOf(controller); if (index === -1) { return; } this.__state = this.__nextState = controllers[index].isOpen(); controllers.splice(index, 1); }; /** * A function that allows this control to observe both the bound property itself as well as * potential child properties if being bound to an object. * @param {plat.observable.IImplementTwoWayBinding} binder The control that facilitates the * databinding. */ Drawer.prototype.observeProperties = function (binder) { binder.observeProperty(this._setBoundProperty); }; /** * The function called when the bindable property is set externally. * @param {boolean} newValue The new value of the control state. * @param {boolean} oldValue The old value of the bindable control state. * @param {void} identifier The child identifier of the property being observed. * @param {boolean} firstTime? Whether or not this is the first call to bind the property. */ Drawer.prototype._setBoundProperty = function (newValue, oldValue, identifier, firstTime) { var utils = this.utils, controller = this._controllers[0]; if (firstTime === true && utils.isNull(newValue)) { this.inputChanged(utils.isNull(controller) ? false : controller.isOpen()); return; } var drawerState = !!newValue; if (drawerState !== newValue) { this.inputChanged(drawerState); } if (!this._isInitialized) { this._preInitializedValue = drawerState; } else if (utils.isNull(controller)) { this.__nextState = drawerState; } else if (drawerState) { if (controller.isOpen()) { return; } controller.open(); } else if (controller.isOpen()) { controller.close(); } }; /** * Changes the placement and implied position of the Drawer. * @param {string} position The new position to change to. */ Drawer.prototype._changeDirection = function (position) { if (this.utils.isNull(position) || position === this._currentPosition) { return; } var dom = this.dom, element = this.element; dom.removeClass(element, __Plat + this._currentPosition); dom.addClass(element, __Plat + position); this._currentPosition = position; }; /** * Initializes and dispatches pub sub events. * @param {string} id The ID of this Drawer if used. * @param {string} position The position. * @param {boolean} isElastic Whether or not the Drawer has an * elastic transition effect. */ Drawer.prototype._initializeEvents = function (id, position, isElastic) { var _this = this; var utils = this.utils, innerTemplate = this.innerTemplate; this.on(__DrawerControllerFetchEvent + "_" + id, function (event, controllerArg) { var control = controllerArg.control; if (utils.isNull(control)) { return; } if (utils.isString(controllerArg.position)) { position = controllerArg.position; _this._changeDirection(position); } _this._controllers.unshift(control); if (!controllerArg.received) { _this.ready.then(function () { _this.dispatchEvent(__DrawerFoundEvent + "_" + id, plat.events.EventManager.DIRECT, { control: _this, received: true, position: position, template: utils.isNode(innerTemplate) ? innerTemplate.cloneNode(true) : null, elastic: isElastic, state: _this.__state, nextState: _this.__nextState }); }); } _this._isInitialized = true; if (!controllerArg.useContext) { _this.bindTemplate('drawer', innerTemplate.cloneNode(true)).then(function () { _this._checkPreInit(); }); return; } _this._checkPreInit(); }); this.dispatchEvent(__DrawerFoundEvent + "_" + id, plat.events.EventManager.DIRECT, { control: this, received: false, position: position, template: utils.isNode(innerTemplate) ? innerTemplate.cloneNode(true) : null, elastic: isElastic, state: this.__state, nextState: this.__nextState }); }; /** * Checks the pre-initialized value and handles accordingly. */ Drawer.prototype._checkPreInit = function () { var _this = this; if (this._preInitializedValue) { var utils_1 = this.utils; utils_1.postpone(function () { var controller = _this._controllers[0]; if (!utils_1.isNull(controller)) { controller.open(); } }); } }; Drawer._inject = { _Promise: __Promise }; return Drawer; }(plat.ui.BindControl)); platui.Drawer = Drawer; plat.register.control(__Drawer, Drawer); /** * An BindControl that manipulates and controls a global drawer. */ var DrawerController = /** @class */ (function (_super) { __extends(DrawerController, _super); function DrawerController() { var _this = _super !== null && _super.apply(this, arguments) || this; /** * Whether or not the user has swiped. */ _this._hasSwiped = false; /** * Whether or not the user has tapped. */ _this._hasTapped = false; /** * Whether or not the Drawer is open. */ _this._isOpen = false; /** * An enum denoting the current touch state of the user. */ _this._touchState = 0; /** * Whether the corresponding Drawer is vertical or horizontal. */ _this._isVertical = false; /** * A function for removing the click eater scroll listening event. */ _this._removeClickEaterListener = noop; /** * A function to remove the toggle delay if present. */ _this._toggleDelay = noop; /** * Whether or not the this control has been paired with a corresponding Drawer. */ _this._isInitialized = false; return _this; } /** * Sets the classes on the proper elements. * @param {string} className? An optional, additional class name or class names to set on the control * in addition to its standard set. * @param {Element} element? The element to set the class name on. Should default to * the control's element if not specified. */ DrawerController.prototype.setClasses = function (className, element) { this.dom.addClass(element || this.element, __DrawerController + " " + (className || '')); }; /** * Sets the class name on the element. */ DrawerController.prototype.initialize = function () { this.dom.addClass(this.element, __DrawerController); }; /** * Initialize the track events on the element. */ DrawerController.prototype.loaded = function () { var optionObj = this.options || {}, options = optionObj.value || {}, position = options.position, id = options.id || ''; this._type = options.type || 'tap track'; this._isElastic = options.elastic; this._useContext = options.useContext === true; this._templateUrl = options.templateUrl; this._initializeEvents(id, position); }; /** * Remove the transition classes off the root element and reset the position and * zIndex properties if modified and only if this is the last DrawerController * referencing this Drawer. */ DrawerController.prototype.dispose = function () { var _this = this; _super.prototype.dispose.call(this); var drawer = this._drawer; if (this.utils.isNull(drawer)) { return; } if (drawer.controllerCount() > 1) { drawer.spliceController(this); return; } else if (this._isOpen) { drawer.ready = this.close().then(function () { drawer.spliceController(_this); if (drawer.controllerCount() > 0) { return; } _this._cleanRootElement(); }); return;