Add folders to a toolbar automatically

GPSoftware Notes:

  • If you just want to add some files to a toolbar, you can drag them there directly while in Customize mode.

  • Or, if you want to add everything in or below a folder to a toolbar, you can do that using the Go FOLDERCONTENT command. Example here: Start Menu button

  • We don't really recommend modifying the toolbar XML files directly, by hand or by script, outside of exceptional situations, as it could cause problems with future versions.

  • All of that said, the code below may be useful to you if you want an example of modifying XML files via scripts.

--Leo


Hi, I make this script a long time ago and I think is time to share with you guys, mainly because I think it implements (very poorly) two things that have a lot of potentials: Modifying toolbars and GUI's. I'm doing this with the hope of that everyone can grab this ideas and make it more efficient/better stuff.
Feel free to use portions of my code to your own scripts, althought please just refer me as the original author.

Here you go:

Sites.js.txt (16.1 KB)

/*
---------------------------------------
---------------------------------------
GLOBAL VARIABLES
dlg			:=		Is used to show error messages, you don't have to configure anything.
template	:=		Here you can define your own button template to use with this script, if you don't want to use an extra
					file or the clipboard, just remember to put each line between single quotes, just like in the example below.
state,line	:=		If the toolbar is not open on the current Lister or the script can't get their state or line number, those 
					are the default values to use.
*/
var template = "";
template = [
			'<button backcol="none" display="icon" textcol="none" type="menu_button">',
			'	<label>&amp;name&amp;</label>',
			'	<tip>Ir a &amp;name&amp;</tip>',
			'	<icon1>#folder</icon1>',
			'	<function type="normal">',
			'		<instruction>Go &quot;&amp;dir&amp;&quot; KEYARGS &quot;ctrl:OPENINDEST NEWTAB=findexisting,tofront&quot; &quot;alt:NEWTAB=findexisting,tofront&quot; &quot;shift:NEW&quot;</instruction>',
			'	</function>',
			'	<button backcol="none" display="both" label_pos="right" textcol="none">',
			'		<label>&amp;name&amp;</label>',
			'		<tip>Ver contenido de &amp;name&amp;</tip>',
			'		<icon1>#newcommand</icon1>',
			'		<function type="normal">',
			'			<instruction>Go &quot;&amp;dir&amp;&quot; FOLDERCONTENT=button,nofiles </instruction>',
			'		</function>',
			'	</button>',
			'</button>'
			].join("\r\n");
var state = "top";	var line = 1;

var dlg = DOpus.dlg;

function OnInit(initData)
{
	initData.name = "Sites";
	initData.desc = "";
	initData.copyright = "";

	var cmd = initData.AddCommand();
	cmd.name = "Sites";
	cmd.method = "Sites";
	cmd.desc = "";
	cmd.label = "Sites";
	cmd.template = "TOOLBARNAME/K,POS/K/N,CONFIRM/S,PATHS/K/M,TEMPLATE/K[<fullfilepath>,clip],GUI/S,USEDISKLABELS/S";
}

function Sites(c)
{
	//Configure the dialog to show info/errors
	dlg.title = "Error";
	dlg.icon = "error";
	dlg.buttons = "Ok";
	dlg.window = c.func.sourcetab.lister;
	var paths = c.func.args.PATHS;
	if (paths != undefined)
	{
		var template = getTemplate(String(c.func.args.TEMPLATE));
		var nodes = (c.func.args.got_arg.GUI) ? Add_with_GUI(paths, template, c.func.args.got_arg.USEDISKLABELS) : Add_Paths(c.func.Dlg, paths, template, c.func.args.got_arg.CONFIRM);
		if (nodes.childNodes.length > 0)
			Do_The_Toolbar_Thing(c.func.args.TOOLBARNAME, nodes, c.func.args.POS, c.func.sourcetab.lister.toolbars, c.func.command);
		else
			alert("No buttons to add", "info");
		template = null;
		nodes = null;
	}
	else
		alert("????????", "error");
}

