/*!
* Copyright (c) 2009 Francesco Mele jsbeans@francescomele.com
*
* This Software is licenced under the LGPL Licence (GNU Lesser General
* Public License).
* In addition to the LGPL Licence the Software is subject to the
* following conditions:
*
* i every modification must be public and comunicated to the Author
* ii every "jsbean" added to this library must be self consistent
* except for the dependence from jsbeans-x.x.x.js
* iii copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* A navigation bar starting from a pseudo-xml descriptor of the site.
* @namespace jsbeans
* @class Navbar
* @static
*/
jsbeans.Navbar = {
/**
* @property options
* @type JSON
* @static
* <pre>
* parameter: String, // the name of the request parameter indicating the actual page
* separator: String, // separator of each element of navigation bar, default " > "
* target: String, // the id of the container of the navigation bar, default "navbar"
* descriptor: String, // the id of the container of the descriptor, usually an hidden div
* linkable: boolean, // if any voice of the navigation bar must have a link to the corresponding page, default true
* home: String, // the context path, default "/"
* replace: Array // replacer for rendered links
* </pre>
* */
options: {
parameter: null,
separator: " > ",
target: "navbar",
descriptor: "navbardescriptor",
linkable: true,
home: "/",
replace: null
},
/**
* Renders the UI
* @method render
* @param [options] {JSON} override of defaults
* @static
* */
render: function() {
this._init(arguments[0] || {});
var descriptor = document.getElementById("" + this.options.descriptor);
if (descriptor == null || typeof(descriptor) == "undefined") {
return;
}
descriptor.style.display = "none";
descriptor.style.visibility = "hidden";
descriptor.style.position = "absolute";
descriptor.style.top = "-10000px";
var currentPage = null;
// use parameter
if (this.options.parameter != null) {
if (this._isFun(this.options.parameter)) {
var parVal = this.options.parameter();
}
else {
var parVal = this.getParameterValue();
}
if (this.options.replace != null && parVal != null) {
parVal = parVal.split(this.options.replace[0]).join(this.options.replace[1]);
}
currentPage = document.getElementById(parVal);
}
// use url
else {
var currentLocation = location.href;
// cut from protocol to first ? (http://www.francescomele.com/index.php?parName=parValue => www.francescomele.com/index.php)
currentLocation = currentLocation.substring(currentLocation.indexOf("://") + 3, currentLocation.length);
if (currentLocation.indexOf("?") != -1) {
currentLocation = currentLocation.substring(0, currentLocation.indexOf("?"));
}
// cut this.options.home if != "/"
if (this.options.home != "/" && currentLocation.indexOf(this.options.home) != -1) {
currentLocation = currentLocation.substring(currentLocation.indexOf(this.options.home) + this.options.home.length);
}
currentPage = document.getElementById(currentLocation);
}
if (currentPage == null || typeof(currentPage) == "undefined") {
return;
}
this._navbar = new Array();
this._buildNavigation(currentPage);
this._navbar.reverse();
var nv = document.getElementById(this.options.target);
nv.innerHTML = "";
var a, cur;
for (var i = 0; i < this._navbar.length; i++) {
cur = this._navbar[i];
a = document.createElement("a");
if (this.options.linkable && (i != this._navbar.length - 1)) {
// use parameter
if (this.options.parameter != null) {
if (this._isFun(this.options.parameter)) {
a.href = "?" + this.options.parameter(cur);
}
else {
a.href = "?" + this.options.parameter + "=" + this._getHref(cur);
}
}
// use url
else {
a.href = this._getHref(cur);
}
}
a.title = this._getAlt(cur);
a.innerHTML = this._getLabel(cur);
nv.innerHTML = nv.innerHTML + " " + this.options.separator;
nv.appendChild(a);
}
},
/**
* Returns the value of the request parameter as that of <code class="prop">jsbeans.Navbar.options.parameter</code>
* @method getParameterValue
* @return {String} the request parameter value
* @static
* */
getParameterValue: function() {
var qs = location.search.substring(1, location.search.length).replace(/\+/g, ' ');
var items = qs.split('&');
for (var i = 0, item; item = items[i]; i++) {
var p = item.split('=');
var n = decodeURIComponent(p[0]);
if (this.options.parameter == n) {
return (p.length == 2) ? decodeURIComponent(p[1]) : null;
}
}
return null;
},
/**
* @method _init
* @param options {JSON}
* @private
* @static
* */
_init: function(/*JSON*/options) {
this.options.parameter = typeof(options.parameter) != "undefined" ? options.parameter : this.options.parameter;
this.options.separator = typeof(options.separator) != "undefined" ? options.separator : this.options.separator;
this.options.target = typeof(options.target) != "undefined" ? options.target : this.options.target;
this.options.descriptor = typeof(options.descriptor) != "undefined" ? options.descriptor : this.options.descriptor;
this.options.linkable = typeof(options.linkable) != "undefined" ? options.linkable : this.options.linkable;
this.options.home = typeof(options.home) != "undefined" ? options.home : this.options.home;
this.options.replace = typeof(options.replace) != "undefined" ? options.replace : this.options.replace;
},
/**
* @property _navbar
* @type Array
* @private
* @static
* */
_navbar: new Array(),
/**
* @method _buildNavigation
* @param node {DOM}
* @return {Array}
* @private
* @static
* */
_buildNavigation: function(node) {
if (node.id != this.options.descriptor) {
this._navbar.push(node);
this._buildNavigation(node.parentNode);
}
else {
return this._navbar;
}
},
/**
* @method _getHref
* @param node {DOM}
* @return {String}
* @private
* @static
* */
_getHref: function(obj) {
var res = this._getAttribute(obj, "id");
if (this.options.replace != null) {
res = res.split(this.options.replace[1]).join(this.options.replace[0]);
}
return res;
},
/**
* @method _getLabel
* @param node {DOM}
* @return {String}
* @private
* @static
* */
_getLabel: function(obj) {
return this._getAttribute(obj, "class");
},
/**
* @method _getAlt
* @param node {DOM}
* @return {String}
* @private
* @static
* */
_getAlt: function(obj) {
return this._getAttribute(obj, "title");
},
/**
* @method _getAttribute
* @param node {DOM}
* @param attributeName {String}
* @return {String}
* @private
* @static
* */
_getAttribute: function(obj, attrName) {
return obj == null || !obj.getAttribute ? null : obj.getAttribute(attrName);
},
/**
* Cheks if fn is a Function
* @method _isFun
* @param func {Object}
* @return {boolean} true if <code class="param">func</code> is a <code>Function</code>
* @private
* @static
* */
_isFun: function(fn) {
return !!fn && typeof fn != "string" && !fn.nodeName &&
fn.constructor != Array && /function/i.test( fn + "" );
}
};