/* * WinJS Contrib v2.1.0.6 * licensed under MIT license (see http://opensource.org/licenses/MIT) * sources available at https://github.com/gleborgne/winjscontrib */ /// <reference path="winjscontrib.core.js" /> (function () { 'use strict'; function debugLog(msg) { console.log(msg); } WinJS.Namespace.define("WinJSContrib.UI", { parentFlyoutPage: function (element) { if (!element) return null; var current = element.parentNode; while (current) { if (current.mcnFlyoutPage) { return current.winControl; } current = current.parentNode; } }, FlyoutPageTrigger: WinJS.Class.define(function (element, options) { var ctrl = this; ctrl.element = element || document.createElement('DIV'); options = options || {}; ctrl.element.classList.add('win-disposable'); WinJS.UI.setOptions(this, options); WinJSContrib.UI.tap(ctrl.element, function () { ctrl.openFlyout(); }, options.tapOptions); }, { openFlyout: function () { if (this.flyoutpage && this.flyoutpage.winControl) this.flyoutpage.winControl.show(); } }), FlyoutPage: WinJS.Class.mix(WinJS.Class.define( /** * @classdesc * display html content or target html fragment as a sidebar flyout page * @class WinJSContrib.UI.FlyoutPage * @param {HTMLElement} element DOM element containing the control * @param {Object} options */ function ctor(element, options) { var ctrl = this; ctrl.eventTracker = new WinJSContrib.UI.EventTracker(); ctrl.element = element || document.createElement('DIV'); options = options || {}; ctrl.element.mcnFlyoutPage = true; ctrl.element.winControl = ctrl; ctrl.element.classList.add('mcn-flyoutpage'); ctrl.element.classList.add('mcn-navigation-ctrl'); ctrl.element.classList.add('mcn-flyout'); ctrl.element.classList.add('win-disposable'); ctrl.hardwareBackBtnPressedBinded = ctrl.hardwareBackBtnPressed.bind(ctrl); //ctrl.cancelNavigationBinded = ctrl.cancelNavigation.bind(ctrl); ctrl._container = document.createElement('DIV'); ctrl._container.className = 'mcn-flyoutpage-area'; ctrl._overlay = document.createElement('DIV'); ctrl._overlay.className = 'mcn-flyoutpage-overlay'; ctrl._overlay.innerHTML = '<DIV class="mcn-flyoutpage-overlay-bg"></DIV>' ctrl._container.appendChild(ctrl._overlay); WinJSContrib.UI.tap(ctrl._overlay, function () { ctrl.hide(); }, { disableAnimation: true }); ctrl._wrapper = document.createElement('DIV'); ctrl._wrapper.className = 'mcn-flyoutpage-contentwrapper'; ctrl._container.appendChild(ctrl._wrapper); ctrl._wrapperArea = document.createElement('DIV'); ctrl._wrapperArea.className = 'mcn-flyoutpage-contentwrapperarea'; ctrl._wrapper.appendChild(ctrl._wrapperArea); ctrl._bg = document.createElement('DIV'); ctrl._bg.className = 'mcn-flyoutpage-bg'; ctrl._wrapperArea.appendChild(ctrl._bg); ctrl._content = document.createElement('DIV'); ctrl._content.className = 'mcn-flyoutpage-content'; ctrl._wrapperArea.appendChild(ctrl._content); if (options.edgeSwipe && WinJSContrib.UI.SwipeSlide) { debugLog('flyout page edge swipe'); ctrl.edgeSwipeCtrl = new WinJSContrib.UI.SwipeSlide(null, { moveDivider: 1, threshold: 4, allowed: { left: false, right: false } }); ctrl.edgeSwipeCtrl.element.classList.add('mcn-edgeswipe'); document.body.appendChild(ctrl.edgeSwipeCtrl.element); ctrl.eventTracker.addEvent(ctrl.edgeSwipeCtrl, 'swipestart', function (arg) { ctrl._edgeSwipeStart(arg); }); ctrl.eventTracker.addEvent(ctrl.edgeSwipeCtrl, 'swipe', function (arg) { ctrl._edgeSwipeCompleted(arg); }); } if (options.swipeToClose && WinJSContrib.UI.SwipeSlide) { debugLog('flyout page swipe to close'); ctrl.swipeToCloseCtrl = new WinJSContrib.UI.SwipeSlide(ctrl._wrapperArea, { moveDivider: 1, allowed: { left: false, right: false } }); ctrl.eventTracker.addEvent(ctrl.swipeToCloseCtrl, 'swipe', function (arg) { ctrl._swipeToCloseCompleted(arg); }); } WinJS.UI.setOptions(this, options); if (!ctrl.enterAnimation) ctrl.enterAnimation = options.enterAnimation || WinJS.UI.Animation.enterPage; if (!ctrl.exitAnimation) ctrl.exitAnimation = options.exitAnimation || WinJS.UI.Animation.exitPage; if (options.uri) { new WinJS.UI.HtmlControl(ctrl._content, { uri: options.uri }, function (elt) { ctrl.contentCtrl = elt; WinJSContrib.UI.bindMembers(elt.element, elt); elt.flyoutPage = ctrl; ctrl.bindLinks(); }); } else { WinJSContrib.Utils.moveChilds(ctrl.element, ctrl._content); ctrl.bindLinks(); } ctrl.element.appendChild(ctrl._container); ctrl._swipeTargets(); if (!ctrl.display) ctrl.display = 'overlay'; }, /** * @lends WinJSContrib.UI.FlyoutPage.prototype */ { /** * @field * @type HTMLElement */ content: { get: function () { return this._content; } }, /** * @field * @type HTMLElement */ display: { get: function () { return this._display; }, set: function (value) { var val = 'overlay'; if (value == 'move') val = 'move'; this.element.classList.remove('mcn-overlay'); this.element.classList.remove('mcn-move'); this.element.classList.add('mcn-' + val); this._display = val; this._swipeTargets(); } }, /** * left | right | top | bottom * @field * @type string */ placement: { get: function () { return this._placement; }, set: function (value) { var ctrl = this; this._placement = value; if (this._placement == 'right') { if (ctrl.edgeSwipeCtrl) { ctrl.edgeSwipeCtrl.allowed.left = true; ctrl.edgeSwipeCtrl.element.classList.remove('mcn-edgeswipe-left'); ctrl.edgeSwipeCtrl.element.classList.add('mcn-edgeswipe-right'); } if (ctrl.swipeToCloseCtrl) ctrl.swipeToCloseCtrl.allowed.right = true; ctrl.element.classList.add('partial-right'); if (!ctrl.enterAnimation) { ctrl.enterAnimation = function (elements) { return WinJSContrib.UI.Animation.slideFromRight(elements, { duration: 300 }) }; } if (!ctrl.exitAnimation) { ctrl.exitAnimation = function (elements) { return WinJSContrib.UI.Animation.slideToRight(elements, { duration: 120 }) }; } } else if (this._placement == 'left') { if (ctrl.edgeSwipeCtrl) { ctrl.edgeSwipeCtrl.allowed.right = true; ctrl.edgeSwipeCtrl.element.classList.remove('mcn-edgeswipe-right'); ctrl.edgeSwipeCtrl.element.classList.add('mcn-edgeswipe-left'); } if (ctrl.swipeToCloseCtrl) ctrl.swipeToCloseCtrl.allowed.left = true; ctrl.element.classList.add('partial-left'); if (!ctrl.enterAnimation) { ctrl.enterAnimation = function (elements) { return WinJSContrib.UI.Animation.slideFromLeft(elements, { duration: 300 }) }; } if (!ctrl.exitAnimation) { ctrl.exitAnimation = function (elements) { return WinJSContrib.UI.Animation.slideToLeft(elements, { duration: 120 }) }; } } else if (this._placement == 'bottom') { ctrl.element.classList.add('partial-bottom'); if (!ctrl.enterAnimation) { ctrl.enterAnimation = function (elements) { return WinJSContrib.UI.Animation.slideFromBottom(elements, { duration: 300 }) }; } if (!ctrl.exitAnimation) { ctrl.exitAnimation = function (elements) { return WinJSContrib.UI.Animation.slideToBottom(elements, { duration: 120 }) }; } } else if (this._placement == 'top') { ctrl.element.classList.add('partial-top'); if (!ctrl.enterAnimation) { ctrl.enterAnimation = function (elements) { return WinJSContrib.UI.Animation.slideFromTop(elements, { duration: 300 }) }; } if (!ctrl.exitAnimation) { ctrl.exitAnimation = function (elements) { return WinJSContrib.UI.Animation.slideToTop(elements, { duration: 120 }) }; } } } }, hardwareBackBtnPressed: function (arg) { var ctrl = this; var idx = WinJSContrib.UI.FlyoutPage.openPages.indexOf(ctrl); if (idx == WinJSContrib.UI.FlyoutPage.openPages.length - 1) { ctrl.hide(); arg.handled = true; if (arg.preventDefault) arg.preventDefault(); } }, //cancelNavigation: function (args) { // //this.eventTracker.addEvent(nav, 'beforenavigate', this._beforeNavigate.bind(this)); // var p = new WinJS.Promise(function (c) { }); // args.detail.setPromise(p); // setImmediate(function () { // p.cancel(); // }); //}, addContentElement: function (element) { var ctrl = this; ctrl._content.appendChild(element); }, pick: function (url, options) { var ctrl = this; options = options || {}; options.uri = url; var p = new WinJS.Promise(function (complete, error) { new WinJS.UI.HtmlControl(ctrl._content, options, function (elt) { ctrl.contentCtrl = elt; elt.close = function (result) { ctrl.hide(result); } elt.flyoutPage = ctrl; WinJSContrib.UI.bindMembers(elt.element, elt); ctrl.bindLinks(); ctrl.show(); ctrl.onbeforehide = function () { ctrl.onbeforehide = null; var result = ctrl.result; setImmediate(function () { complete(result); }); }; ctrl.onafterhide = function () { ctrl.onafterhide = null; WinJS.Utilities.disposeSubTree(ctrl._content); if (ctrl.contentCtrl.unload) { ctrl.contentCtrl.unload(); } ctrl.contentCtrl = null; ctrl._content.innerHTML = ''; }; }); }); return p; }, registerBack: function () { var ctrl = this; if (ctrl.edgeSwipeCtrl) { ctrl.edgeSwipeCtrl.disabled = true; } ctrl.navEventsHandler = WinJSContrib.UI.registerNavigationEvents(ctrl, this.hardwareBackBtnPressedBinded); //WinJS.Navigation.addEventListener('beforenavigate', this.cancelNavigationBinded); //if (window.Windows && window.Windows.Phone) // Windows.Phone.UI.Input.HardwareButtons.addEventListener("backpressed", this.hardwareBackBtnPressedBinded); //else // document.addEventListener("backbutton", this.hardwareBackBtnPressedBinded, true); }, //lockNavigation: function () { // if (WinJSContrib.UI.Application && WinJSContrib.UI.Application.navigator) // WinJSContrib.UI.Application.navigator.addLock(); //}, show: function () { var ctrl = this; if (ctrl.contentCtrl && ctrl.contentCtrl.beforeshow) { ctrl.contentCtrl.beforeshow(); } this.dispatchEvent("beforeshow"); ctrl.element.classList.add('visible'); ctrl._wrapper.classList.add('visible'); ctrl._wrapper.style.opacity = '0'; ctrl._overlay.style.opacity = '0'; ctrl._overlay.classList.add('visible'); ctrl.registerBack(); WinJSContrib.UI.Animation.fadeIn(ctrl._overlay, { duration: 400 }); var p = WinJS.Promise.wrap(); if (ctrl.contentCtrl && ctrl.contentCtrl.beforeShowContent) { p = WinJS.Promise.as(ctrl.contentCtrl.beforeShowContent()); } return p.then(function () { return WinJS.Promise.timeout(); }).then(function () { ctrl.calcAutosize(); return WinJS.Promise.timeout(); }).then(function () { return ctrl.enterAnimation(ctrl._wrapper); }).then(function () { WinJSContrib.UI.FlyoutPage.openPages.push(ctrl); if (ctrl.contentCtrl && ctrl.contentCtrl.aftershow) { ctrl.contentCtrl.aftershow(); } ctrl.dispatchEvent("aftershow"); //ctrl.lockNavigation(); }); }, calcAutosize: function () { var ctrl = this; if (ctrl.autosize) { var elt = ctrl.element.querySelector('.mcn-flyoutpage-content'); var wrapper = ctrl.element.querySelector('.mcn-flyoutpage-contentwrapper'); elt = elt.children[0]; if (ctrl.placement == 'top' || ctrl.placement == 'bottom') { var h = elt.clientHeight; wrapper.style.height = h + 'px'; } else if (ctrl.placement == 'left' || ctrl.placement == 'right') { var h = elt.clientWidth; wrapper.style.width = h + 'px'; } } }, hide: function (result) { var ctrl = this; ctrl.result = result; if (ctrl.contentCtrl && ctrl.contentCtrl.beforehide) { ctrl.contentCtrl.beforehide(); } this.dispatchEvent("beforehide"); this._removeNavigationLocks(); return WinJS.Promise.join([ctrl.exitAnimation(ctrl._wrapper), WinJSContrib.UI.Animation.fadeOut(ctrl._overlay, { duration: 200 })]).then(function () { return WinJS.Promise.timeout(100); }).then(function () { ctrl._wrapper.classList.remove('visible'); var wrapper = ctrl.element.querySelector('.mcn-flyoutpage-contentwrapper'); wrapper.style.width = ''; wrapper.style.height = ''; }).then(function () { var idx = WinJSContrib.UI.FlyoutPage.openPages.indexOf(ctrl); WinJSContrib.UI.FlyoutPage.openPages.splice(idx, 1); ctrl._wrapper.style.opacity = ''; ctrl._overlay.style.opacity = ''; ctrl._overlay.classList.remove('visible'); ctrl.element.classList.remove('visible'); if (ctrl.contentCtrl && ctrl.contentCtrl.afterhide) { ctrl.contentCtrl.afterhide(); } ctrl.dispatchEvent("afterhide"); }); }, _removeNavigationLocks: function () { var ctrl = this; if (ctrl.navEventsHandler) { ctrl.navEventsHandler(); ctrl.navEventsHandler = null; } //if (WinJSContrib.UI.Application && WinJSContrib.UI.Application.navigator) // WinJSContrib.UI.Application.navigator.removeLock(); //WinJS.Navigation.removeEventListener('beforenavigate', this.cancelNavigationBinded); //if (window.Windows && window.Windows.Phone) // Windows.Phone.UI.Input.HardwareButtons.removeEventListener("backpressed", this.hardwareBackBtnPressedBinded); //else // document.removeEventListener("backbutton", this.hardwareBackBtnPressedBinded); if (ctrl.edgeSwipeCtrl) { ctrl.edgeSwipeCtrl.disabled = false; } //if (ctrl.display == 'move') { // ctrl.element.parentElement.style.transform = ''; //} }, bindLinks: function () { var ctrl = this; var bindFlyout = function (elt) { var target = elt.dataset.flyout; if (target) { WinJSContrib.UI.tap(elt, function (eltarg) { var flyout = document.querySelector(target); if (flyout && flyout.winControl && flyout.winControl.show) { ctrl.element.style.zIndex = '500'; ctrl.hide().done(function () { ctrl.element.style.zIndex = ''; }); flyout.winControl.show(); } }); } } var flyouts = ctrl.element.querySelectorAll('*[data-flyout]'); for (var i=0, l=flyouts.length; i<l ; i++){ bindFlyout(flyouts[i]); } var bindLink = function (elt) { var target = elt.dataset.link; if (target && target.indexOf('/') < 0) { var tmp = WinJSContrib.Utils.readProperty(window, target); if (tmp) { target = tmp; } } if (target) { WinJSContrib.UI.tap(elt, function (eltarg) { var actionArgs = eltarg.dataset.linkArgs; if (actionArgs && typeof actionArgs == 'string') { try { var tmp = WinJSContrib.Utils.readValue(eltarg, actionArgs); if (tmp) { actionArgs = tmp; } else { actionArgs = JSON.parse(actionArgs); } } catch (exception) { return; } } ctrl.hide().then(function () { WinJS.Navigation.navigate(target, actionArgs); }); }); } } var links = ctrl.element.querySelectorAll('*[data-link]'); for (var i = 0, l = links.length; i < l ; i++) { bindLink(links[i]); } var bindAction = function (elt) { var actionName = elt.dataset.action; var action = ctrl._content.winControl[actionName]; if (action && typeof action === 'function') { WinJSContrib.UI.tap(elt, function (eltarg) { var actionArgs = eltarg.dataset.actionArgs; if (actionArgs && typeof actionArgs == 'string') { try { var tmp = WinJSContrib.Utils.readValue(eltarg, actionArgs); if (tmp) { actionArgs = tmp; } else { actionArgs = JSON.parse(actionArgs); } } catch (exception) { return; } } ctrl.hide().then(function () { ctrl._content.winControl[actionName].bind(ctrl._content.winControl)({ elt: eltarg, args: actionArgs }); }); }); } } var actions = ctrl.element.querySelectorAll('*[data-action]'); for (var i = 0, l = actions.length; i < l ; i++) { bindAction(actions[i]); } }, _swipeTargets: function () { var ctrl = this; if (ctrl.edgeSwipeCtrl) { if (ctrl.display == 'overlay') { ctrl.edgeSwipeCtrl.target = ctrl._container; } else if (ctrl.display == 'move') { ctrl.edgeSwipeCtrl.target = ctrl.element.parentElement; } } if (ctrl.swipeToCloseCtrl) { if (ctrl.display == 'overlay') { ctrl.swipeToCloseCtrl.target = ctrl._wrapperArea; } else if (ctrl.display == 'move') { ctrl.swipeToCloseCtrl.target = ctrl.element.parentElement; } } }, _edgeSwipeStart: function () { var ctrl = this; ctrl.edgeSwipeCtrl.minMoveBounds = null; ctrl.edgeSwipeCtrl.maxMoveBounds = null; if (ctrl.placement == 'right') { var bound = ctrl._content.clientWidth * -1; debugLog('minBounds ' + bound); ctrl.edgeSwipeCtrl.minMoveBounds = bound; } else if (ctrl.placement == 'left') { var bound = ctrl._content.clientWidth; debugLog('maxBounds ' + bound); ctrl.edgeSwipeCtrl.maxMoveBounds = bound; } }, _edgeSwipeCompleted: function (arg) { var ctrl = this; debugLog('swiped by ' + arg.move + '/' + arg.screenMove + ' ' + (document.body.clientWidth / 3)); if (Math.abs(arg.screenMove) > (document.body.clientWidth / 3)) { ctrl.edgeSwipeCtrl.swipeHandled = true; ctrl.element.classList.add('visible'); ctrl._wrapper.classList.add('visible'); if (ctrl.display == 'overlay') { ctrl.edgeSwipeCtrl.target.style.transform = ''; if (ctrl.edgeSwipeCtrl.target.style.hasOwnProperty('webkitTransform')) ctrl.edgeSwipeCtrl.target.style.webkitTransform = ''; if (ctrl.placement == 'right') { ctrl._wrapper.style.transform = 'translate(' + (document.body.clientWidth + arg.screenMove) + 'px, 0)'; } else if (ctrl.placement == 'left') { ctrl._wrapper.style.transform = 'translate(' + (arg.screenMove) + 'px, 0)'; } WinJS.UI.executeTransition(ctrl._wrapper, { property: "transform", delay: 10, duration: 600 * (1 - (document.body.clientWidth + arg.screenMove) / document.body.clientWidth), easing: 'ease-out', to: 'translate(0,0)' }); } else if (ctrl.display == 'move') { var bound = ctrl.edgeSwipeCtrl.minMoveBounds || ctrl.edgeSwipeCtrl.maxMoveBounds; WinJS.UI.executeTransition(ctrl.edgeSwipeCtrl.target, { property: "transform", delay: 10, duration: 600 * (1 - (document.body.clientWidth + arg.screenMove) / document.body.clientWidth), easing: 'ease-out', to: 'translate(' + bound + 'px,0)' }); } ctrl._overlay.style.opacity = '0'; ctrl._overlay.classList.add('visible'); WinJSContrib.UI.Animation.fadeIn(ctrl._overlay, { duration: 400 }); ctrl.registerBack(); //ctrl.lockNavigation(); } }, _swipeToCloseCompleted: function (arg) { var ctrl = this; var swiper = ctrl.swipeToCloseCtrl; debugLog('swiped back by ' + arg.move + '/' + arg.screenMove + ' ' + (document.body.clientWidth / 4) + '(' + swiper.swipeHandled + ')'); if (Math.abs(arg.screenMove) > (document.body.clientWidth / 4)) { swiper.swipeHandled = true; ctrl._removeNavigationLocks(); WinJSContrib.UI.Animation.fadeOut(ctrl._overlay, { duration: 300 }).then(function () { ctrl._overlay.classList.remove('visible'); }); if (ctrl.display == 'overlay') { var targetX = '0', targetY = '0'; if (ctrl.placement == 'right') { targetX = '100%'; } else if (ctrl.placement == 'left') { targetX = '-100%'; } WinJS.UI.executeTransition(ctrl._wrapper, { property: "transform", delay: 10, duration: 500 * (1 - (document.body.clientWidth - arg.screenMove) / document.body.clientWidth), easing: 'ease-out', to: 'translate(' + targetX + ',' + targetY + ')' }).then(function () { ctrl._wrapper.classList.remove('visible'); ctrl.element.classList.remove('visible'); return ctrl.hide(); }).then(function () { ctrl._wrapperArea.style.transform = ''; if (ctrl._wrapperArea.style.hasOwnProperty('webkitTransform')) ctrl._wrapperArea.style.webkitTransform = ''; }); } else if (ctrl.display == 'move') { WinJS.UI.executeTransition(ctrl.element.parentElement, { property: "transform", delay: 10, duration: 500 * (1 - (document.body.clientWidth - arg.screenMove) / document.body.clientWidth), easing: 'ease-out', to: 'translate(0,0)' }).then(function () { ctrl._wrapper.classList.remove('visible'); ctrl.element.classList.remove('visible'); return ctrl.hide(); }).then(function () { ctrl._wrapperArea.style.transform = ''; if (ctrl._wrapperArea.style.hasOwnProperty('webkitTransform')) ctrl._wrapperArea.style.webkitTransform = ''; }); } } }, dispose: function () { var ctrl = this; ctrl.eventTracker.dispose(); if (ctrl.edgeSwipeCtrl) { ctrl.edgeSwipeCtrl.dispose(); ctrl.edgeSwipeCtrl.element.parentElement.removeChild(ctrl.edgeSwipeCtrl.element); } if (ctrl.swipeToCloseCtrl) { ctrl.swipeToCloseCtrl.dispose(); } WinJS.Utilities.disposeSubTree(this.element); } }), WinJS.Utilities.eventMixin, WinJS.Utilities.createEventProperties("beforeshow", "beforehide", "aftershow", "afterhide")) }); WinJSContrib.UI.FlyoutPage.openPages = []; WinJS.Namespace.define("WinJSContrib.UI", { FlyoutPicker: WinJS.Class.mix(WinJS.Class.define(function ctor(element, options) { var ctrl = this; ctrl.element = element || document.createElement('DIV'); options = options || {}; ctrl.element.style.display = 'none'; ctrl.element.classList.add('mcn-flyoutpicker'); ctrl.element.classList.add('win-disposable'); ctrl.element.mcnFlyoutPage = true; ctrl.element.winControl = ctrl; ctrl.flyoutPage = new WinJSContrib.UI.FlyoutPage(null, options); var parentFlyoutPage = WinJSContrib.UI.parentFlyoutPage(element); if (parentFlyoutPage) { parentFlyoutPage.addContentElement(ctrl.flyoutPage.element); } else { document.body.appendChild(ctrl.flyoutPage.element); } }, { dispose: function () { var ctrl = this; ctrl.flyoutPage.element.parentElement.removeChild(ctrl.flyoutPage.element); ctrl.element.parentElement.removeChild(ctrl.element); ctrl.flyoutPage = null; }, addContentElement: function (element) { var ctrl = this; ctrl.flyoutPage.addContentElement(element); }, pick: function (url, options) { var ctrl = this; return ctrl.flyoutPage.pick(url, options); } }), WinJS.UI.DOMEventMixin, WinJS.Utilities.createEventProperties("")) }); })();