function Do_The_Toolbar_Thing (toolbar_name, nodes, pos, toolbars, com) 
{
	if (toolbar_name == undefined)
		toolbar_name = "sites";
	var toolbar = new Toolbar(toolbar_name);
	toolbar.addButtons(pos, nodes);
	toolbar.save();
	var toolbars = new Enumerator(toolbars);
	while (!toolbars.atEnd())
	{
		if (toolbars.item() == toolbar_name)
		{
			state = toolbars.item().group;
			line = toolbars.item().line;
			break;
		}
		toolbars.moveNext();
	}
	toolbars = null;
	com.RunCommand("Toolbar NAME=" + toolbar_name + " CLOSE");
	DOpus.Delay(5);
	com.RunCommand("Toolbar NAME=" + toolbar_name + " LOCAL STATE=" + state + " LINE=" + line);
	toolbar = null;
}

function Add_Paths (dialog, paths, template, conf) 
{
	var name;
	var dom = new ActiveXObject("Msxml2.DOMDocument.6.0");
	dom.async = false;
	var FSO = new ActiveXObject("Scripting.FileSystemObject");
	var nodeList = dom.createDocumentFragment();
	// alert("template:" + template, "info");
	for (var i = 0; i < paths.length; i++) {
		paths(i) = (paths(i).slice(-1) == "\\") ? paths(i).slice(0, -1) : paths(i);
		if (DOpus.FSUtil.GetType(paths(i), "a") == "dir")
		{
			name = paths(i).substring(paths(i).lastIndexOf("\\")+1);
			try
			{
				if (FSO.GetDrive(paths(i)).VolumeName)
					name = FSO.GetDrive(paths(i)).VolumeName;
			}
			catch(e){}
			if (conf)
			{
				//Show a dialog
				if (dialog.Request("The button with the following info will be added:\nPath:" + paths(i) + "\nName:" + name + "\nAre you sure?.", 
								"Yes|No", "Confirm button creation") == 0)
					continue;
			}
			try{
				dom.loadXML(template.replace(/&amp;dir&amp;/g, paths(i)).replace(/&amp;name&amp;/g, name));
				nodeList.appendChild(dom.documentElement);
			}
			catch(e) {alert(e.description, "error");}
		}
	};
	name = null;
	dom = null;
	FSO = null;
	return nodeList;
}

