MozillaZine

Dev : Extensions : Example Code : Adding Drag and Drop to Statusbarpanel

From MozillaZine Knowledge Base

drag.js file

Add the code below to a javascript file and put it in the same directory as the overlay file. Change the flavour variable and the name of the statusbarPanel variable. The statusbarPanel variable should have the same value as the id of the statusbarpanel in your extension.

const Ext_statObserver = {
init: function () {
  this.flavour = "Ext_Fla";//any text you want but should have something to do with the extension name
  this.statusbarPanel = "Ext__stat";//id of the statusbarpanel to drag
  this.statbar = "status-bar";//name of statusbar
 //alert(this.statbar);
  prefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService).getBranch("extensions.tagExt_.");
  document.getElementById(this.statbar).insertBefore(document.getElementById(this.statusbarPanel),document.getElementById(this.prefs.getCharPref("insertAfter")));
},
getSupportedFlavours: function () {
  var flavours = new FlavourSet();
  flavours.appendFlavour(this.flavour);//text/unicode
  return flavours;
},
onDragStart: function (evt,transferData,action){
  var elme = evt.target;
  while(elme.id != this.statusbarPanel){
    elme =elme.parentNode;
  }
  var txt=elme.getAttribute("id");
  transferData.data=new TransferData();
  transferData.data.addDataForFlavour(this.flavour,txt);
  var status = document.getElementById(this.statusbarPanel);
  var statusbar = document.getElementById(this.statbar);
  var child = statusbar.firstChild;
  var x = 0;
  while (child) {
    if (child != status) {
      if (!child.id) {
        var newId = "statusbarpanel-noID"+x;
        while (document.getElementById(newId)) newId += "x"+x;
        child.id = newId;
        child.setAttribute("persist", new String("id" + (child.persist ? " "+child.persist : "")) );
        x++;
      }
      if (child.childNodes.length == 0 && document.getAnonymousNodes(child).length == 0)
        child.setAttribute("abnochildren", true);
      child.addEventListener("dragenter", function(event) { nsDragAndDrop.dragEnter(event,Ext_statObserver); }, false);
      child.addEventListener("dragover", function(event) { nsDragAndDrop.dragOver(event,Ext_statObserver); }, false);
      child.addEventListener("dragdrop", function(event) { nsDragAndDrop.drop(event,Ext_statObserver); }, false);
    }
    child = child.nextSibling;
  }
  window.addEventListener("dragexit", function(event) { nsDragAndDrop.dragExit(event,Ext_statObserver); }, true);
},
onDragEnter: function (evt,flavour,session){
  var elm = evt.target;
  while(elm.nodeName != "statusbarpanel"){
    elm = elm. parentNode;
  }
},
onDragOver: function (evt,flavour,session){
  var elm = evt.target;
  while(elm.parentNode.nodeName != "statusbar"){
    elm = elm.parentNode;
  }
},
onDrop: function (evt,dropdata,session){
  if (dropdata.data!=""){
    prefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService).getBranch("extensions.tagExt_.");
    var elm = evt.target;
    while(elm.nodeName != "statusbarpanel"){
      elm = elm.parentNode;
    }
    var elem = document.getElementById(dropdata.data);
    var parent = elem.parentNode;
    elem.setAttribute("insertafter",""+elm.getAttribute("id"));
    parent.removeChild(elem);
    parent.insertBefore(elem,elm);
    prefs.setCharPref("insertAfter",elm.getAttribute("id")+"");
 }
}
};
window.addEventListener('load', Ext_statObserver.init, false); 

swap "Ext_" with the name of your extension (eg, if your extension is called mozFind then enter mozfind_

If you cant get it to work have a look at the code from bbTager:

const bbstatObserver = {
 init: function () {
   this.flavour = "bbFla";//any text you want but should have something to do with the extension name
   this.statusbarPanel = "bb_stat";//id of the statusbarpanel to drag
   this.statbar = "status-bar";//name of statusbar
  //alert(this.statbar);
   prefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService).getBranch("extensions.tagbb.");
  document.getElementById(this.statbar).insertBefore(document.getElementById(this.statusbarPanel),document.getElementById(this.prefs.getCharPref("insertAfter")));
 },
 getSupportedFlavours: function () {
   var flavours = new FlavourSet();
   flavours.appendFlavour(this.flavour);//text/unicode
   return flavours;
 },
 onDragStart: function (evt,transferData,action){
   var elme = evt.target;
   while(elme.id != this.statusbarPanel){
     elme =elme.parentNode;
   }
   var txt=elme.getAttribute("id");
   transferData.data=new TransferData();
   transferData.data.addDataForFlavour(this.flavour,txt);
   var status = document.getElementById(this.statusbarPanel);
   var statusbar = document.getElementById(this.statbar);
   var child = statusbar.firstChild;
   var x = 0;
   while (child) {
     if (child != status) {
       if (!child.id) {
         var newId = "statusbarpanel-noID"+x;
         while (document.getElementById(newId)) newId += "x"+x;
         child.id = newId;
         child.setAttribute("persist", new String("id" + (child.persist ? " "+child.persist : "")) );
         x++;
       }
       if (child.childNodes.length == 0 && document.getAnonymousNodes(child).length == 0)
         child.setAttribute("abnochildren", true);
       child.addEventListener("dragenter", function(event) { nsDragAndDrop.dragEnter(event,bbstatObserver); }, false);
       child.addEventListener("dragover", function(event) { nsDragAndDrop.dragOver(event,bbstatObserver); }, false);
       child.addEventListener("dragdrop", function(event) { nsDragAndDrop.drop(event,bbstatObserver); }, false);
     }
     child = child.nextSibling;
   }
   window.addEventListener("dragexit", function(event) { nsDragAndDrop.dragExit(event,bbstatObserver); }, true);
  },
  onDragEnter: function (evt,flavour,session){
   var elm = evt.target;
   while(elm.nodeName != "statusbarpanel"){
     elm = elm. parentNode;
   }
 },
 onDragOver: function (evt,flavour,session){
   var elm = evt.target;
   while(elm.parentNode.nodeName != "statusbar"){
     elm = elm.parentNode;
   }
 },
 onDrop: function (evt,dropdata,session){
   if (dropdata.data!=""){
     prefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService).getBranch("extensions.tagbb.");
     var elm = evt.target;
     while(elm.nodeName != "statusbarpanel"){
       elm = elm.parentNode;
     }
     var elem = document.getElementById(dropdata.data);
     var parent = elem.parentNode;
     elem.setAttribute("insertafter",""+elm.getAttribute("id"));
     parent.removeChild(elem);
     parent.insertBefore(elem,elm);
     prefs.setCharPref("insertAfter",elm.getAttribute("id")+"");
  }
 }
};
window.addEventListener('load', bbstatObserver.init, false);

overlay.xul file

This is the overlay xul file where you add the statusbarpanel

<?xml version="1.0"?>
<overlay id="extensionName" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
  <script src="chrome://global/content/nsDragAndDrop.js" type="application/x-javascript" />
  <script src="chrome://global/content/nsTransferable.js" type="application/x-javascript" />
  <script src="chrome://extName/content/drag.js" type="application/x-javascript" />
  <statusbar id="status-bar">
    <statusbarpanel id="Extname"
                    ondraggesture="nsDragAndDrop.startDrag(event,Ext_statObserver)">
      <description>statusbar</description>
    </statusbarpanel>
  </statusbar>
</overlay>

Thanks to

The developers of Adblock. I used some of the sourcecode but modified it a bit. With this code you can drop one statusbarpanel on top of another one that can also be dragged.

Ihoss, April 2005