UNPKG

tizen-tau-wearable

Version:

Tizen Advanced UI Wearable

1,764 lines (1,618 loc) 840 kB
/* * Copyright (c) 2015 Samsung Electronics Co., Ltd * * Licensed under the Flora License, Version 1.1 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://floralicense.org/license/ * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ (function(window, document, undefined) { var ns = window.tau = {}, nsConfig = window.tauConfig = window.tauConfig || {}; nsConfig.rootNamespace = 'tau'; nsConfig.fileName = 'tau'; ns.version = '0.10.29-13'; /*global window, console, define, ns, nsConfig */ /*jslint plusplus:true */ /* * Copyright (c) 2015 Samsung Electronics Co., Ltd * * Licensed under the Flora License, Version 1.1 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://floralicense.org/license/ * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * #Core namespace * Object contains main framework methods. * @class ns * @author Maciej Urbanski <m.urbanski@samsung.com> * @author Krzysztof Antoszek <k.antoszek@samsung.com> * @author Maciej Moczulski <m.moczulski@samsung.com> * @author Piotr Karny <p.karny@samsung.com> * @author Tomasz Lukawski <t.lukawski@samsung.com> */ (function (document, ns, nsConfig) { var idNumberCounter = 0, currentDate = +new Date(), slice = [].slice, rootNamespace = nsConfig.rootNamespace, fileName = nsConfig.fileName, infoForLog = function (args) { var dateNow = new Date(); args.unshift('[' + rootNamespace + '][' + dateNow.toLocaleString() + ']'); }; /** * Return unique id * @method getUniqueId * @static * @return {string} * @member ns */ ns.getUniqueId = function () { return rootNamespace + "-" + ns.getNumberUniqueId() + "-" + currentDate; }; /** * Return unique id * @method getNumberUniqueId * @static * @return {number} * @member ns */ ns.getNumberUniqueId = function () { return idNumberCounter++; }; /** * logs supplied messages/arguments * @method log * @static * @param {...*} argument * @member ns */ ns.log = function () { var args = slice.call(arguments); infoForLog(args); if (console) { console.log.apply(console, args); } }; /** * logs supplied messages/arguments ad marks it as warning * @method warn * @static * @param {...*} argument * @member ns */ ns.warn = function () { var args = slice.call(arguments); infoForLog(args); if (console) { console.warn.apply(console, args); } }; /** * logs supplied messages/arguments and marks it as error * @method error * @static * @param {...*} argument * @member ns */ ns.error = function () { var args = slice.call(arguments); infoForLog(args); if (console) { console.error.apply(console, args); } }; /** * get from nsConfig * @method getConfig * @param {string} key * @param {*} defaultValue * @return {*} * @static * @member ns */ ns.getConfig = function (key, defaultValue) { return nsConfig[key] === undefined ? defaultValue : nsConfig[key]; }; /** * set in nsConfig * @method setConfig * @param {string} key * @param {*} value * @param {boolean} [asDefault=false] value should be treated as default (doesn't overwrites the config[key] if it already exists) * @static * @member ns */ ns.setConfig = function (key, value, asDefault) { if (!asDefault || (asDefault && nsConfig[key] === undefined)) { nsConfig[key] = value; } }; /** * Return path for framework script file. * @method getFrameworkPath * @returns {?string} * @member ns */ ns.getFrameworkPath = function () { var scripts = document.getElementsByTagName('script'), countScripts = scripts.length, i, url, arrayUrl, count; for (i = 0; i < countScripts; i++) { url = scripts[i].src; arrayUrl = url.split('/'); count = arrayUrl.length; if (arrayUrl[count - 1] === fileName + '.js' || arrayUrl[count - 1] === fileName + '.min.js') { return arrayUrl.slice(0, count - 1).join('/'); } } return null; }; }(window.document, ns, nsConfig)); /*global window, define, ns */ /* * Copyright (c) 2015 Samsung Electronics Co., Ltd * * Licensed under the Flora License, Version 1.1 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://floralicense.org/license/ * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /*jslint plusplus: true, nomen: true */ // * @TODO add support of $.mobile.buttonMarkup.hoverDelay /* * Defaults settings object * @author Maciej Urbanski <m.urbanski@samsung.com> * @class ns.defaults */ (function (ns) { ns.defaults = {}; Object.defineProperty(ns.defaults, "autoInitializePage", { get: function(){ return ns.getConfig("autoInitializePage", true); }, set: function(value){ return ns.setConfig("autoInitializePage", value); } }); Object.defineProperty(ns.defaults, "dynamicBaseEnabled", { get: function(){ return ns.getConfig("dynamicBaseEnabled", true); }, set: function(value){ return ns.setConfig("dynamicBaseEnabled", value); } }); Object.defineProperty(ns.defaults, "pageTransition", { get: function(){ return ns.getConfig("pageTransition", "none"); }, set: function(value){ return ns.setConfig("pageTransition", value); } }); Object.defineProperty(ns.defaults, "popupTransition", { get: function(){ return ns.getConfig("popupTransition", "none"); }, set: function(value){ return ns.setConfig("popupTransition", value); } }); Object.defineProperty(ns.defaults, "popupFullSize", { get: function(){ return ns.getConfig("popupFullSize", false); }, set: function(value){ return ns.setConfig("popupFullSize", value); } }); Object.defineProperty(ns.defaults, "enablePageScroll", { get: function(){ return ns.getConfig("enablePageScroll", false); }, set: function(value){ return ns.setConfig("enablePageScroll", value); } }); Object.defineProperty(ns.defaults, "scrollEndEffectArea", { get: function(){ return ns.getConfig("scrollEndEffectArea", "content"); }, set: function(value){ return ns.setConfig("scrollEndEffectArea", value); } }); Object.defineProperty(ns.defaults, "enablePopupScroll", { get: function(){ return ns.getConfig("enablePopupScroll", false); }, set: function(value){ return ns.setConfig("enablePopupScroll", value); } }); }(ns)); /*global window, define*/ /*jslint bitwise: true */ /* * Copyright (c) 2015 Samsung Electronics Co., Ltd * * Licensed under the Flora License, Version 1.1 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://floralicense.org/license/ * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * @author Maciej Urbanski <m.urbanski@samsung.com> * @author Piotr Karny <p.karny@samsung.com> */ (function (ns) { // Default configuration properties ns.setConfig('rootDir', ns.getFrameworkPath(), true); ns.setConfig('version', ''); ns.setConfig('allowCrossDomainPages', false, true); ns.setConfig('domCache', false, true); // .. other possible options // ns.setConfig('autoBuildOnPageChange', true); // ns.setConfig('autoInitializePage', true); // ns.setConfig('container', document.body); // for defining application container // ns.setConfig('pageContainer', document.body); // same as above, but for wearable version }(ns)); /*global window, define*/ /*jslint bitwise: true */ /* * Copyright (c) 2015 Samsung Electronics Co., Ltd * * Licensed under the Flora License, Version 1.1 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://floralicense.org/license/ * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @class ns.support * @author Maciej Urbanski <m.urbanski@samsung.com> */ (function (window, document, ns) { var isTizen = !(typeof tizen === "undefined"); function isCircleShape() { var testDiv = document.createElement("div"), fakeBody = document.createElement("body"), html = document.getElementsByTagName('html')[0], style = getComputedStyle(testDiv), isCircle; testDiv.classList.add("is-circle-test"); fakeBody.appendChild(testDiv); html.insertBefore(fakeBody, html.firstChild); isCircle = style.width === "1px"; html.removeChild(fakeBody); return isCircle; } ns.support = { cssTransitions: true, mediaquery: true, cssPseudoElement: true, touchOverflow: true, cssTransform3d: true, boxShadow: true, scrollTop: 0, dynamicBaseTag: true, cssPointerEvents: false, boundingRect: true, browser: { ie: false, tizen: isTizen }, shape: { circle: isTizen ? window.matchMedia("(-tizen-geometric-shape: circle)").matches : isCircleShape(), }, gradeA : function () { return true; } }; }(window, window.document, ns)); /*global window, define*/ /* * Copyright (c) 2015 Samsung Electronics Co., Ltd * * Licensed under the Flora License, Version 1.1 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://floralicense.org/license/ * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /*jslint bitwise: true */ /* * @author Piotr Karny <p.karny@samsung.com> */ (function (ns) { // Default configuration properties for wearable ns.setConfig("autoBuildOnPageChange", false, true); if(ns.support.shape.circle) { ns.setConfig("pageTransition", "pop"); ns.setConfig("popupTransition", "pop"); ns.setConfig("popupFullSize", true); ns.setConfig("scrollEndEffectArea", "screen"); ns.setConfig("enablePageScroll", true); ns.setConfig("enablePopupScroll", true); } else { ns.setConfig("popupTransition", "slideup"); ns.setConfig("enablePageScroll", false); ns.setConfig("enablePopupScroll", false); } // .. other possible options // ns.setConfig('autoInitializePage', true); // ns.setConfig('pageContainer', document.body); // defining application container for wearable }(ns)); /*global window, define, XMLHttpRequest, console, Blob */ /*jslint nomen: true, browser: true, plusplus: true */ /* * Copyright (c) 2015 Samsung Electronics Co., Ltd * * Licensed under the Flora License, Version 1.1 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://floralicense.org/license/ * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * #Utilities * * The Tizen Advanced UI (TAU) framework provides utilities for easy-developing * and fully replaceable with jQuery method. When user using these DOM and * selector methods, it provide more light logic and it proves performance * of web app. The following table displays the utilities provided by the * TAU framework. * * @class ns.util * @author Maciej Urbanski <m.urbanski@samsung.com> * @author Krzysztof Antoszek <k.antoszek@samsung.com> */ (function (window, document, ns) { var currentFrame = null, /** * requestAnimationFrame function * @method requestAnimationFrame * @static * @member ns.util */ requestAnimationFrame = (window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) { currentFrame = window.setTimeout(callback.bind(callback, +new Date()), 1000 / 60); }).bind(window), util = ns.util || {}, slice = [].slice; /** * fetchSync retrieves a text document synchronously, returns null on error * @param {string} url * @param {=string} [mime=""] Mime type of the resource * @return {string|null} * @static * @member ns.util */ function fetchSync(url, mime) { var xhr = new XMLHttpRequest(), status; xhr.open("get", url, false); if (mime) { xhr.overrideMimeType(mime); } xhr.send(); if (xhr.readyState === 4) { status = xhr.status; if (status === 200 || (status === 0 && xhr.responseText)) { return xhr.responseText; } } return null; } util.fetchSync = fetchSync; /** * Removes all script tags with src attribute from document and returns them * @param {HTMLElement} container * @return {Array.<HTMLElement>} * @private * @static * @member ns.util */ function removeExternalScripts(container) { var scripts = slice.call(container.querySelectorAll("script[src]")), i = scripts.length, script; while (--i >= 0) { script = scripts[i]; script.parentNode.removeChild(script); } return scripts; } /** * Evaluates code, reason for a function is for an atomic call to evaluate code * since most browsers fail to optimize functions with try-catch blocks, so this * minimizes the effect, returns the function to run * @param {string} code * @return {Function} * @static * @member ns.util */ function safeEvalWrap(code) { return function () { try { window.eval(code); } catch (e) { if (typeof console !== "undefined") { if (e.stack) { console.error(e.stack); } else if (e.name && e.message) { console.error(e.name, e.message); } else { console.error(e); } } } }; } util.safeEvalWrap = safeEvalWrap; /** * Calls functions in supplied queue (array) * @param {Array.<Function>} functionQueue * @static * @member ns.util */ function batchCall(functionQueue) { var i, length = functionQueue.length; for (i = 0; i < length; ++i) { functionQueue[i].call(window); } } util.batchCall = batchCall; /** * Creates new script elements for scripts gathered from a differnt document * instance, blocks asynchronous evaluation (by renaming src attribute) and * returns an array of functions to run to evalate those scripts * @param {Array.<HTMLElement>} scripts * @param {HTMLElement} container * @return {Array.<Function>} * @private * @static * @member ns.util */ function createScriptsSync(scripts, container) { var scriptElement, scriptBody, i, length, queue = []; // proper order of execution for (i = 0, length = scripts.length; i < length; ++i) { scriptBody = fetchSync(scripts[i].src, "text/plain"); if (scriptBody) { scriptElement = document.adoptNode(scripts[i]); scriptElement.setAttribute("data-src", scripts[i].src); scriptElement.removeAttribute("src"); // block evaluation queue.push(safeEvalWrap(scriptBody)); if (container) { container.appendChild(scriptElement); } } } return queue; } util.requestAnimationFrame = requestAnimationFrame; /** * cancelAnimationFrame function * @method cancelAnimationFrame * @return {Function} * @member ns.util * @static */ util.cancelAnimationFrame = (window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || window.oCancelAnimationFrame || window.msCancelAnimationFrame || function () { // propably wont work if there is any more than 1 // active animationFrame but we are trying anyway window.clearTimeout(currentFrame); }).bind(window); /** * Method make asynchronous call of function * @method async * @inheritdoc #requestAnimationFrame * @member ns.util * @static */ util.async = requestAnimationFrame; /** * Appends element from different document instance to current document in the * container element and evaluates scripts (synchronously) * @param {HTMLElement} element * @param {HTMLElement} container * @method importEvaluateAndAppendElement * @member ns.util * @static */ util.importEvaluateAndAppendElement = function (element, container) { var externalScriptsQueue = createScriptsSync(removeExternalScripts(element), element), newNode = document.importNode(element, true); container.appendChild(newNode); // append and eval inline batchCall(externalScriptsQueue); return newNode; }; /** * Checks if specified string is a number or not * @method isNumber * @return {boolean} * @member ns.util * @static */ util.isNumber = function (query) { var parsed = parseFloat(query); return !isNaN(parsed) && isFinite(parsed); }; /** * Reappend script tags to DOM structure to correct run script * @method runScript * @param {string} baseUrl * @param {HTMLScriptElement} script * @member ns.util * @deprecated 2.3 */ util.runScript = function (baseUrl, script) { var newScript = document.createElement("script"), scriptData = null, i, scriptAttributes = slice.call(script.attributes), src = script.getAttribute("src"), path = util.path, request, attribute, status; // 'src' may become null when none src attribute is set if (src !== null) { src = path.makeUrlAbsolute(src, baseUrl); } //Copy script tag attributes i = scriptAttributes.length; while (--i >= 0) { attribute = scriptAttributes[i]; if (attribute.name !== "src") { newScript.setAttribute(attribute.name, attribute.value); } else { newScript.setAttribute("data-src", attribute.value); } } if (src) { scriptData = fetchSync(src, "text/plain"); } else { scriptData = script.textContent; } if (scriptData) { // add the returned content to a newly created script tag newScript.src = URL.createObjectURL(new Blob([scriptData], {type: "text/javascript"})); newScript.textContent = scriptData; // for compatibility with some libs ex. templating systems } script.parentNode.replaceChild(newScript, script); }; ns.util = util; }(window, window.document, ns)); /*global window, define */ /* * Copyright (c) 2015 Samsung Electronics Co., Ltd * * Licensed under the Flora License, Version 1.1 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://floralicense.org/license/ * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * #Array Utility * Utility helps work with arrays. * @class ns.util.array */ (function (window, document, ns) { /** * Create an array containing the range of integers or characters * from low to high (inclusive) * @method range * @param {number|string} low * @param {number|string} high * @param {number} step * @static * @return {Array} array containing continous elements * @member ns.util.array */ function range(low, high, step) { // Create an array containing the range of integers or characters // from low to high (inclusive) // // version: 1107.2516 // discuss at: http://phpjs.org/functions/range // + original by: Waldo Malqui Silva // * example 1: range ( 0, 12 ); // * returns 1: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] // * example 2: range( 0, 100, 10 ); // * returns 2: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100] // * example 3: range( 'a', 'i' ); // * returns 3: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'] // * example 4: range( 'c', 'a' ); // * returns 4: ['c', 'b', 'a'] var matrix = [], inival, endval, plus, walker = step || 1, chars = false; if (!isNaN(low) && !isNaN(high)) { inival = low; endval = high; } else if (isNaN(low) && isNaN(high)) { chars = true; inival = low.charCodeAt(0); endval = high.charCodeAt(0); } else { inival = (isNaN(low) ? 0 : low); endval = (isNaN(high) ? 0 : high); } plus = inival <= endval; if (plus) { while (inival <= endval) { matrix.push((chars ? String.fromCharCode(inival) : inival)); inival += walker; } } else { while (inival >= endval) { matrix.push((chars ? String.fromCharCode(inival) : inival)); inival -= walker; } } return matrix; } /** * Check object is arraylike (arraylike include array and * collection) * @method isArrayLike * @param {Object} object * @return {boolean} Whether arraylike object or not * @member ns.util.array * @static */ function isArrayLike(object) { var type = typeof object, length = object && object.length; // if object exists and is different from window // window object has length property if (object && object !== object.window) { // If length value is not number, object is not array and collection. // Collection type is not array but has length value. // e.g) Array.isArray(document.childNodes) ==> false return Array.isArray(object) || object instanceof NodeList || type === "function" && (length === 0 || typeof length === "number" && length > 0 && (length - 1) in object); } return false; } /** * Faster version of standard forEach method in array * Confirmed that this method is 20 times faster then native * @method forEach * @param {Array} array * @param {Function} callback * @member ns.util.array * @static */ function forEach(array, callback) { var i, length; if (!(array instanceof Array)) { array = [].slice.call(array); } length = array.length; for (i = 0; i < length; i++) { callback(array[i], i, array); } } /** * Faster version of standard filter method in array * @method filter * @param {Array} array * @param {Function} callback * @member ns.util.array * @static */ function filter(array, callback) { var result = [], i, length, value; if (!(array instanceof Array)) { array = [].slice.call(array); } length = array.length; for (i = 0; i < length; i++) { value = array[i]; if (callback(value, i, array)) { result.push(value); } } return result; } /** * Faster version of standard map method in array * Confirmed that this method is 60% faster then native * @method map * @param {Array} array * @param {Function} callback * @member ns.util.array * @static */ function map(array, callback) { var result = [], i, length; if (!(array instanceof Array)) { array = [].slice.call(array); } length = array.length; for (i = 0; i < length; i++) { result.push(callback(array[i], i, array)); } return result; } /** * Faster version of standard reduce method in array * Confirmed that this method is 60% faster then native * @method reduce * @param {Array} array * @param {Function} callback * @param {*} [initialValue] * @member ns.util.array * @return {*} * @static */ function reduce(array, callback, initialValue) { var i, length, value, result = initialValue; if (!(array instanceof Array)) { array = [].slice.call(array); } length = array.length; for (i = 0; i < length; i++) { value = array[i]; if (result === undefined && i === 0) { result = value; } else { result = callback(result, value, i, array); } } return result; } ns.util.array = { range: range, isArrayLike: isArrayLike, forEach: forEach, filter: filter, map: map, reduce: reduce }; }(window, window.document, ns)); /*global window, ns, define, CustomEvent */ /*jslint nomen: true */ /* * Copyright (c) 2015 Samsung Electronics Co., Ltd * * Licensed under the Flora License, Version 1.1 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://floralicense.org/license/ * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * #Events * * The Tizen Advanced UI (TAU) framework provides events optimized for the Tizen * Web application. The following table displays the events provided by the TAU * framework. * @class ns.event */ (function (window, ns) { /** * Checks if specified variable is a array or not * @method isArray * @return {boolean} * @member ns.event * @private * @static */ var isArray = Array.isArray, isArrayLike = ns.util.array.isArrayLike, /** * @property {RegExp} SPLIT_BY_SPACES_REGEXP */ SPLIT_BY_SPACES_REGEXP = /\s+/g, /** * Returns trimmed value * @method trim * @param {string} value * @return {string} trimmed string * @static * @private * @member ns.event */ trim = function (value) { return value.trim(); }, /** * Split string to array * @method getEventsListeners * @param {string|Array|Object} names string with one name of event, many names of events divided by spaces, array with names of widgets or object in which keys are names of events and values are callbacks * @param {Function} globalListener * @return {Array} * @static * @private * @member ns.event */ getEventsListeners = function (names, globalListener) { var name, result = [], i; if (typeof names === 'string') { names = names.split(SPLIT_BY_SPACES_REGEXP).map(trim); } if (isArray(names)) { for (i=0; i<names.length; i++) { result.push({type: names[i], callback: globalListener}); } } else { for (name in names) { if (names.hasOwnProperty(name)) { result.push({type: name, callback: names[name]}); } } } return result; }; ns.event = { /** * Triggers custom event fastOn element * The return value is false, if at least one of the event * handlers which handled this event, called preventDefault. * Otherwise it returns true. * @method trigger * @param {HTMLElement} element * @param {string} type * @param {?*} [data=null] * @param {boolean=} [bubbles=true] * @param {boolean=} [cancelable=true] * @return {boolean=} * @member ns.event * @static */ trigger: function (element, type, data, bubbles, cancelable) { var evt = new CustomEvent(type, { "detail": data, //allow event to bubble up, required if we want to allow to listen fastOn document etc bubbles: typeof bubbles === "boolean" ? bubbles : true, cancelable: typeof cancelable === "boolean" ? cancelable : true }); return element.dispatchEvent(evt); }, /** * Prevent default on original event * @method preventDefault * @param {CustomEvent} event * @member ns.event * @static */ preventDefault: function (event) { var originalEvent = event._originalEvent; // @todo this.isPropagationStopped = returnTrue; if (originalEvent && originalEvent.preventDefault) { originalEvent.preventDefault(); } event.preventDefault(); }, /** * Stop event propagation * @method stopPropagation * @param {CustomEvent} event * @member ns.event * @static */ stopPropagation: function (event) { var originalEvent = event._originalEvent; // @todo this.isPropagationStopped = returnTrue; if (originalEvent && originalEvent.stopPropagation) { originalEvent.stopPropagation(); } event.stopPropagation(); }, /** * Stop event propagation immediately * @method stopImmediatePropagation * @param {CustomEvent} event * @member ns.event * @static */ stopImmediatePropagation: function (event) { var originalEvent = event._originalEvent; // @todo this.isPropagationStopped = returnTrue; if (originalEvent && originalEvent.stopImmediatePropagation) { originalEvent.stopImmediatePropagation(); } event.stopImmediatePropagation(); }, /** * Return document relative cords for event * @method documentRelativeCoordsFromEvent * @param {Event} event * @return {Object} * @return {number} return.x * @return {number} return.y * @member ns.event * @static */ documentRelativeCoordsFromEvent: function(event) { var _event = event ? event : window.event, client = { x: _event.clientX, y: _event.clientY }, page = { x: _event.pageX, y: _event.pageY }, posX = 0, posY = 0, touch0, body = document.body, documentElement = document.documentElement; if (event.type.match(/^touch/)) { touch0 = _event.targetTouches[0] || _event.originalEvent.targetTouches[0]; page = { x: touch0.pageX, y: touch0.pageY }; client = { x: touch0.clientX, y: touch0.clientY }; } if (page.x || page.y) { posX = page.x; posY = page.y; } else if (client.x || client.y) { posX = client.x + body.scrollLeft + documentElement.scrollLeft; posY = client.y + body.scrollTop + documentElement.scrollTop; } return { x: posX, y: posY }; }, /** * Return target relative cords for event * @method targetRelativeCoordsFromEvent * @param {Event} event * @return {Object} * @return {number} return.x * @return {number} return.y * @member ns.event * @static */ targetRelativeCoordsFromEvent: function(event) { var target = event.target, cords = { x: event.offsetX, y: event.offsetY }; if (cords.x === undefined || isNaN(cords.x) || cords.y === undefined || isNaN(cords.y)) { cords = ns.event.documentRelativeCoordsFromEvent(event); cords.x -= target.offsetLeft; cords.y -= target.offsetTop; } return cords; }, /** * Add event listener to element * @method fastOn * @param {HTMLElement} element * @param {string} type * @param {Function} listener * @param {boolean} [useCapture=false] * @member ns.event * @static */ fastOn: function(element, type, listener, useCapture) { element.addEventListener(type, listener, useCapture || false); }, /** * Remove event listener to element * @method fastOff * @param {HTMLElement} element * @param {string} type * @param {Function} listener * @param {boolean} [useCapture=false] * @member ns.event * @static */ fastOff: function(element, type, listener, useCapture) { element.removeEventListener(type, listener, useCapture || false); }, /** * Add event listener to element with prefixes for all browsers * @method fastPrefixedOn * @param {HTMLElement} element * @param {string} type * @param {Function} listener * @param {boolean} [useCapture=false] * @member ns.event * @static */ prefixedFastOn: function(element, type, listener, useCapture) { var nameForPrefix = type.charAt(0).toLocaleUpperCase() + type.substring(1); element.addEventListener(type.toLowerCase(), listener, useCapture || false); element.addEventListener("webkit" + nameForPrefix, listener, useCapture || false); element.addEventListener("moz" + nameForPrefix, listener, useCapture || false); element.addEventListener("ms" + nameForPrefix, listener, useCapture || false); element.addEventListener("o" + nameForPrefix.toLowerCase(), listener, useCapture || false); }, /** * Remove event listener to element with prefixes for all browsers * @method fastPrefixedOff * @param {HTMLElement} element * @param {string} type * @param {Function} listener * @param {boolean} [useCapture=false] * @member ns.event * @static */ prefixedFastOff: function(element, type, listener, useCapture) { var nameForPrefix = type.charAt(0).toLocaleUpperCase() + type.substring(1); element.removeEventListener(type.toLowerCase(), listener, useCapture || false); element.removeEventListener("webkit" + nameForPrefix, listener, useCapture || false); element.removeEventListener("moz" + nameForPrefix, listener, useCapture || false); element.removeEventListener("ms" + nameForPrefix, listener, useCapture || false); element.removeEventListener("o" + nameForPrefix.toLowerCase(), listener, useCapture || false); }, /** * Add event listener to element that can be added addEventListner * @method on * @param {HTMLElement|HTMLDocument|Window} element * @param {string|Array|Object} type * @param {Function} listener * @param {boolean} [useCapture=false] * @member ns.event * @static */ on: function(element, type, listener, useCapture) { var i, j, elementsLength, typesLength, elements, listeners; if (isArrayLike(element)) { elements = element; } else { elements = [element]; } elementsLength = elements.length; listeners = getEventsListeners(type, listener); typesLength = listeners.length; for (i = 0; i < elementsLength; i++) { if (typeof elements[i].addEventListener === "function") { for (j = 0; j < typesLength; j++) { ns.event.fastOn(elements[i], listeners[j].type, listeners[j].callback, useCapture); } } } }, /** * Remove event listener to element * @method off * @param {HTMLElement|HTMLDocument|Window} element * @param {string|Array|Object} type * @param {Function} listener * @param {boolean} [useCapture=false] * @member ns.event * @static */ off: function(element, type, listener, useCapture) { var i, j, elementsLength, typesLength, elements, listeners; if (isArrayLike(element)) { elements = element; } else { elements = [element]; } elementsLength = elements.length; listeners = getEventsListeners(type, listener); typesLength = listeners.length; for (i = 0; i < elementsLength; i++) { if (typeof elements[i].addEventListener === "function") { for (j = 0; j < typesLength; j++) { ns.event.fastOff(elements[i], listeners[j].type, listeners[j].callback, useCapture); } } } }, /** * Add event listener to element only for one trigger * @method one * @param {HTMLElement|HTMLDocument|window} element * @param {string|Array|Object} type * @param {Function} listener * @param {boolean} [useCapture=false] * @member ns.event * @static */ one: function(element, type, listener, useCapture) { var arraySlice = [].slice, i, j, elementsLength, typesLength, elements, types, listeners, callbacks = []; if (isArrayLike(element)) { elements = arraySlice.call(element); } else { elements = [element]; } elementsLength = elements.length; listeners = getEventsListeners(type, listener); typesLength = listeners.length; for (i = 0; i < elementsLength; i++) { if (typeof elements[i].addEventListener === "function") { callbacks[i] = []; for (j = 0; j < typesLength; j++) { callbacks[i][j] = (function(i, j) { var args = arraySlice.call(arguments); ns.event.fastOff(elements[i], listeners[j].type, callbacks[i][j], useCapture); args.shift(); // remove the first argument of binding function args.shift(); // remove the second argument of binding function listeners[j].callback.apply(this, args); }).bind(null, i, j); ns.event.fastOn(elements[i], listeners[j].type, callbacks[i][j], useCapture); } } } } }; }(window, ns)); /*global window, ns, define */ /* * Copyright (c) 2015 Samsung Electronics Co., Ltd * * Licensed under the Flora License, Version 1.1 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://floralicense.org/license/ * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * #Info * * Various TAU information * @class ns.info */ (function (window, document, ns) { /** * @property {Object} info * @property {string} [info.profile="default"] Current runtime profile * @property {string} [info.theme="default"] Current runtime theme * @property {string} info.version Current runtime version * @member ns.info * @static */ var eventUtils = ns.event, info = { profile: "default", theme: "default", version: ns.version, /** * Refreshes information about runtime * @method refreshTheme * @param {Function} done Callback run when the theme is discovered * @member ns.info * @return {null|String} * @static */ refreshTheme: function (done) { var el = document.createElement("span"), parent = document.body, themeName = null; if (document.readyState !== "interactive" && document.readyState !== "complete") { eventUtils.fastOn(document, "DOMContentLoaded", this.refreshTheme.bind(this, done)); return null; } el.classList.add("tau-info-theme"); parent.appendChild(el); themeName = window.getComputedStyle(el, ":after").content; parent.removeChild(el); if (themeName && themeName.length > 0) { this.theme = themeName; } themeName = themeName || null; if (done) { done(themeName); } return themeName; } }; info.refreshTheme(); ns.info = info; }(window, window.document, ns)); /*global define: true, window: true */ /* * Copyright (c) 2015 Samsung Electronics Co., Ltd * * Licensed under the Flora License, Version 1.1 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://floralicense.org/license/ * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * #Selectors Utility * Object contains functions to get HTML elements by different selectors. * @class ns.util.selectors * @author Maciej Urbanski <m.urbanski@samsung.com> * @author Krzysztof Antoszek <k.antoszek@samsung.com> * @author Jadwiga Sosnowska <j.sosnowska@partner.samsung.com> * @author Damian Osipiuk <d.osipiuk@samsung.com> */ (function (document, ns) { /** * @method slice Alias for array slice method * @member ns.util.selectors * @private * @static */ var slice = [].slice, /** * @method matchesSelectorType * @return {string|boolean} * @member ns.util.selectors * @private * @static */ matchesSelectorType = (function () { var el = document.createElement("div"); if (typeof el.webkitMatchesSelector === "function") { return "webkitMatchesSelector"; } if (typeof el.mozMatchesSelector === "function") { return "mozMatchesSelector"; } if (typeof el.msMatchesSelector === "function") { return "msMatchesSelector"; } if (typeof el.matchesSelector === "function") { return "matchesSelector"; } if (typeof el.matches === "function") { return "matches"; } return false; }()); /** * Prefix selector with 'data-' and namespace if present * @method getDataSelector * @param {string} selector * @return {string} * @member ns.util.selectors * @private * @static */ function getDataSelector(selector) { var namespace = ns.getConfig('namespace'); return '[data-' + (namespace ? namespace + '-' : '') + selector + ']'; } /** * Runs matches implementation of matchesSelector * method on specified element * @method matchesSelector * @param {HTMLElement} element * @param {string} selector * @return {boolean} * @static * @member ns.util.selectors */ function matchesSelector(element, selector) { if (matchesSelectorType && element[matchesSelectorType]) { return element[matchesSelectorType](selector); } return false; } /** * Return array with all parents of element. * @method parents * @param {HTMLElement} element * @return {Array} * @member ns.util.selectors * @private * @static */ function parents(element) { var items = [], current = element.parentNode; while (current && current !== document) { items.push(current); current = current.parentNode; } return items; } /** * Checks if given element and its ancestors matches given function * @method closest * @param {HTMLElement} element * @param {Function} testFunction * @return {?HTMLElement} * @member ns.util.selectors * @static * @private */ function closest(element, testFunction) { var current = element; while (current && current !== document) { if (testFunction(current)) { return current; } current = current.parentNode; } return null; } /** * @method testSelector * @param {string} selector * @param {HTMLElement} node * @return {boolean} * @member ns.util.selectors * @static * @private */ function testSelector(selector, node) { return matchesSelector(node, selector); } /** * @method testClass * @param {string} className * @param {HTMLElement} node * @return {boolean} * @member ns.util.selectors * @static * @private */ function testClass(className, node) { return node && node.classList && node.classList.contains(className); } /** * @method testTag * @param {string} tagName * @param {HTMLElement} node * @return {boolean} * @member ns.util.selectors * @static * @private */ function testTag(tagName, node) { return node.tagName.toLowerCase() === tagName; } /** * @class ns.util.selectors */ ns.util.selectors = { matchesSelector: matchesSelector, /** * Return array with children pass by given selector. * @method getChildrenBySelector * @param {HTMLElement} context * @param {string} selector * @return {Array} * @static * @member ns.util.selectors */ getChildrenBySelector: function (context, selector) { return slice.call(context.children).filter(testSelector.bind(null, selector)); }, /** * Return array with children pass by given data-namespace-selector. * @method getChildrenByDataNS * @param {HTMLElement} context * @param {string} dataSelector * @return {Array} * @static * @member ns.util.selectors */ getChildrenByDataNS: function (context, dataSelector) { return slice.call(context.children).filter(testSelector.bind(null, getDataSelector(dataSelector))); }, /** * Return array with children with given class name. * @method getChildrenByClass * @param {HTMLElement} context * @param {string} className * @return {Array} * @static * @member ns.util.selectors */ getChildrenByClass: function (context, className) { return slice.call(context.children).filter(testClass.bind(null, className)); }, /** * Return array with children with given tag name. * @method getChildrenByTag * @param {HTMLElement} context * @param {string} tagName * @return {Array} * @static * @member ns.util.selectors */ getChildrenByTag: function (context, tagName) { return slice.call(context.children).filter(testTag.bind(null, tagName)); }, /** * Return array with all parents of element. * @method getParents * @param {HTMLElement} context * @param {string} selector * @return {Array} * @static * @member ns.util.selectors */ getParents: parents, /** * Return array with all parents of element pass by given selector. * @method getParentsBySelector * @param {HTMLElement} context * @param {string} selector * @return {Array} * @static * @member ns.util.selectors */ getParentsBySelector: function (context, selector) { return parents(context).filter(testSelector.bind(null, selector)); }, /** * Return array with all parents of element pass by given selector with namespace. * @method getParentsBySelectorNS * @param {HTMLElement} context * @param {string} selector * @return {Array} * @static * @member ns.util.selectors */ getParentsBySelectorNS: function (context, selector) { return parents(context).filter(testSelector.bind(null, getDataSelector(selector))); }, /** * Return array with all parents of element with given class name. * @method getParentsByClass * @param {HTMLElement} context * @param {string} className * @return {Array} * @static * @member ns.util.selectors */ getParentsByClass: function (context, className) { return parents(context).filter(testClass.bind(null, className)); }, /** * Return array with all parents of element with given tag name. * @method getParentsByTag * @param {HTMLElement} context * @param {string} tagName * @return {Array} * @static * @member ns.util.selectors */ getParentsByTag: function (context, tagName) { return parents(context).filter(testTag.bind(null, tagName)); }, /** * Return first element from parents of element pass by selector. * @method getClosestBySelector * @param {HTMLElement} context * @param {string} selector * @return {HTMLElement} * @static * @member ns.util.selectors */ getClosestBySelector: function (context, selector) { return closest(context, testSelector.bind(null, selector)); }, /** * Return first element from parents of element pass by selector with namespace. * @method getClosestBySelectorNS * @param {HTMLElement} context * @param {string} selector * @return {HTMLEle