function Add_with_GUI (paths, template, USEDISKLABELS) 
{
	var gui = new GUIWindow();
	var dom = new ActiveXObject("Msxml2.DOMDocument.6.0");
	var FSO = new ActiveXObject("Scripting.FileSystemObject");
	var name;
	var nodeList = dom.createDocumentFragment();
	var html = 	[
				'<html><head>',
				'	<meta charset="utf-8">',
				'	<style type="text/css">',
				'		.todo {',
				'			font-family: "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", "DejaVu Sans", Verdana, sans-serif;',
				'			background-color: #FFF;',
				'			color: #333;',
				'			border: 1px solid #CCC;',
				'			padding-right: 9px;',
				'			padding-left: 9px;',
				'			padding-bottom: 0px;',
				'		}',
				'		.name {',
				'			border: 1px solid #CCC;',
				'			font-family: Segoe, "Segoe UI", "DejaVu Sans", "Trebuchet MS", Verdana, sans-serif;',
				'			font-size: 12px;',
				'			font-style: normal;',
				'			height: 25px;',
				'			width: 25%;',
				'		}',
				'		.name:hover {',
				'			border-color: #C00;',
				'			border-width: 1px;',
				'		}',
				'		.path {',
				'			border: 1px solid #CCC;',
				'			font-family: Segoe, "Segoe UI", "DejaVu Sans", "Trebuchet MS", Verdana, sans-serif;',
				'			font-size: 12px;',
				'			font-style: normal;',
				'			height: 25px;',
				'			width: 70%;',
				'		}',
				'		.path:hover {',
				'			border-color: #C00;',
				'			border-width: 1px;',
				'		}',
				'		h1 {',
				'			color: #535353;',
				'			font-size: 18px;',
				'			font-weight: normal;',
				'			margin-top: -1px;',
				'			background-color: rgb(242, 242, 242);',
				'			font-family: Segoe, "Segoe UI", "DejaVu Sans", "Trebuchet MS", Verdana, sans-serif;',
				'			border: 1px solid #CCCCCC;',
				'			margin-right: -10px;',
				'			margin-left: -10px;',
				'			padding: 8px;',
				'		}',
				'	</style></head><body>',
				'	<form method="post" name="form1" class="todo" id="form1" accept-charset="UTF-8">',
				'		<h1>Add Paths</h1>'
				];
	for (var i = 0; i < paths.length; i++) {
		paths(i) = (paths(i).slice(-1) == "\\") ? paths(i).slice(0, -1) : paths(i);
		name = paths(i).substring(paths(i).lastIndexOf("\\")+1);
		try
		{
			if (FSO.GetDrive(paths(i)).VolumeName)
				name = FSO.GetDrive(paths(i)).VolumeName;
		}
		catch(e){}
		if (!FSO.FileExists(paths(i)))
		{
			html.push(
				'<p><input type="checkbox" checked="true" name="checkbox">',
				'<input name="textfield" type="text" class="name" id="name' + (i + 1) + '" value="' + name + '">',
				'<input name="keywords" type="text" class="path" id="path' + (i + 1) + '"  value="' + paths(i) + '"></p>'
				);
		}
	};
	html.push(
				'<p align="right">',
				'<input type=\'button\' id=\'add\' value=\'Add\' onClick=\'document.getElementById(\"control\").value=\"done\"\'>',
				'<input type=\'button\' id=\'exit\' value=\'Close\' onClick=\'document.getElementById(\"control\").value=\"exit\"\'></p></form>',
				'<input type=\'hidden\' id=\'control\' value=\'waiting\'>',
				'</body></html>');
	gui.SetHTML(html.join("\r\n"));
	gui.SetTitle("Add Paths");
	gui.Center();
	gui.SetVisible(true);
	var control;
	while ((control = gui.GetValueById("control")) == "waiting")
	{
		gui.Focus();
		DOpus.Delay(500);
	}
	gui.SetVisible(false);
	if (control == "done")
	{
		var form = gui.GetDocument().form1;
		var label, dn;
		for (var i = 0; i < form.length - 2; i = i + 3) {
			// DOpus.Output(form.elements[i].checked);
			// DOpus.Output('"' + form.elements[i+1].value + '"');
			// DOpus.Output('"' + form.elements[i+2].value + '"');
			if (form.elements[i].checked && DOpus.FSUtil.GetType(form.elements[i+2].value, "a") == "dir")
			{
				label = FSO.GetDrive((dn = FSO.GetDriveName(form.elements[i+2].value))).VolumeName;
				if (label && USEDISKLABELS)
					form.elements[i+2].value = form.elements[i+2].value.replace(dn, "{alias|$" + label + "}");
				try{
					dom.loadXML(template.replace(/&amp;dir&amp;/g, form.elements[i+2].value).replace(/&amp;name&amp;/g, form.elements[i+1].value));
					nodeList.appendChild(dom.documentElement);
				}
				catch(e) {alert(e.description, "error");}
			}
		};
		form = null;
	}
	gui.Quit();
	dom = null;
	FSO = null;
	gui = null;
	return nodeList;
}


function getTemplate (temp) 
{
	if (DOpus.FSUtil.Exists(temp))
	{
		var dom = new ActiveXObject("Msxml2.DOMDocument.6.0");
		try {
		dom.load(temp);
		temp = dom.selectSingleNode("//button").xml;
		}
		catch(e){}
		dom = null;
	}
	else if (temp.toLowerCase() == "clip" && DOpus.GetClipFormat() == "text")
		temp = DOpus.GetClip();
	else
		temp = template;
	return temp;
}



