Attaching the Libraries and Custom Code
Here’s a run-down of everything you need to do within your Actions to integrate with the Softpress FX Actions and Protaculous.
There are a few things you need to do within a “Scripty” Action to communicate with the other Actions that might also be applied to the page.
Firstly, create your Action bundle and create a directory called “Support Files~” in the same directory as the Action file. This directory needs to contain the JavaScript libraries you’ll be linking to. You can download the full set of libraries here.
At the very beginning of your Action somewhere, you need to declare:
var scripty = true;
var debug = false;
var gLibraries = ["builder", "effects", "dragdrop", "controls", "slider", "sound"];
Your functions will also add to and track an object called filesList, at the fwPage level, which will be sorted and normalized at the end of the publish cycle.
The first variable marks your Action as being one of the Scripty Actions, the second will load the normal (not minified) versions of the Prototype and Scriptaculous libraries, which is useful for testing, and the third is used to make sure only the required libraries are loaded in the resulting page.
Next, you need to add the following functions to your <action-javascript> block. (I like to use an action-library for this.)
/*This function runs at publish time, and
decides if this is the last "scripty" Action
on the page or not. If it is, then it returns
true, and the function that called it will
attach all the necessary files to the head
of the page.*/
function lastOrders(){
var actions = fwPage.fwFindAllActions();
var scripties = new Array();
for (i in actions){
if (actions[i].scripty == true) scripties.push(actions[i]);
}
return this === scripties[scripties.length -1];
}
/*Clean up the list of libraries by sorting
them in their correct order (according to
scripty specs) and removing duplicates*/
var gLibraries = ["builder", "effects", "dragdrop", "controls", "slider", "sound"];
var include = function(arr, obj) {
for(var i = -1, j = arr.length; ++i < j;)
if(arr[i] === obj) return true;
return false;
};
function cleanLibs(){
// Get rid of duplicates and out of range values
var out = [];
for (var i=0; i < fwPage.scriptyLibs.length; i++) {
if( ! (include(out, fwPage.scriptyLibs[i])) &&
(fwPage.scriptyLibs[i] < gLibraries.length) &&
(fwPage.scriptyLibs[i] >= 0) ){
out.push(fwPage.scriptyLibs[i]);
}
};
fwPage.scriptyLibs = out.sort();
}
/*Build a string containing the scripty
libraries used, or return "" if all are
used or none are specified*/
function getLibs()
{
var scriptyLibs = "";
if(fwPage.scriptyLibs)
{
if(fwPage.scriptyLibs.length == gLibraries.length)
{
// All scriptyLibs are being used so don't specify any
}
else
{
scriptyLibs += "?load=";
for(var i in fwPage.scriptyLibs)
scriptyLibs += gLibraries[fwPage.scriptyLibs[i]] + ",";
scriptyLibs = scriptyLibs.substring(0, scriptyLibs.length-1);
}
}
return scriptyLibs;
}
/*This function creates a link to a
JavaScript file in the head of the page.*/
function LinkFileToHead(theTag, file)
{
// Get the list of individual scriptyLibs and add it to the end of the scripty reference
var scriptyLibs = getLibs();
var scriptTag = theTag.fwAdd("script", true);
scriptTag.src = fwQuote((!file.match("scriptaculous") ? file : file+scriptyLibs));
scriptTag.type = fwQuote("text/javascript");
scriptTag.fwAddRawOpt();
theTag.fwAddRawOpt();
}
/*This function does the same thing,
only using the Google CDN to deliver
the files instead of the local versions.*/
function LinkRemoteFileToHead(theTag, file)
{
var path = "http://ajax.googleapis.com/ajax/libs/"
var scriptTag = theTag.fwAdd("script", true);
// Get the list of individual scriptyLibs and add to the end of the scripty reference
var scriptyLibs = getLibs();
if(parseInt(fwFreewayVersion.replace(/.?(wd)?/g, "")) >= 562)
scriptTag.src = fwQuote(path + (file.match("pro") ? "prototype/1.7.0.0/prototype.js" : "scriptaculous/1.9.0/scriptaculous.js"+scriptyLibs));
else if(parseFloat(fwFreewayVersion) >= 5.5)
scriptTag.src = fwQuote(path + (file.match("pro") ? "prototype/1.6.1.0/prototype.js" : "scriptaculous/1.8.3/scriptaculous.js"+scriptyLibs));
else
scriptTag.src = fwQuote(path + (file.match("pro") ? "prototype/1.6.0.2/prototype.js" : "scriptaculous/1.8.1/scriptaculous.js"+scriptyLibs));
scriptTag.type = fwQuote("text/javascript");
scriptTag.fwAddRawOpt();
theTag.fwAddRawOpt();
}
And this is the final step in the puzzle: when your Action requests files be attached to the page, it does so through AddFiles. If you pass it a comma-separated list of libraries, you will get that list of files attached to your page. You must include these files in your Action bundle, and you must include “packed” versions of Prototype and Scriptaculous as well.
Due to a bug in Freeway, you can’t pass a variable containing a dot to this function, so while it would be perfectly clear to say AddFiles('foo.txt') to this function, in practice this blows up dramatically. Therefore, AddFiles is limited to JavaScript files with the .js extension. If you have other file types that you want to include, you’ll need to do that long-hand.
function AddFiles(filesString, scriptyLibs /*number or array of numbers*/)
{
// Cleanup if arguments are missing
if(filesString.constructor == Number || filesString.constructor == Array)
{
scriptyLibs = filesString;
fileString = "";
}
var theHead = fwDocument.fwTags.fwFind("head");
var connected = function(){
if(fwShellCommand) {
return fwShellCommand('ping -c1 -i1 http://ajax.googleapis.com');
}else{
var osa=new FWOSAInterpreter;
osa.fwWrite('do shell script "curl ajax.googleapis.com"');
osa.fwCompile();
return osa.fwRun();
}
}
var useCustom = filesString && filesString.length > 0;
var path = this.fwPathName;
var prefix = path.substring(0, path.lastIndexOf(":")) + ':Support Files~:';
if(parseInt(fwFreewayVersion.replace(/.?(wd)?/g, "")) >= 562)
var canon = 'prototype1700packer,prototype1700,scriptaculous190packer,scriptaculous190'.split(',');
else if(parseFloat(fwFreewayVersion) >= 5.5)
var canon = 'prototype1610packer,prototype1610,scriptaculous183packer,scriptaculous183'.split(',');
else
var canon = 'prototype1602packer,prototype1602,scriptaculous181packer,scriptaculous181'.split(',');
var files = (useCustom) ? filesString.split(',') : canon;
if(scriptyLibs)
{
// Make the scriptyLibs argument an array if it isn't one already
scriptyLibs = scriptyLibs.constructor == Array ? scriptyLibs : [scriptyLibs];
// Create or add the libraries used to a page variable
if(!fwPage.scriptyLibs)
fwPage.scriptyLibs = scriptyLibs;
else
fwPage.scriptyLibs = fwPage.scriptyLibs.concat(scriptyLibs);
}
// Make the overall library list object variable if it doesn't exist
if(!fwPage.libsList)
fwPage.libsList = new Object();
for (i in files)
{
var file = files[i];
if (file && !fwPage.libsList[file])
{
myFile = new FWFile;
myFile.fwOpenRead(prefix + file + '.js');
myFile.fwClose();
if (fwParameters[file])
{
fwParameters[file].fwSpecify(myFile);
var path = fwParameters[file].toString();
if(useCustom == true)
fwPage.libsList[file] = path;
fwParameters[file].fwClear();
}
else
{
fwAlert(ParamString(kFileNotFound, file, ".js"));
}
}
}
if(lastOrders())
{
if(parseInt(fwFreewayVersion.replace(/.?(wd)?/g, "")) >= 562) {
if(fwPage.libsList['prototype1700packer'] && fwPage.libsList['prototype1700'])
fwPage.libsList['prototype1700packer'] = null;
if(fwPage.libsList['scriptaculous190packer'] && fwPage.libsList['scriptaculous190'])
fwPage.libsList['scriptaculous190packer'] = null;
}
else if(parseFloat(fwFreewayVersion) >= 5.5) {
if(fwPage.libsList['prototype1610packer'] && fwPage.libsList['prototype1610'])
fwPage.libsList['prototype1610packer'] = null;
if(fwPage.libsList['scriptaculous183packer'] && fwPage.libsList['scriptaculous183'])
fwPage.libsList['scriptaculous183packer'] = null;
} else {
if(fwPage.libsList['prototype1602packer'] && fwPage.libsList['prototype1602'])
fwPage.libsList['prototype1602packer'] = null;
if(fwPage.libsList['scriptaculous181packer'] && fwPage.libsList['scriptaculous181'])
fwPage.libsList['scriptaculous181packer'] = null;
}
// Clean the list of individual libs
if(fwPage.scriptyLibs)
cleanLibs();
for (i in canon)
{
if (fwPage.libsList[canon[i]])
{
var file = fwPage.libsList[canon[i]];
connected() ? LinkRemoteFileToHead(theHead, file) : LinkFileToHead(theHead, file);
delete fwPage.libsList[canon[i]];
}
}
for ( i in fwPage.libsList )
LinkFileToHead(theHead, fwPage.libsList[i]);
}
}
Here’s an example of a call to this function, from within Protaculous. I encourage further study of that Action for more details about this technique.
First, we set up the file references, outside of the <action-javascript>:
<action-file name ="prototype1700packer" var/>
<action-file name ="scriptaculous190packer" var/>
<action-file name ="prototype1610packer" var/>
<action-file name ="scriptaculous183packer" var/>
<action-file name ="prototype1602packer" var/>
<action-file name ="scriptaculous181packer" var/>
<action-popup name="lib" title="Use Library">
<value name="prototype">
<value name="prototype-packed">
<value name="scriptaculous">
<value name="scriptaculous-packed">
</action-popup>
Next, we instantiate the libsList object to store file references. I do this in fwInterface and in some Actions I back it up in the main execution function as well.
function fwInterface(){
fwPage.libsList = new Object();
}
Finally, here’s the call to load the files:
function fwAfterStartHead()
{
var filesString = '';
if(fwParameters['lib'].fwValue == 'scriptaculous-packed'){
filesString = 'prototype1610packer,scriptaculous183packer';
}
if(fwParameters['lib'].fwValue == 'prototype-packed'){
filesString = 'prototype1610packer';
}
if(fwParameters['lib'].fwValue == 'scriptaculous'){
filesString = 'prototype1610,scriptaculous183';
}
if(fwParameters['lib'].fwValue == 'prototype'){
filesString = 'prototype1610';
}
/* Use the following table to request particular libraries within Scriptaculous:
0 = Builder
1 = Effects
2 = Dragdrop
3 = Controls
4 = Slider
5 = Sound
"" = All libraries
*/
if(parseInt(fwFreewayVersion.replace(/.?(wd)?/g, "")) >= 562) {
AddFiles('prototype1700packer,scriptaculous190packer', [1]);
} else if(parseFloat(fwFreewayVersion) >= 5.5) {
AddFiles('prototype1610packer,scriptaculous183packer', [1]);
} else {
AddFiles('prototype1602packer,scriptaculous181packer', [1]);
}
}
Here’s a breadkown of adding libraries:
// Use all Scripty libraries
AddFiles(filesString);
// Use the Effects library only
AddFiles(filesString, 1);
// Use the Effects and Dragdrop libraries
AddFiles(filesString, [1,2]);
