|
|
- /**
- * utility functions
- */
- var util = {};
-
- /**
- * Test whether given object is a number
- * @param {*} object
- * @return {Boolean} isNumber
- */
- util.isNumber = function isNumber(object) {
- return (object instanceof Number || typeof object == 'number');
- };
-
- /**
- * Test whether given object is a string
- * @param {*} object
- * @return {Boolean} isString
- */
- util.isString = function isString(object) {
- return (object instanceof String || typeof object == 'string');
- };
-
- /**
- * Test whether given object is a Date, or a String containing a Date
- * @param {Date | String} object
- * @return {Boolean} isDate
- */
- util.isDate = function isDate(object) {
- if (object instanceof Date) {
- return true;
- }
- else if (util.isString(object)) {
- // test whether this string contains a date
- var match = ASPDateRegex.exec(object);
- if (match) {
- return true;
- }
- else if (!isNaN(Date.parse(object))) {
- return true;
- }
- }
-
- return false;
- };
-
- /**
- * Test whether given object is an instance of google.visualization.DataTable
- * @param {*} object
- * @return {Boolean} isDataTable
- */
- util.isDataTable = function isDataTable(object) {
- return (typeof (google) !== 'undefined') &&
- (google.visualization) &&
- (google.visualization.DataTable) &&
- (object instanceof google.visualization.DataTable);
- };
-
- /**
- * Create a semi UUID
- * source: http://stackoverflow.com/a/105074/1262753
- * @return {String} uuid
- */
- util.randomUUID = function randomUUID () {
- var S4 = function () {
- return Math.floor(
- Math.random() * 0x10000 /* 65536 */
- ).toString(16);
- };
-
- return (
- S4() + S4() + '-' +
- S4() + '-' +
- S4() + '-' +
- S4() + '-' +
- S4() + S4() + S4()
- );
- };
-
- /**
- * Extend object a with the properties of object b or a series of objects
- * Only properties with defined values are copied
- * @param {Object} a
- * @param {... Object} b
- * @return {Object} a
- */
- util.extend = function (a, b) {
- for (var i = 1, len = arguments.length; i < len; i++) {
- var other = arguments[i];
- for (var prop in other) {
- if (other.hasOwnProperty(prop) && other[prop] !== undefined) {
- a[prop] = other[prop];
- }
- }
- }
-
- return a;
- };
-
- /**
- * Convert an object to another type
- * @param {Boolean | Number | String | Date | Moment | Null | undefined} object
- * @param {String | undefined} type Name of the type. Available types:
- * 'Boolean', 'Number', 'String',
- * 'Date', 'Moment', ISODate', 'ASPDate'.
- * @return {*} object
- * @throws Error
- */
- util.convert = function convert(object, type) {
- var match;
-
- if (object === undefined) {
- return undefined;
- }
- if (object === null) {
- return null;
- }
-
- if (!type) {
- return object;
- }
- if (!(typeof type === 'string') && !(type instanceof String)) {
- throw new Error('Type must be a string');
- }
-
- //noinspection FallthroughInSwitchStatementJS
- switch (type) {
- case 'boolean':
- case 'Boolean':
- return Boolean(object);
-
- case 'number':
- case 'Number':
- return Number(object.valueOf());
-
- case 'string':
- case 'String':
- return String(object);
-
- case 'Date':
- if (util.isNumber(object)) {
- return new Date(object);
- }
- if (object instanceof Date) {
- return new Date(object.valueOf());
- }
- else if (moment.isMoment(object)) {
- return new Date(object.valueOf());
- }
- if (util.isString(object)) {
- match = ASPDateRegex.exec(object);
- if (match) {
- // object is an ASP date
- return new Date(Number(match[1])); // parse number
- }
- else {
- return moment(object).toDate(); // parse string
- }
- }
- else {
- throw new Error(
- 'Cannot convert object of type ' + util.getType(object) +
- ' to type Date');
- }
-
- case 'Moment':
- if (util.isNumber(object)) {
- return moment(object);
- }
- if (object instanceof Date) {
- return moment(object.valueOf());
- }
- else if (moment.isMoment(object)) {
- return moment(object);
- }
- if (util.isString(object)) {
- match = ASPDateRegex.exec(object);
- if (match) {
- // object is an ASP date
- return moment(Number(match[1])); // parse number
- }
- else {
- return moment(object); // parse string
- }
- }
- else {
- throw new Error(
- 'Cannot convert object of type ' + util.getType(object) +
- ' to type Date');
- }
-
- case 'ISODate':
- if (util.isNumber(object)) {
- return new Date(object);
- }
- else if (object instanceof Date) {
- return object.toISOString();
- }
- else if (moment.isMoment(object)) {
- return object.toDate().toISOString();
- }
- else if (util.isString(object)) {
- match = ASPDateRegex.exec(object);
- if (match) {
- // object is an ASP date
- return new Date(Number(match[1])).toISOString(); // parse number
- }
- else {
- return new Date(object).toISOString(); // parse string
- }
- }
- else {
- throw new Error(
- 'Cannot convert object of type ' + util.getType(object) +
- ' to type ISODate');
- }
-
- case 'ASPDate':
- if (util.isNumber(object)) {
- return '/Date(' + object + ')/';
- }
- else if (object instanceof Date) {
- return '/Date(' + object.valueOf() + ')/';
- }
- else if (util.isString(object)) {
- match = ASPDateRegex.exec(object);
- var value;
- if (match) {
- // object is an ASP date
- value = new Date(Number(match[1])).valueOf(); // parse number
- }
- else {
- value = new Date(object).valueOf(); // parse string
- }
- return '/Date(' + value + ')/';
- }
- else {
- throw new Error(
- 'Cannot convert object of type ' + util.getType(object) +
- ' to type ASPDate');
- }
-
- default:
- throw new Error('Cannot convert object of type ' + util.getType(object) +
- ' to type "' + type + '"');
- }
- };
-
- // parse ASP.Net Date pattern,
- // for example '/Date(1198908717056)/' or '/Date(1198908717056-0700)/'
- // code from http://momentjs.com/
- var ASPDateRegex = /^\/?Date\((\-?\d+)/i;
-
- /**
- * Get the type of an object, for example util.getType([]) returns 'Array'
- * @param {*} object
- * @return {String} type
- */
- util.getType = function getType(object) {
- var type = typeof object;
-
- if (type == 'object') {
- if (object == null) {
- return 'null';
- }
- if (object instanceof Boolean) {
- return 'Boolean';
- }
- if (object instanceof Number) {
- return 'Number';
- }
- if (object instanceof String) {
- return 'String';
- }
- if (object instanceof Array) {
- return 'Array';
- }
- if (object instanceof Date) {
- return 'Date';
- }
- return 'Object';
- }
- else if (type == 'number') {
- return 'Number';
- }
- else if (type == 'boolean') {
- return 'Boolean';
- }
- else if (type == 'string') {
- return 'String';
- }
-
- return type;
- };
-
- /**
- * Retrieve the absolute left value of a DOM element
- * @param {Element} elem A dom element, for example a div
- * @return {number} left The absolute left position of this element
- * in the browser page.
- */
- util.getAbsoluteLeft = function getAbsoluteLeft (elem) {
- var doc = document.documentElement;
- var body = document.body;
-
- var left = elem.offsetLeft;
- var e = elem.offsetParent;
- while (e != null && e != body && e != doc) {
- left += e.offsetLeft;
- left -= e.scrollLeft;
- e = e.offsetParent;
- }
- return left;
- };
-
- /**
- * Retrieve the absolute top value of a DOM element
- * @param {Element} elem A dom element, for example a div
- * @return {number} top The absolute top position of this element
- * in the browser page.
- */
- util.getAbsoluteTop = function getAbsoluteTop (elem) {
- var doc = document.documentElement;
- var body = document.body;
-
- var top = elem.offsetTop;
- var e = elem.offsetParent;
- while (e != null && e != body && e != doc) {
- top += e.offsetTop;
- top -= e.scrollTop;
- e = e.offsetParent;
- }
- return top;
- };
-
- /**
- * Get the absolute, vertical mouse position from an event.
- * @param {Event} event
- * @return {Number} pageY
- */
- util.getPageY = function getPageY (event) {
- if ('pageY' in event) {
- return event.pageY;
- }
- else {
- var clientY;
- if (('targetTouches' in event) && event.targetTouches.length) {
- clientY = event.targetTouches[0].clientY;
- }
- else {
- clientY = event.clientY;
- }
-
- var doc = document.documentElement;
- var body = document.body;
- return clientY +
- ( doc && doc.scrollTop || body && body.scrollTop || 0 ) -
- ( doc && doc.clientTop || body && body.clientTop || 0 );
- }
- };
-
- /**
- * Get the absolute, horizontal mouse position from an event.
- * @param {Event} event
- * @return {Number} pageX
- */
- util.getPageX = function getPageX (event) {
- if ('pageY' in event) {
- return event.pageX;
- }
- else {
- var clientX;
- if (('targetTouches' in event) && event.targetTouches.length) {
- clientX = event.targetTouches[0].clientX;
- }
- else {
- clientX = event.clientX;
- }
-
- var doc = document.documentElement;
- var body = document.body;
- return clientX +
- ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) -
- ( doc && doc.clientLeft || body && body.clientLeft || 0 );
- }
- };
-
- /**
- * add a className to the given elements style
- * @param {Element} elem
- * @param {String} className
- */
- util.addClassName = function addClassName(elem, className) {
- var classes = elem.className.split(' ');
- if (classes.indexOf(className) == -1) {
- classes.push(className); // add the class to the array
- elem.className = classes.join(' ');
- }
- };
-
- /**
- * add a className to the given elements style
- * @param {Element} elem
- * @param {String} className
- */
- util.removeClassName = function removeClassname(elem, className) {
- var classes = elem.className.split(' ');
- var index = classes.indexOf(className);
- if (index != -1) {
- classes.splice(index, 1); // remove the class from the array
- elem.className = classes.join(' ');
- }
- };
-
- /**
- * For each method for both arrays and objects.
- * In case of an array, the built-in Array.forEach() is applied.
- * In case of an Object, the method loops over all properties of the object.
- * @param {Object | Array} object An Object or Array
- * @param {function} callback Callback method, called for each item in
- * the object or array with three parameters:
- * callback(value, index, object)
- */
- util.forEach = function forEach (object, callback) {
- var i,
- len;
- if (object instanceof Array) {
- // array
- for (i = 0, len = object.length; i < len; i++) {
- callback(object[i], i, object);
- }
- }
- else {
- // object
- for (i in object) {
- if (object.hasOwnProperty(i)) {
- callback(object[i], i, object);
- }
- }
- }
- };
-
- /**
- * Update a property in an object
- * @param {Object} object
- * @param {String} key
- * @param {*} value
- * @return {Boolean} changed
- */
- util.updateProperty = function updateProp (object, key, value) {
- if (object[key] !== value) {
- object[key] = value;
- return true;
- }
- else {
- return false;
- }
- };
-
- /**
- * Add and event listener. Works for all browsers
- * @param {Element} element An html element
- * @param {string} action The action, for example "click",
- * without the prefix "on"
- * @param {function} listener The callback function to be executed
- * @param {boolean} [useCapture]
- */
- util.addEventListener = function addEventListener(element, action, listener, useCapture) {
- if (element.addEventListener) {
- if (useCapture === undefined)
- useCapture = false;
-
- if (action === "mousewheel" && navigator.userAgent.indexOf("Firefox") >= 0) {
- action = "DOMMouseScroll"; // For Firefox
- }
-
- element.addEventListener(action, listener, useCapture);
- } else {
- element.attachEvent("on" + action, listener); // IE browsers
- }
- };
-
- /**
- * Remove an event listener from an element
- * @param {Element} element An html dom element
- * @param {string} action The name of the event, for example "mousedown"
- * @param {function} listener The listener function
- * @param {boolean} [useCapture]
- */
- util.removeEventListener = function removeEventListener(element, action, listener, useCapture) {
- if (element.removeEventListener) {
- // non-IE browsers
- if (useCapture === undefined)
- useCapture = false;
-
- if (action === "mousewheel" && navigator.userAgent.indexOf("Firefox") >= 0) {
- action = "DOMMouseScroll"; // For Firefox
- }
-
- element.removeEventListener(action, listener, useCapture);
- } else {
- // IE browsers
- element.detachEvent("on" + action, listener);
- }
- };
-
-
- /**
- * Get HTML element which is the target of the event
- * @param {Event} event
- * @return {Element} target element
- */
- util.getTarget = function getTarget(event) {
- // code from http://www.quirksmode.org/js/events_properties.html
- if (!event) {
- event = window.event;
- }
-
- var target;
-
- if (event.target) {
- target = event.target;
- }
- else if (event.srcElement) {
- target = event.srcElement;
- }
-
- if (target.nodeType != undefined && target.nodeType == 3) {
- // defeat Safari bug
- target = target.parentNode;
- }
-
- return target;
- };
-
- /**
- * Stop event propagation
- */
- util.stopPropagation = function stopPropagation(event) {
- if (!event)
- event = window.event;
-
- if (event.stopPropagation) {
- event.stopPropagation(); // non-IE browsers
- }
- else {
- event.cancelBubble = true; // IE browsers
- }
- };
-
- /**
- * Fake a hammer.js gesture. Event can be a ScrollEvent or MouseMoveEvent
- * @param {Element} element
- * @param {Event} event
- */
- util.fakeGesture = function fakeGesture (element, event) {
- var eventType = null;
-
- // for hammer.js 1.0.5
- return Hammer.event.collectEventData(this, eventType, event);
-
- // for hammer.js 1.0.6
- //var touches = Hammer.event.getTouchList(event, eventType);
- //return Hammer.event.collectEventData(this, eventType, touches, event);
- };
-
- /**
- * Cancels the event if it is cancelable, without stopping further propagation of the event.
- */
- util.preventDefault = function preventDefault (event) {
- if (!event)
- event = window.event;
-
- if (event.preventDefault) {
- event.preventDefault(); // non-IE browsers
- }
- else {
- event.returnValue = false; // IE browsers
- }
- };
-
-
- util.option = {};
-
- /**
- * Convert a value into a boolean
- * @param {Boolean | function | undefined} value
- * @param {Boolean} [defaultValue]
- * @returns {Boolean} bool
- */
- util.option.asBoolean = function (value, defaultValue) {
- if (typeof value == 'function') {
- value = value();
- }
-
- if (value != null) {
- return (value != false);
- }
-
- return defaultValue || null;
- };
-
- /**
- * Convert a value into a number
- * @param {Boolean | function | undefined} value
- * @param {Number} [defaultValue]
- * @returns {Number} number
- */
- util.option.asNumber = function (value, defaultValue) {
- if (typeof value == 'function') {
- value = value();
- }
-
- if (value != null) {
- return Number(value) || defaultValue || null;
- }
-
- return defaultValue || null;
- };
-
- /**
- * Convert a value into a string
- * @param {String | function | undefined} value
- * @param {String} [defaultValue]
- * @returns {String} str
- */
- util.option.asString = function (value, defaultValue) {
- if (typeof value == 'function') {
- value = value();
- }
-
- if (value != null) {
- return String(value);
- }
-
- return defaultValue || null;
- };
-
- /**
- * Convert a size or location into a string with pixels or a percentage
- * @param {String | Number | function | undefined} value
- * @param {String} [defaultValue]
- * @returns {String} size
- */
- util.option.asSize = function (value, defaultValue) {
- if (typeof value == 'function') {
- value = value();
- }
-
- if (util.isString(value)) {
- return value;
- }
- else if (util.isNumber(value)) {
- return value + 'px';
- }
- else {
- return defaultValue || null;
- }
- };
-
- /**
- * Convert a value into a DOM element
- * @param {HTMLElement | function | undefined} value
- * @param {HTMLElement} [defaultValue]
- * @returns {HTMLElement | null} dom
- */
- util.option.asElement = function (value, defaultValue) {
- if (typeof value == 'function') {
- value = value();
- }
-
- return value || defaultValue || null;
- };
-
-
- /**
- * Compare two numbers and return the lowest, non-negative number.
- *
- * @param {number} number1
- * @param {number} number2
- * @returns {number} | number1 or number2, the lowest positive number. If both negative, return -1
- * @private
- */
- util._getLowestPositiveNumber = function(number1,number2) {
- if (number1 >= 0) {
- if (number2 >= 0) {
- return (number1 < number2) ? number1 : number2;
- }
- else {
- return number1;
- }
- }
- else {
- if (number2 >= 0) {
- return number2;
- }
- else {
- return -1;
- }
- }
- }
|