function Toolbar(name)
{
	this.agregar = function(name, attrs) {
		var elem = this.xml.createElement(name);
		var attr;
		for (attr in attrs)
		{
			elem.setAttribute(attr, attrs[attr]);
		}
		this.xml.documentElement.appendChild(elem);
		return elem;
	};
	this.addButton = function(pos, attrs, props, functions) {
		var attr, prop, temp;
		var button = this.xml.createElement("button");
		for (attr in attrs)
		{
			button.setAttribute(attr, attrs[attr]);
		}
		if (typeof props == "object")
		{
			for (prop in props)
			{
				temp = this.xml.createElement(prop);
				temp.text = props[prop];
				button.appendChild(temp);
				temp = null;
			}
		}
		if (functions != undefined)
		{
			var f = this.xml.createElement("function");
			f.setAttribute("type", functions[0]);
			var i, inst;
			for (i = 1; i < functions.length; i++) {
				inst = this.xml.createElement("instruction");
				inst.text = functions[i];
				f.appendChild(inst);
				inst = null;
			};
			button.appendChild(f);
			f = null;
		}
		if (typeof pos["ref"] == "number")
			pos["ref"] = this.getButton(pos["ref"]);
		if (pos["ref"] == null)
			pos["mode"] = "append";
		switch(pos["mode"])
		{
			case "replace"	:
				this.buttons.replaceChild(button, pos["ref"]);
				break;
			case "within"	:
				switch(pos[ref].getAttribute("type"))
				{
					case "menu"			:
					case "menu_button"	:
					case "three_button"	:
						pos["ref"].appendChild(button);
						break;
				}
				break;
			case "append"	:
				this.buttons.appendChild(button);
				break;	
			default	:
				return null;
		}
		return button;
	};
	this.addButtons = function(pos, buttonList) {
		var ref;
		if (typeof pos != "number" || pos < 1)
			ref = this.getButtonByContent("field_type", "spacer");
		else 
			ref = this.getButton(pos);
		if (ref == undefined)
			this.buttons.appendChild(buttonList);
		else
			this.buttons.insertBefore(buttonList, ref);
		ref = null;
	};
	this.getButtonByContent = function(attr, value) {
			return this.buttons.selectSingleNode("//button[@" + attr + "='" + value + "']");
	};
	this.getButton = function(pos) {
			return this.buttons.childNodes[pos-1];
	};
	this.save = function() {
		this.transform();
		this.xml.save(this.file);
	};
	this.transform = function() {
		var xsl = new ActiveXObject("Msxml2.DOMDocument.6.0");
		var style = '<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">\r\n';
		style = style + '<xsl:output method="xml" indent="yes" encoding="UTF-8"/>\r\n';
		style = style + '<xsl:template match="@*|node()">\r\n';
		style = style + '<xsl:copy>\r\n';
		style = style + '<xsl:apply-templates select="@*|node()"/>\r\n';
		style = style + '<xsl:for-each select="@*">\r\n';
		style = style + '<xsl:text></xsl:text>\r\n';
		style = style + '</xsl:for-each>\r\n';
		style = style + '</xsl:copy>\r\n';
		style = style + '</xsl:template>\r\n';
		style = style + '</xsl:stylesheet>\r\n';
		xsl.loadXML(style);
		this.xml.transformNodeToObject(xsl,this.xml);
		xsl = style = null;
	};


	this.file = DOpus.Aliases("buttons").path + "\\" + name + ".dop";
	this.xml = new ActiveXObject("Msxml2.DOMDocument.6.0");
	with (this.xml)
	{
		async = false;
		// validateOnParse = true;
		// resolveExternals = true;
		setProperty("SelectionLanguage", "XPath");
	}
	this.buttons = null;
	//If the toolbar exists on disk, we load them
	if (DOpus.FSUtil.Exists(this.file))
	{
		this.xml.load(this.file);
		this.buttons = this.xml.selectSingleNode("//buttons");
	}
	//Otherwise create a default one
	else
	{
		DOpus.Output("Creating the toolbar " + name);
		var root = this.xml.createElement("toolbar");
	    root.setAttribute("version", "11.0");
		this.xml.appendChild(root);
		root = null;
		// Add the wallpaper element
		this.agregar("wallpaper", {	enabled: "no",
								inheritable: "yes",
								type: "toolbar" });
		// Add the Buttons element
		this.buttons = this.agregar("buttons", 
								{	backcol: "none",
									display: "icon",
									textcol: "none",
									type: "menu"});

		this.addButton(	{ 	ref: -1,
							mode: "append"},
						{	backcol: "none",
							display: "label",
							field_type: "spacer",
							textcol: "none",
							size: "full",
							separate: "yes"},
						{	label: "spacer",
							icon1: "#spacer"},
						[	"normal",
							"Set SPACER"]);
	}
}

