• 10ott
    Categories: Programming Commenti disabilitati

    Passing arguments to the function repeated in setInterval is not implemented in Internet explorer; even if there is a documented way to pass parameters to it, this way only works in IE for static parameters. What about, for example, if you need to set an interval for a function that, in a certain moment, clears itself?

    Fortunately, javascript can do closures (as Actionscript does); which means that, having two nested functions, you can still access outer variables from the inner function even if the outer one has already terminated execution. Using this trick, you can define setInterval parameters as outer scope vars; in other words:

    function outerScope() {
        var arg = "Hello world!";
        var innerFn = function() {
            alert(arg);
            clearInterval(interval);
        };
        var interval = setInterval(innerFn(), 1000);
    }
    outerScope();

    The code above will alert a message after one second, then clear the repeating event. This could also be done with setTimeout as obviously the same applies to setTimeout. It's elegant and cross-browser. Knowing language characteristics can help you write much less code...

  • 06ott
    Categories: Programming Commenti disabilitati

    Drupal menu Ext JS integration

    Did you ever need to use drupal with ext js? If you did, you probably wanted to use ext also for drupal main menu. Now, there is a way to display all sidebar blocks into an accordion panel, preserving html/javascript functionality.

    First step is to load ext library in one of your modules. You can accomplish this task by calling the init hook of the module, in my case called "extjs":

    function extjs_init() {
    	drupal_add_css("javascript/ext/resources/css/ext-all.css");
    	drupal_add_js("javascript/ext/adapter/ext/ext-base.js");
    	drupal_add_js("javascript/ext/ext-all.js");
    
        return $block;
    }

    Then, in the block hook, include the following html:

    <div id="extjs_sidebar"></div>
    <div id="extjs_smartbar"></div>
    <div id="extjs_tasksbar"></div>
    <script type="text/javascript">
    
    	function createCookie(name,value,days) {
    		if (days) {
    			var date = new Date();
    			date.setTime(date.getTime()+(days*24*60*60*1000));
    			var expires = "; expires="+date.toGMTString();
    		}
    		else var expires = "";
    		document.cookie = name+"="+value+expires+"; path=/";
    	}
    
    	function readCookie(name) {
    		var nameEQ = name + "=";
    		var ca = document.cookie.split(';');
    		for(var i=0;i < ca.length;i++) {
    			var c = ca[i];
    			while (c.charAt(0)==' ') c = c.substring(1,c.length);
    			if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
    		}
    		return null;
    	}
    
    	// Written by Jonathan Snook, http://www.snook.ca/jonathan
    	// Add-ons by Robert Nyman, http://www.robertnyman.com
    	function getElementsByClassName(oElm, strTagName, strClassName){
    		var arrElements = (strTagName == "*" && oElm.all)? oElm.all : oElm.getElementsByTagName(strTagName);
    		var arrReturnElements = new Array();
    		strClassName = strClassName.replace(/\-/g, "\\-");
    		var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)");
    		var oElement;
    		for(var i=0; i<arrElements.length; i++){
    			oElement = arrElements[i];
    			if(oRegExp.test(oElement.className)){
    				arrReturnElements.push(oElement);
    			}
    		}
    		return (arrReturnElements)
    	}
    
         /* List of all DOM event handler names.
         */
         var dom_events =
         ["onblur", "onfocus", "oncontextmenu", "onload",
         "onresize", "onscroll", "onunload", "onclick",
         "ondblclick", "onmousedown", "onmouseup", "onmouseenter",
         "onmouseleave", "onmousemove", "onmouseover",
         "onmouseout", "onchange", "onreset", "onselect",
         "onsubmit", "onkeydown", "onkeyup", "onkeypress",
         "onabort", "onerror"]; // ondasher, onprancer, etc.
    
         /*
          Fixes copy errors introduced by {@link element#cloneNode}, e.g. failure to copy classically-registered event handlers and the value property.
          @param {element} o The original DOM element
          @param {element} copy The result of o.cloneNode()
          @return {element} A modified copy with event handlers maintained
          */
          function fix_dom_clone(o, copy) {
    		if(o != "undefined" && copy != "undefined") {
    			for (var i = 0;i < dom_events.length;i++) {
    				var event = dom_events[i];
    				if (event in o) { copy[event] = o[event]; }
    			}
    			if ("value" in o) { copy.value = o.value; }
    			// recur
    			var o_kids = o.childNodes;
    			var c_kids = copy.childNodes;
    			for (i = 0;i < o_kids.length;i++) {
    				fix_dom_clone(o_kids[i], c_kids[i]);
    			}
    		}
          }
    
    	Ext.onReady(function(){
    
    		Ext.QuickTips.init();
    
    		/*
    		 * ================  Ricerca Altri Moduli ==================
    		 */
    		var elements = getElementsByClassName(document.getElementById("sidebar-left"), "div", "block");
    		var avoidSidebarBlock = new RegExp('(^|\\s)block-sidebar(\\s|$)');
    		var titleTag=new RegExp("<h2 .*?>(.*?)</h2>","i");
    		var reRes, childs;
    		var blocks = new Array(); var blockCopies = new Array(); var titles = new Array(); var j = 0;
    		for(var i = 0; i < elements.length; i++) {
    
    			if (avoidSidebarBlock.test(elements[i].className) ) {
    			} else
    			{
    				html = document.getElementById(elements[i].id).innerHTML;
    				reRes=titleTag.exec(html);
    				titles[j] = (reRes) ? reRes[1] : "";
    				// Prende il div di contenuto del blocco drupal. E' il secondo dei 2 div annidati nel div blocco
    				childs = elements[i].childNodes;
    				// ie non ritorna i TextNodes!!!
    				// ie non ritorna i TextNodes!!!
    				for(k = 0; k < childs.length; k++) {
    					if(childs.item(k).className == "content") {
    						blocks[j] = childs.item(k);
    						blockCopies[j] = childs.item(k).cloneNode(true);
    					};
    				}
    
    				j++;
    
    			}
    		}
    
    		// Legge il cookie impostato
    		var lastActive = readCookie("sideBar_mainmenu_selTab");
    
    		// Crea dei pannelli che salvano lo stato su cookie
    		var blockItems = new Array();
    		for (i = 0; i < blocks.length; i++) {
    			blockItems[i] = {
    				title: titles[i],
    				html: '<div id="sideBarBlock'+i+'"></div>',
    				id: 'sideBar_mainmenu_Tab'+i,
    				listeners: {
    					beforeexpand: function() {
    						document.cookie = createCookie("sideBar_mainmenu_selTab", this.getId());
    					}
    				}
    			};
    
    			if(lastActive == blockItems[i].id)
    				blockItems[i].collapsed = false;
    			else
    				blockItems[i].collapsed = true;
    		}
    
    		/*
    		 * ================  Barra laterale  =======================
    		 */
    		var lastCollapse = readCookie("sideBar_mainmenu_collapse");
    		if(lastCollapse == null) lastCollapse = "false";
    		var bd = Ext.get("extjs_sidebar");
    		var sideBar	 = new Ext.Panel({
    			title: 'Men&ugrave; principale',
    			layout:'accordion',
    			collapsible: true,
    			id: 'sideBar_mainmenu',
    			defaults: {
    				// applied to each contained panel
    				bodyStyle: 'padding:5px; overflow: auto;'
    			},
    			layoutConfig: {
    				// layout-specific configs go here
    				titleCollapse: true,
    				animate: true,
    				activeOnTop: false,
    				fill: false
    			},
    			width: 200,
    			autoHeight: true,
    			items: blockItems,
    			listeners: {
    					beforeexpand: function() {
    						document.cookie = createCookie("sideBar_mainmenu_collapse", false);
    					},
    					expand: function() {
    						this.doLayout();
    					},
    					beforecollapse: function() {
    						document.cookie = createCookie("sideBar_mainmenu_collapse", true);
    					}
    				}
    		});
    
    		sideBar.render(bd);
    		if(lastCollapse == "true")
    			sideBar.collapse(false);
    
    		for (i = 0; i < blocks.length; i++) {
    			fix_dom_clone(blocks[i], blockCopies[i]);
    			document.getElementById("sideBarBlock"+i).appendChild(blocks[i]);
    		}
    	});
    </script>
    

    I hope not to have made copy/paste errors. Notify me if you find any. Happy tweaking to those who need this!