Make a Screenshot of a Widget

Yahoo! Widgets 4 introduced an interesting new feature - the saveImageToFile method of many objects, giving developers the ability to generate a PNG or JPEG image of parts of a running Widget. This is really cool because it includes the alpha transparency when you save as a PNG.

However, one feature was inexplicably missing - the ability to call saveImageToFile on a whole window!

I created the following function (and helper functions) in order to assist with making screenshots of entire Widgets. Why? Possibly because I'm strange.

Using this requires Yahoo! Widgets 4. I haven't tested it on later versions. It will create horrible errors on earlier versions.

Usage

Include all the code below, and call screenshot(myContainer, path). myContainer can be a Window, a Frame, or any container-type Object.

/** * screenshot(container, path) * screenshot(container) * Generates a screenshot of a container (i.e., a Frame or Window object) * If path is not passed, uses a default of "Screenshot.png". */ function screenshot(container, path, leaveMess) { if (!path) { path = screenshot.defaultFilename; }	var extension = screenshot.getExtension(path); var type = screenshot.extensionMap[extension.toLowerCase]; if (!type) { type = extension.toLowerCase; }	path = screenshot.getUniqueFilename(path); if (container.saveImageToFile) { var myContainer = container; } else { // create copies of everything in a new Frame var myContainer = new Frame; screenshot.copyChildren(container, myContainer); }	myContainer.saveImageToFile(path, type); if (!leaveMess) { var t;		while (t = screenshot.mess.pop) { filesystem.remove(t); }	}	return path; }

screenshot.mess = [];

screenshot.getUniqueFilename = function(path) { var basename = screenshot.getFilenameWithoutExtension(path); var extension = screenshot.getExtension(path); var iterator = 0; while (filesystem.itemExists(path)) { iterator++; path = basename + iterator + '.' + extension; }	return path; }

screenshot.copyChildren = function(src, dst) { for (var o = src.firstChild; o; o = o.nextSibling) { if (o instanceof Canvas || o instanceof Frame || o instanceof TextArea || o instanceof Text) { var rendered = true; var t = new Image; t.src = screenshot(o, 'temporary_.png', true); screenshot.mess.push(t.src); } else { var rendered = false; var t = new o.constructor; if (o.firstChild) { screenshot.copyChildren(o, t); }		}		dst.appendChild(t); for (var i in o) { if (screenshot.ignoreAttributes.test(i)) { continue; }			if (rendered && screenshot.ignoreRenderedAttributes.test(i)) { continue; }			t[i] = o[i]; }	} };

screenshot.ignoreAttributes = /(^contextMenuItems$|^id$|^.*Child$|^.*Sibling$|^name$|^on.*$|^parentNode$|^subviews$|^superview$|^tooltip$|^window$|^.LineSize$|^.ScrollBar$|^tracking$|^srcHeight$|^srcWidth$|^alignment$|^level$|^locked$|^root$|^data$|^anchorStyle)/;

screenshot.ignoreRenderedAttributes = /(^anchorStyle$|^bgColou?r$|^bgOpacity$|^colou?r$|^data$|^font$|^scrolling$|^shadow$|^style$|^truncation$|^wrap$|^columns$|^editable$|^fontStyle$|^lines$|^secure$|^scrollbar$|^size$|^spellcheck$|^text$|^thumbColor$|^handleLinks$|^scroll.$)/;

screenshot.extensionMap = { jpg: 'jpeg', jpeg: 'jpeg', png: 'png' };

screenshot.getExtension = function(path) { var pos = path.lastIndexOf('.'); return (pos < 0) ? "" : path.substr(pos + 1); };

screenshot.getFilenameWithoutExtension = function(path) { var pos1 = Math.max(path.lastIndexOf('/'), path.lastIndexOf('\\')); var pos2 = path.lastIndexOf('.'); return (pos2 < pos1) ? path.substr(pos1 + 1) : path.substr(pos1 + 1, pos2 - (pos1 + 1)); };

screenshot.defaultFilename = 'Screenshot.png';