function GUIWindow()
{
	this.objExplorer = new ActiveXObject("InternetExplorer.Application");
	this.objExplorer.Navigate("about:blank");
	this.width = (this.objExplorer.document.parentWindow.screen.availWidth * 60) / 100;
	this.height = this.objExplorer.document.parentWindow.screen.availHeight - 150;	
	this.top = 100;
	this.left = 200;
	with(this.objExplorer)
	{		   
		// FullScreen		= 1;
		ToolBar   		= 0;
		StatusBar 		= 0;
		Width     		= this.width;
		Height    		= this.height; 
		Left      		= this.left;
		Top       		= this.top;
		Visible   		= 0;
		Resizable 		= 0;
		AlwaysRaised  	= 1;
		document.title = 'GUI with Jscript';
	}


	this.Center		=	function()
	{
		var height = this.GetWindow().screen.availHeight;
		var width = this.GetWindow().screen.availWidth;
		wheight = this.GetDocument().form1.clientHeight + 70;
		this.SetSize(this.width, (wheight > height) ? this.height : wheight);
		this.MoveTo(width/2 - (this.GetDocument().documentElement.clientWidth/2),height/2 - (this.GetDocument().documentElement.clientHeight/2));
	}

	this.MoveTo			= function (x, y)
	{
		this.left = this.objExplorer.left = x;
		this.top = this.objExplorer.top = y;
	}

	this.SetTitle    = function(title)
	{
		this.objExplorer.document.title = title;
	}
	this.GetDocument = function()
	{
		return this.objExplorer.document;
	}
	this.SetHTML     = function(html)
	{
		this.objExplorer.document.write(html);
	}
	this.Quit        = function()
	{
		try
		{
		this.objExplorer.quit();
		this.objExplorer = null;
		}
		catch(e){}
	}
	this.SetSize     = function(width,height)
	{
		this.width = this.objExplorer.Width = width;
		this.height = this.objExplorer.Height = height;
	}
	this.GetWindow   = function()
	{
		return this.objExplorer.document.parentWindow;
	}    
	this.ScrollTo    = function(x,y)
	{
		objExplorer.document.parentWindow.scrollTo(x,y);
	}
	this.SetVisible  = function(tf)
	{
		try {
			this.objExplorer.Visible=tf;
		} catch(e){}
	}
	this.Focus = function()
	{
		this.objExplorer.document.focus();
	}

	this.GetValueById = function(id)
	{
		try
		{
		return this.objExplorer.document.getElementById(id).value;
		}
		catch (e)
		{
			return "exit";
		}
	}

	this.SetValueById = function(id,value)
	{
		this.objExplorer.document.getElementById(id).value=value;
	}

	this.WaitOnId = function(id)
	{
		var elem = this.objExplorer.document.getElementById(id);
		var val= elem.value;
		while(elem.value == val)
		{
			DOpus.Delay(100);
		}
		return elem.value;
	}
}

function alert(message, icon, title)
{
	dlg.message = message;
	if (title != undefined)
		dlg.title = title;
	if (/warning|error|info|question/.exec(icon) != null)
		dlg.icon = icon;
	dlg.Show();
}

Remember this I'm doing with the hope that someone can improve the ideas of modifying toolbars and GUI's via scripting. If you achieve this, please share with us!!!
Have fun!!!

Then, one possible use in a button could be:

@dironly
Sites TEMPLATE="{alias|buttons}\template.dcf" PATHS {allfilepath} {sourcepath} GUI TOOLBARNAME="sitios" USEDISKLABELS 

So no one is interested in modifying toolbars nor creating IE GUi's via scripting?
I guess I was wrong...

Creating IE GUIs with scripting is somethign I investigated today myself, that is interesting indeed as there seems to be no framework available for 64bit to create windows forms.
For 32bit I digged home.hccnet.nl/p.vd.klugt/Documentation.htm, which is really nice, sadly it doesn't fit nowadays 64bit needs.

Then I needed to read your code to actually get an idea of what this is really about and how it works (it creates a fully fledged xml representation of a toolbar file). I think you should have explained in more detail what goes on, especially if we are about to put 600 lines of code to work! o))

A screenshot of your internet explorer (you can type that instead of IE, to make things more clear again) GUI surely would have spiced things up as well. Your script worked for me at a quick test. The resulting buttons did not show a label though and the internet explorer windows was just 50px tall and not resizable, so I could not see it in its full beauty! o)

Regarding the IE-GUI thing, your GUIWindow-object/class for making life easier is surely worth building upon. I stumpled upon really aged articles like this today, which core functionality you obviously transported to js as well, thanks! o) techrepublic.com/article/des ... -occasion/

