diff -r 913c9751c067 -r 716254ccbcc0 org.symbian.tools.wrttools.doc.WebDeveloper/html/js/utils.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.symbian.tools.wrttools.doc.WebDeveloper/html/js/utils.js Fri Mar 05 19:11:15 2010 -0800 @@ -0,0 +1,671 @@ +// ARRAY FUNTIONS + +/** + * Test is some array member is equal (===) to tested value. + * + * @param arr array to test + * @param value value to test + * @type Boolean + */ +function inArray(arr, value) { + for (var i = 0; i < arr.length; i++) { + if (arr[i] === value) { + return true; + } + } + return false; +} + +// STRING FUNCTIONS + + +/** + * Get relative URL. + * + * @param url URL string + * @return relative part of the URL + * @type String + */ +function getRelativeUrl(url, baseUrl) { + if (baseUrl === undefined) { + var i = url.lastIndexOf("/"); + if (i != -1) { + return url.substring(i + 1); + } else { + return url; + } + } else { + if (url.substring(0, baseUrl.length) === baseUrl) { + return url.substring(baseUrl.length); + } else { + return undefined; + } + } +} + +/** + * Fix file scheme URLs generated by IE. + * + * @param url file scheme URL to fix + */ +/* +function fixUrl(url) { + var _url; + if (pathFileUrl.test(url)) { + _url = url.replace(pathFileUrl, "file:///$1/$2"); + } else { + _url = url; + } + return _url.replace("\\", "/"); + +} +var pathFileUrl = new RegExp("^file://([a-zA-Z]:)[\\\\/](.+)$"); +*/ + +/** + * Get string value for array where list is in prose. + * + * @param array array to get the string value for + * @type String + * @return array string value in prose + */ +function toProseString(array) { + switch (array.length) { + case 0: + return ""; + case 1: + return array[0]; + case 2: + return array[0] + " and " + array[1]; + default: + var t = ""; + for (var i = 0; i < array.length - 1; i++) { + t += array[i] + ", "; + } + return t + "and " + array[array.length - 1]; + } +} + + +// EVENT FUNCTIONS + +/** + * Stop event. + * + * @param event event to stop + */ +function stopEvent(event) { + if (event.stopPropagation) { + event.stopPropagation(); + } else { + event.cancelBubble = true; + } + if (event.preventDefault) { + event.preventDefault(); + } else { + event.returnValue = false; + } +} + +/** + * Return target node of an event. + * + * @return target node of the event + * @type Node + */ +function getTargetNode(event) { + if (event.target) { + return event.target; + } else if (event.srcElement) { + return event.srcElement; + } else { + return null; + } +} + +/** + * Attach event listener to a DOM node. + * + * @param node DOM node to attach lister to + * @param type Type of event to catch + * @param func Function to act as the handler + */ +function attachEventListener(node, type, func) { + if (node.addEventListener) { + node.addEventListener(type, func, false); + } else if (node.attachEvent) { + node.attachEvent("on" + type, function() { func.call(this, event); } ); + } +} + + +// CSS CLASS FUNCTIONS + + +/** + * Switch class of an element. + * + * @param n Element node to change the class of + * @param f Class to change from + * @param t Class to change to + * @param arr Class array (optional) + */ +function switchClass(n, f, t, arr) { + if (arr === undefined) { + arr = getClassArray(n.className); + } + for (var i = 0; i < arr.length; i++) { + if (arr[i] == f) { + arr[i] = t; + } else if (arr[i] == t) { + arr[i] = f; + } + } + n.className = arr.join(" "); +} + +/** + * Test if element is of class. + * + * @param n Element node to test + * @param c Class to test for + * @param arr Class array (optional) + * @return boolean value if element is of the tested class + */ +function isClass(n, c, arr) { + if (arr === undefined) { + arr = getClassArray(n.className); + } + for (var i = 0; i < arr.length; i++) { + if (arr[i] == c) { + return true; + } + } + return false; +} + +/** + * Add class to an element. + * + * @param n Element node to add the class to + * @param c Class to add + * @param arr Class array (optional) + */ +function addClass(n, c, arr) { + if (arr === undefined) { + arr = getClassArray(n.className); + } + if (!isClass(n, c, arr)) { + n.className = n.className + " " + c; + } +} + +/** + * Remove class + * + * @param n Element node to remove the class from + * @param c Class to remove + * @param arr Class array (optional) + */ +function removeClass(n, c, arr) { + if (arr === undefined) { + arr = getClassArray(n.className); + } + if (isClass(n, c, arr)) { + var ret = []; + for (var i = 0; i < arr.length; i++) { + if (arr[i] != c) { + ret.push(arr[i]); + } + } + n.className = ret.join(" "); + } +} + +/** + * Get class names as an array + * + * @param c class name + * @return array of class members + * @type Array + */ +function getClassArray(c) { + return String(c).split(" "); +} + + +// COLLECTION CLASSES + + +/** + * Multi value Map. + * + * Usage: + * + * >> var m = new Map(); + * >> m.put("a", "first"); + * >> m.put("a", "second"); + * >> m.size(); + * 1 + * >> m.get("a"); + * ["first", "second"] + * + * @constructor + * @param {Boolean} multi Boolean to define whether map will store dublicate values into an array + */ +function Map(multi) { + this.keys = []; + this.values = []; + this.multi = (multi === undefined ? false : multi); +} +Map.prototype.toString = function() { + var val = "[Object Map"; + if (this.keys.length !== 0) { + val += ": {"; + for (var i = 0; i < this.keys.length; i++) { + if (i !== 0) { + val += "; "; + } + val += this.keys[i] + ":"; + for (var j = 0; j < this.values[i].length; j++) { + if (j !== 0) { + val += ","; + } + val += " " + this.values[i][j].toString(); + } + + } + val += "}"; + } + val += "]"; + return val; +}; +/** + * @param {String} key + * @param {Object} value + */ +Map.prototype.put = function(key, value) { + var index = this._find(key); + var a; + if (index != -1 ) { + a = this.values[index]; + } else { + index = this.keys.length; + this.keys[index] = key; + a = []; + } + if (this.multi) { + a[a.length] = value; + } else { + a[0] = value; + } + this.values[index] = a; +}; +/** + * @param {String} key + * @type Object + */ +Map.prototype.get = function(key) { + var index = this._find(key); + if (index != -1) { + if (this.multi) { + return this.values[index]; + } else { + return this.values[index][0]; + } + } else { + return null; + } +}; +/** + * Iterator for the value set. + * + * @return Iterator for the values + * @type ArrayIterator + */ +Map.prototype.iterator = function(key) { + var index = this._find(key); + var val; + if (index != -1) { + val = this.values[index]; + } else { + val = []; + } + return new ArrayIterator(val); +}; +/** + * @type Number + */ +Map.prototype.size = function() { + return this.keys.length; +}; +/** + * @param {String} key + * @type Number + */ +Map.prototype._find = function(key) { + var index = -1; + for (var i = 0; i < this.keys.length; i++) { + if (this.keys[i] == key) { + index = i; + break; + } + } + return index; +}; + +/** + * Map. + * + * Usage: + * + * >> var m = new SingleValueMap(); + * >> m.put("a", "first"); + * >> m.put("a", "second"); + * >> m.size(); + * 1 + * >> m.get("a"); + * "second" + * + * @constructor + */ +function SingleValueMap() { + this.keys = []; + this.values = []; + this.multi = false; +} +SingleValueMap.prototype = new Map(false); +SingleValueMap.prototype.toString = function() { + return "[Object SingleValueMap]"; +}; + +/** + * Set. + * + * @constructor + */ +function Set() { + this.keys = []; +} +Set.prototype.toString = function() { + var val = "[object Set"; + if (this.keys.length > 0) { + val += ":"; + for (var i = 0; i < this.keys.length; i++) { + if (i !== 0) { + val += ","; + } + val += " " + this.keys[i]; + } + } + val += "]"; + return val; +}; +Set.prototype.add = function(value) { + var i = this.m_find(value); + if (i == -1) { + this.keys[this.keys.length] = value; + } +}; +Set.prototype.iterator = function() { + return new ArrayIterator(this.keys); +}; +Set.prototype.size = Map.prototype.size; +Set.prototype.m_find = Map.prototype._find; + +/** + * Array Iterator + * + * Usage: + * + * >> var arr = new Array("a", "b", "c"); + * >> for (var itr = new ArrayIterator(arr); itr.hasNext();) { + * >> alert(itr.next()); + * >> } + * "a" + * "b" + * "c" + * + * @constructor + * @param {Array} arrayLike array to iterate through + */ +function ArrayIterator(arrayLike) { + this.arrayLike = arrayLike; + this.i = 0; + NoSuchElementException = function() {}; + NoSuchElementException.prototype = new Error(); + NoSuchElementException.prototype.name = 'NoSuchElementException'; + NoSuchElementException.prototype.message = 'Iteration has no more elements'; +} +/** + * String value of the object. + * + * @type String + */ +ArrayIterator.prototype.toString = function() { + return "[Object ArrayIterator]"; +}; +/** + * @type Object + */ +ArrayIterator.prototype.next = function() { + if (!this.hasNext()) { + throw new NoSuchElementException(); + } + if (this.arrayLike.item) { + return this.arrayLike.item(this.i++); + } else { + return this.arrayLike[this.i++]; + } +}; +/*/ + * @type Boolean + */ +ArrayIterator.prototype.hasNext = function() { + return this.i < this.arrayLike.length; +}; + + +// DOM FUNCTIONS + + +/** + * Get next sibling by element name + * + * @param n current element + * @param t element name of the desired sibling + * @return next sibling element with a given name or null if not found + * @type Element + */ +function getNextSiblingByTagName(n, t) { + if (n != null) { + var tag = t.toLowerCase(); + var i = n; + while (true) { + if (i.nodeType == 1 && i.nodeName.toLowerCase() == tag) { + return i; + } + if (i.nextSibling != null) { + i = i.nextSibling; + } else { + return null; + } + } + } + return null; +} + +/** + * Get child elements by element name. + * + * @param node parent element + * @param name element name of the desired child elements + * @return array of child elements + * @type Array + */ +function getChildElementsByTagName(node, name) { + var buf = []; + var tag = undefined; + if (name !== undefined) { + tag = name.toLowerCase(); + } + for (var n = node.firstChild; n != null; n = n.nextSibling) { + if (n.nodeType == 1 && (name === undefined || n.nodeName.toLowerCase() == tag)) { + buf[buf.length] = n; + } + } + return buf; +} + +/** + * Get first child element by element name. + * + * @param node parent element + * @param name element name of the desired child elements + * @return DOM Element, null if none found + * @type Object + */ +function getFirstChildElementByTagName(node, name) { + var tag = undefined; + if (name !== undefined) { + tag = name.toLowerCase(); + } + for (var n = node.firstChild; n != null; n = n.nextSibling) { + if (n.nodeType == 1 && (name === undefined || n.nodeName.toLowerCase() == tag)) { + return n; + } + } + return null; +} + + +/** + * Wrap child nodes of an element to wrapper element. + * + * @param parent element whose child nodes to wrapper + * @param wrapper wrapper element + */ +function wrapChildElements(parent, wrapper) { + for (var c = parent.firstChild, n = null; c != null; c = parent.firstChild) { + n = parent.removeChild(c); + wrapper.appendChild(n); + } + parent.appendChild(wrapper); +} + +/** + * Get elements by class name. + * + * @param node DOM node whose descendants select + * @param cls class name + * @param elem element name (optional) + * @return array of DOM nodes + * @type Array + */ +function getElementsByClassName(node, cls, elem) { + if (elem === undefined) { + elem = "*"; + } + var res = []; + for (var el = document.getElementsByTagName(elem), i = 0; i < el.length; i++) { + if (isClass(el[i], cls)) { + res[res.length] = el[i]; + } + } + return res; +} + +/** + * Get first element by class name. + * + * @param node DOM node whose descendants select + * @param cls class name + * @param elem element name (optional) + * @return DOM Element, null if none found + * @type Object + */ +function getFirstElementByClassName(node, cls, elem) { + if (elem === undefined) { + elem = "*"; + } + for (var el = document.getElementsByTagName(elem), i = 0; i < el.length; i++) { + if (isClass(el[i], cls)) { + return el[i]; + } + } + return null; +} + +// FORM FUNCTIONS + +function formSubmitHandler(event) { + var f = getTargetNode(event); + if (!validateForm(f)) { + stopEvent(event); + } +} + +/** + * Validate form + * + * @param form form to validate + * @type Boolean + * @return boolean value whether validation was successful + */ +function validateForm(form) { + var isValid = true; + var labels; + var r = []; + var missing; + var col = form.elements; + elements: for (var i = 0; i < col.length; i++) { + if (isClass(col[i], "required") && !col[i].disabled) { + var f = col[col[i].name]; + var valid = false; + if (col[i].type === "checkbox" || col[i].type === "radio") { + if (col[i].value != f[0].value) { // test only the first + continue; + } + for (var j = 0; j < f.length; j++) { + if (f[j].checked && f[j].className.indexOf("nonrequired") == -1) { + continue elements; + } + } + } else if (col[i].type === "select-one") { + if (!isClass(col[i][col[i].selectedIndex], "nonvalue")) { + continue; + } + } else { + if (f.value !== "") { + continue; + } + } + + if (labels === undefined) { + labels = form.getElementsByTagName("label"); + } + var label; + for (j = 0; j < labels.length; j++) { + if (labels[j].htmlFor == col[i].name) { + label = labels[j]; + } + } + if (!valid) { + isValid = false; + if (missing === undefined) { + missing = []; + } + missing[missing.length] = label.firstChild.data; + addClass(label, "form_invalid"); + } else { + removeClass(label, "form_invalid"); + } + } + } + if (!isValid) { + window.alert("Required field" + (missing.length < 2 ? "" : "s") + + " " + toProseString(missing) + + " " + (missing.length < 2 ? "has" : "have") + " no value"); + } + return isValid; +} \ No newline at end of file