Skip to content
Snippets Groups Projects
jquery.fancytree.js 163 KiB
Newer Older
  • Learn to ignore specific revisions
  • Laura Cappelli's avatar
    Laura Cappelli committed
    	 */
    	evalOption: function(optionName, node, nodeObject, treeOptions, defaultValue) {
    		var ctx, res,
    			tree = node.tree,
    			treeOpt = treeOptions[optionName],
    			nodeOpt = nodeObject[optionName];
    
    		if( $.isFunction(treeOpt) ) {
    			ctx = { node: node, tree: tree, widget: tree.widget, options: tree.widget.options };
    			res = treeOpt.call(tree, {type: optionName}, ctx);
    			if( res == null ) {
    				res = nodeOpt;
    			}
    		} else {
    			res = (nodeOpt != null) ? nodeOpt : treeOpt;
    		}
    		if( res == null ) {
    			res = defaultValue;  // no option set at all: return default
    		}
    		return res;
    	},
    	/** Convert a keydown or mouse event to a canonical string like 'ctrl+a',
    	 * 'ctrl+shift+f2', 'shift+leftdblclick'.
    	 *
    	 * This is especially handy for switch-statements in event handlers.
    	 *
    	 * @param {event}
    	 * @returns {string}
    	 *
    	 * @example
    
    	switch( $.ui.fancytree.eventToString(event) ) {
    		case "-":
    			tree.nodeSetExpanded(ctx, false);
    			break;
    		case "shift+return":
    			tree.nodeSetActive(ctx, true);
    			break;
    		case "down":
    			res = node.navigate(event.which, activate, true);
    			break;
    		default:
    			handled = false;
    	}
    	if( handled ){
    		event.preventDefault();
    	}
    	 */
    	eventToString: function(event) {
    		// Poor-man's hotkeys. See here for a complete implementation:
    		//   https://github.com/jeresig/jquery.hotkeys
    		var which = event.which,
    			et = event.type,
    			s = [];
    
    		if( event.altKey ) { s.push("alt"); }
    		if( event.ctrlKey ) { s.push("ctrl"); }
    		if( event.metaKey ) { s.push("meta"); }
    		if( event.shiftKey ) { s.push("shift"); }
    
    		if( et === "click" || et === "dblclick" ) {
    			s.push(MOUSE_BUTTONS[event.button] + et);
    		} else {
    			if( !IGNORE_KEYCODES[which] ) {
    				s.push( SPECIAL_KEYCODES[which] || String.fromCharCode(which).toLowerCase() );
    			}
    		}
    		return s.join("+");
    	},
    	/** Write message to console if debugLevel >= 1
    	 * @param {string} msg
    	 */
    	info: function(msg){
    		/*jshint expr:true */
    		($.ui.fancytree.debugLevel >= 1) && consoleApply("info", arguments);
    	},
    	/* @deprecated: use eventToString(event) instead.
    	 */
    	keyEventToString: function(event) {
    		this.warn("keyEventToString() is deprecated: use eventToString()");
    		return this.eventToString(event);
    	},
    	/** Return a wrapped handler method, that provides `this.super`.
    	 *
    	 * @example
    		// Implement `opts.createNode` event to add the 'draggable' attribute
    		$.ui.fancytree.overrideMethod(ctx.options, "createNode", function(event, data) {
    			// Default processing if any
    			this._super.apply(this, arguments);
    			// Add 'draggable' attribute
    			data.node.span.draggable = true;
    		});
    	 *
    	 * @param {object} instance
    	 * @param {string} methodName
    	 * @param {function} handler
    	 */
    	overrideMethod: function(instance, methodName, handler){
    		var prevSuper,
    			_super = instance[methodName] || $.noop;
    
    		// context = context || this;
    
    		instance[methodName] = function() {
    			try {
    				prevSuper = this._super;
    				this._super = _super;
    				return handler.apply(this, arguments);
    			} finally {
    				this._super = prevSuper;
    			}
    		};
    	},
    	/**
    	 * Parse tree data from HTML <ul> markup
    	 *
    	 * @param {jQueryObject} $ul
    	 * @returns {NodeData[]}
    	 */
    	parseHtml: function($ul) {
    		// TODO: understand this:
    		/*jshint validthis:true */
    		var classes, className, extraClasses, i, iPos, l, tmp, tmp2,
    			$children = $ul.find(">li"),
    			children = [];
    
    		$children.each(function() {
    			var allData, lowerCaseAttr,
    				$li = $(this),
    				$liSpan = $li.find(">span:first", this),
    				$liA = $liSpan.length ? null : $li.find(">a:first"),
    				d = { tooltip: null, data: {} };
    
    			if( $liSpan.length ) {
    				d.title = $liSpan.html();
    
    			} else if( $liA && $liA.length ) {
    				// If a <li><a> tag is specified, use it literally and extract href/target.
    				d.title = $liA.html();
    				d.data.href = $liA.attr("href");
    				d.data.target = $liA.attr("target");
    				d.tooltip = $liA.attr("title");
    
    			} else {
    				// If only a <li> tag is specified, use the trimmed string up to
    				// the next child <ul> tag.
    				d.title = $li.html();
    				iPos = d.title.search(/<ul/i);
    				if( iPos >= 0 ){
    					d.title = d.title.substring(0, iPos);
    				}
    			}
    			d.title = $.trim(d.title);
    
    			// Make sure all fields exist
    			for(i=0, l=CLASS_ATTRS.length; i<l; i++){
    				d[CLASS_ATTRS[i]] = undefined;
    			}
    			// Initialize to `true`, if class is set and collect extraClasses
    			classes = this.className.split(" ");
    			extraClasses = [];
    			for(i=0, l=classes.length; i<l; i++){
    				className = classes[i];
    				if(CLASS_ATTR_MAP[className]){
    					d[className] = true;
    				}else{
    					extraClasses.push(className);
    				}
    			}
    			d.extraClasses = extraClasses.join(" ");
    
    			// Parse node options from ID, title and class attributes
    			tmp = $li.attr("title");
    			if( tmp ){
    				d.tooltip = tmp; // overrides <a title='...'>
    			}
    			tmp = $li.attr("id");
    			if( tmp ){
    				d.key = tmp;
    			}
    			// Translate hideCheckbox -> checkbox:false
    			if( $li.attr("hideCheckbox") ){
    				d.checkbox = false;
    			}
    			// Add <li data-NAME='...'> as node.data.NAME
    			allData = _getElementDataAsDict($li);
    			if( allData && !$.isEmptyObject(allData) ) {
    				// #507: convert data-hidecheckbox (lower case) to hideCheckbox
    				for( lowerCaseAttr in NODE_ATTR_LOWERCASE_MAP ) {
    					if( allData.hasOwnProperty(lowerCaseAttr) ) {
    						allData[NODE_ATTR_LOWERCASE_MAP[lowerCaseAttr]] = allData[lowerCaseAttr];
    						delete allData[lowerCaseAttr];
    					}
    				}
    				// #56: Allow to set special node.attributes from data-...
    				for(i=0, l=NODE_ATTRS.length; i<l; i++){
    					tmp = NODE_ATTRS[i];
    					tmp2 = allData[tmp];
    					if( tmp2 != null ) {
    						delete allData[tmp];
    						d[tmp] = tmp2;
    					}
    				}
    				// All other data-... goes to node.data...
    				$.extend(d.data, allData);
    			}
    			// Recursive reading of child nodes, if LI tag contains an UL tag
    			$ul = $li.find(">ul:first");
    			if( $ul.length ) {
    				d.children = $.ui.fancytree.parseHtml($ul);
    			}else{
    				d.children = d.lazy ? undefined : null;
    			}
    			children.push(d);
    //            FT.debug("parse ", d, children);
    		});
    		return children;
    	},
    	/** Add Fancytree extension definition to the list of globally available extensions.
    	 *
    	 * @param {object} definition
    	 */
    	registerExtension: function(definition){
    		_assert(definition.name != null, "extensions must have a `name` property.");
    		_assert(definition.version != null, "extensions must have a `version` property.");
    		$.ui.fancytree._extensions[definition.name] = definition;
    	},
    	/** Inverse of escapeHtml().
    	 *
    	 * @param {string} s
    	 * @returns {string}
    	 */
    	unescapeHtml: function(s){
    		var e = document.createElement("div");
    		e.innerHTML = s;
    		return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
    	},
    	/** Write warning message to console.
    	 * @param {string} msg
    	 */
    	warn: function(msg){
    		consoleApply("warn", arguments);
    	}
    });
    
    }(jQuery, window, document));