What's the actual reason you did this? I just tried to add a bunch of folders to a toolbar and because I can drag several at once to any toolbar I think this task is quite easy and fast as it is.

No question about your IE GUI stuff, that should definitely be handy for things to come I guess. o)

No reason more than encourage other users to develop further this two ideas: Gui's and toolbar manipulation via scripting. I believe this have great potential, if the proper people can develope a better coding(I know my code is crap), I imagine something like create buttons that dinamically appear on certain conditions, or more elaborated Gui's, so your imagination is the limit. But as I say, I just posted this to turn the light about these ideas, so more talented and skilled people can develop a better way of achieve this.
So maybe the "add selected folders to a toolbar" doesn't look something awesome (for me is useful), is just an example that make use of the 2 ideas.

[broken image link removed]

PD:This is how it looks on my computer.

You can use your own template (wich is per ex. the one than you get when copy a button froom a toolbar) and edited to create your own defined button (let's says three-button or whatever you want), with the procedure you say not, since is predefined and not configurable.
Besides that, is just an example of how to edit a toolbar via scripting. So anyone can grab a portion of the code to get the idea and then use as pleased.
PD:The GUI is via Internet Explore Active X, so I don't see why this doesn't have to work on a 64 bits machine.

Ok, thanks! o) I think it's much clearer now what's this all about.

Regarding the 64bit, I guess you got me wrong a bit, I didn't mean to say that the iexplorer GUI wouldn't work on x64. I was talking about already existing stuff out there with explicit purpose to create windows and forms from windows scripting host supported languages. These librarys all seem to be limited to 32bit. As feature packed as some of these are, they are practically useless for most of us running 64bit now. Maybe there are clever people porting these to x64 architecture, but it's doubtful as you can do easier and quicker these days with Powershell and WPF to get scripted GUIs to the screen on 64bit machines. I once did not care about powershell/.Net not being directly usable in DO, but one must admit, it would make life easier here and there.

Just two quick GUI examples with powershell and wpf/xaml:
learn-powershell.net/2012/09/13/ ... st-window/
gallery.technet.microsoft.com/sc ... n-720ff7ee

This one is an option too. Allows you to use Powershell from a COM Object :smiley: :smiley:

Thank you for linking that. While searching for Powershell to COM connectors/bridges I came across this as well, but I did not followed this one, as it needed registration and also because the site is called SAPIEN, I assumed this had something to do with SAP, that strange company selling strange consultancy and strange software. o)

Now I took the time to get that ActiveXPosh-thing going and getting WPF-GUIs/powershell scripts to work with DO (by not running powershell.exe of course), which is not easy by itself, as WPF-GUIs need powershell scripts to run in a sta-thread (single appartment thread), powershell defaults to multi appartment threads "of course" and there's no builtin way to switch the thread-model easily. So this was a real journey. That ActiveXPosh-thing is limited in ways I expected from this kind of "tunnel". What you get is some kind of powershell container you can grab into to fetch what you need, but iterating over a powershell hashmap in jscript is therefor not possible for example. We'll see if interconnectivity can be improved with a js-wrapper or something to make life easier, but this really has potential and is something to work on. o)

Here's a small demo of a wpf-window with simple controls tied to DO. This belongs into a new thread I think..


@tbone:
Hey I have no longer to download the ActiveXPosh-thing installer, could you be please so kindly enough to share it here?
Also can you share your scripts than are you talking about?

I opened a new thread for this some seconds ago and explained what I did and what is necessary to get this to work.

I will do a another one here in the scripting section to share more details and the needed components, but while you wait, the linked thread may be interesting for you as well.

You think we can share the ActiveXPosh-Download here? I mean, basically it is free but I don't know exactly if we are allowed to do so right here. Leo?
You can send me an email, I'm gonna reply to you and attach things if that's ok -> mb_selfdestruct01 a#t steax.net

I hope it got through now! Took me 3 attempts, that mail provider of yours is hardcore when it comes to attachments. o)
In the meantime I looked for license information for the posh-container thing and did not encounter anything, which would keep me from spreading it. It was told to be freely available even on a microsoft blog, so anytime soon it's going to be attached and packaged with the other components required.