PDA

View Full Version : Drupal menu Ext JS integration



dalad
6 Oct 2008, 1:29 AM
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.
http://img528.imageshack.us/img528/7725/extjsmenuda6.jpg (http://profile.imageshack.us/user/digitalillusion)
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, write 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 ;)