POE-XUL
view release on metacpan or search on metacpan
javascript/src/Runner.js view on Meta::CPAN
// Returning 1 means we want to give up a timeslice
_.runCommand = function (command) {
var methodName = command['methodName'];
var nodeId = command['nodeId'];
var arg1 = command['arg1'];
var arg2 = command['arg2'];
var arg3 = command['arg3'];
var rv = 0;
if (methodName == 'new') {
if (arg1 == 'window')
this.commandNewWindow(nodeId);
else
this.commandNewElement(nodeId, arg1, arg2, arg3);
}
else if (methodName == 'textnode' ) {
this.commandNewTextNode( nodeId, arg1, arg2 );
}
else if (methodName == 'SID') {
$application.setSID( nodeId );
}
else if (methodName == 'boot') {
if( $status )
$status.title( nodeId );
this.booting = true;
rv = 1;
}
else if ( methodName == 'bye' ) {
this.commandByeElement(nodeId);
}
else if ( methodName == 'bye-textnode' ) {
this.commandByeTextNode( nodeId , arg1 );
}
else if( methodName == 'set' ) {
if ( !this.late && ( POEXUL_Runner.lateAttributes[arg1] ||
this.isLateCommand( command ) ) ) {
// fb_log( 'late = ' + nodeId + "." + arg1 + "=" + arg2 );
this.lateCommands.push(command);
}
else {
rv = this.commandSetNode(nodeId, arg1, arg2);
}
}
else if( methodName == 'remove' ) {
this.commandRemoveAttribute(nodeId, arg1);
}
else if( methodName == 'method' ) {
this.commandMethod(nodeId, arg1, arg2);
}
else if( methodName == 'javascript' ) {
this.commandJavascript( arg1 );
}
else if( methodName == 'ERROR' ) {
$application.crash( arg1 );
}
else if( methodName == 'cdata' ) {
this.commandCDATA( nodeId, arg1, arg2 );
}
else if( methodName == 'style' ) {
this.commandStyle( nodeId, arg1, arg2 );
}
else if( methodName == 'popup_window' ) {
this.commandPopupWindow( nodeId, arg1 );
}
else if( methodName == 'close_window' ) {
this.commandCloseWindow( nodeId );
}
else if( methodName == 'timeslice' ) {
// fb_log( methodName );
rv = 2;
}
else if( window.name ) {
fb_log( window.name + ": Unknown command '" + methodName + "'" );
}
else {
fb_log( "Unknown command '" + methodName + "'" );
}
return rv;
}
// ------------------------------------------------------------------
_.isLateCommand = function ( command ) {
var nodeId = command['nodeId'];
var key = command['arg1'];
var element = this.newNodes[nodeId];
if (!element) element = this.getNode(nodeId, 1);
if (!element) return true;
if( key == 'textNode' && element.nodeName == 'script' ) {
return true;
}
if( key == 'value' && element.nodeName == 'search-list' ) {
// fb_log( 'late value=' + command['arg2'] );
return true;
}
return false;
}
// ------------------------------------------------------------------
_.commandNewWindow = function (nodeId) {
this.windowId = nodeId;
}
// ------------------------------------------------------------------
_.commandNewElement = function (nodeId, tagName, parentId, index) {
try {
var element = this.createElement(tagName, nodeId);
element.setAttribute('_addAtIndex', index);
this.newNodes[nodeId] = element;
var parent = this.newNodes[parentId];
if (parent)
this.addElementAtIndex(parent, element);
else {
// New elements are added to existing nodes in one batch
// in addNewNodes
if( ! this.newNodeRoots[parentId] )
this.newNodeRoots[parentId] = [];
this.newNodeRoots[parentId].push( element );
}
if (tagName == 'listbox') {
// onselect works but addEventListener( 'select' ) doesn't
javascript/src/Runner.js view on Meta::CPAN
}
else if (key == 'callback' ) {
this.commandCallback( element, value );
return;
}
else {
element[key] = value;
}
}
catch (e ) {
Throw( e,
'Cannot set ' + element.id + '.' + key + '=' + value
);
}
}
// ------------------------------------------------------------------
_.commandSetEvent = function ( element, key, value ) {
// key = clickable
var event = POEXUL_Runner.activateEvent[ key ];
// event = click
var att = key + "-code";
// att = clickable-code
// fb_log( { key: key, event: event, att: att, id: element.getAttribute( 'id' ) } );
if( value && value != "0" ) {
// Already active?
if( element[att] )
return;
var ev = event.slice( 0, 1 ).toUpperCase() +
event.slice( 1 );
// ev = Click
element[att] = function (e) {
// make sure clickable is still set
var now = element.getAttribute( key );
fb_log( { key: key, now: now } );
if( now && now != "0" )
$application.fireEvent( ev,
{ target: element },
{ from: key,
now: now }
);
};
element.addEventListener( event, element[att], false );
}
else if( element[att] ) {
var code = element[att];
delete element[att];
element.removeEventListener( key, code, false );
}
}
// ------------------------------------------------------------------
_.commandSelectedIndex = function ( element, value, _try ) {
var doit = 0, popup = 0;
if( !_try ) {
doit = 0;
}
else if( element.tagName == 'radiogroup' ) {
if( element.appendItem ) doit = 1;
}
else if( element.tagName == 'menulist' ) {
popup = element.menupopup;
if( element.menupopup ) doit = 1;
}
else {
fb_log( "how to tell if %s is active?", element.tagName );
doit = 1;
}
if( !doit ) {
this.deferSelectedIndex( element, value, _try );
return;
}
var id = element.getAttribute( 'id' );
var done;
var sel;
element.setAttribute("suppressonselect", 'true');
if( value >= 0 ) {
// This line should be enough... BUT ISN'T!
// I hate you, Milkman Random Behaviour
element.selectedIndex = value;
// But this is stupid : menulist.xml does all the following (and more)
// in <property name="selectedItem">
// We do it anyway, and pray.
if( popup ) {
sel = popup.childNodes[value-0];
if( sel ) {
element.selectedItem = sel;
// Setting .value on editable="true" will cause the
// item to disapear
var editable = element.getAttribute( 'editable' );
if (!editable || editable != 'true' ) {
// Next line forces the display to be updated in
// some situations
element.value = sel.getAttribute( 'value' );
}
}
}
else {
sel = element.selectedItem;
}
if( sel ) {
sel.setAttribute( 'selected', "true" );
}
}
else {
element.selectedItem = null;
}
element.removeAttribute( "suppressonselect" );
return;
}
// ------------------------------------------------------------------
_.commandCallback = function ( element, value ) {
var req = { attribute: value,
source_id: element.id,
event: 'Callback'
};
if( 'object' == typeof value ) {
req.attribute = value.attribute;
req.extra = value.extra;
}
var uri = $application.buildURI( req );
var att = req.attribute.replace( "hidden-", "" );
element.setAttribute( att, uri );
}
// ------------------------------------------------------------------
_.deferSelectedIndex = function ( element, value, _try ) {
if( !_try )
_try = 0;
var id = element.getAttribute( 'id' );
// fb_log( element.id + " has no menupopup try=" + _try );
var tid = "TID.selectedIndex";
_try++;
if( _try < 6 ) {
//if( _try > 1 )
// fb_log( "defering %s.selectedIndex try=%i", id, _try );
// only the last one will stay in the loop
if( this.timeouts[tid] ) {
window.clearTimeout( this.timeouts[ tid ] );
}
// Do the commands as one batch, all together, after they
// have all been added to the 'deferred' array
var self = this;
this.timeouts[tid] = window.setTimeout( function () {
delete self.timeouts[ tid ];
self.doDeferredSelectedIndex( tid );
}, this.BLIP * 20 );
// Add the command to the batch
if( ! this.deferredSelectedIndex )
this.deferredSelectedIndex = [];
this.deferredSelectedIndex.push( [ element, value, _try ] );
}
else {
element.selectedIndex = value;
element.setAttribute( 'selectedIndex', value );
fb_log( 'Giving up on %s.selectedIndex=%i', id, value );
}
}
// ------------------------------------------------------------------
// Do all the commands in the deferred batch
_.doDeferredSelectedIndex = function (tid) {
var todo = this.deferredSelectedIndex;
this.deferredSelectedIndex = [];
var l = todo.length;
for( var q=0; q<l; q++ ) {
// fb_log( q, todo[q] );
this.commandSelectedIndex( todo[q][0], todo[q][1], todo[q][2] );
}
}
// ------------------------------------------------------------------
_.commandRemoveAttribute = function (nodeId, key, value) {
try {
var element = this.newNodes[nodeId];
if (!element) element = this.getNode(nodeId);
element.removeAttribute( key );
if( key in element && element.__lookupSetter__( key ) ) {
fb_log( "remove %s.%s", element.id, key );
element[key] = ''; // also clear the property
}
} catch (e) {
Throw(e,
'Cannot remove attribute from node: [' + nodeId + ', ' + key + ']'
);
}
}
javascript/src/Runner.js view on Meta::CPAN
try {
eval( value );
} catch( e ) {
Throw(e, 'Cannot evaluate javascript: ['+ value + ']' );
}
}
// ------------------------------------------------------------------
// Delete an element
_.commandByeElement = function (nodeId) {
// fb_log( 'bye ' + nodeId );
var node = this.newNodes[nodeId];
if( node ) {
delete this.newNodes[nodeId];
// fb_log( 'bye new node %s', nodeId );
// above is probably enough... but one can never be too paranoid
}
else {
node = this.getNode( nodeId, 1 );
if( !node ) {
// fb_log( 'Attempt to remove unknown node ' + nodeId );
return;
}
}
// Remove from DOM
var p = node.parentNode;
if( p )
p.removeChild( node );
// work around the fact XBL doesn't always call destuctor
if( node.dispose )
node.dispose();
}
// ------------------------------------------------------------------
_.commandFramify = function (nodeId) {
$application.framify( nodeId );
}
// ------------------------------------------------------------------
_.commandPopupWindow = function (id, win) {
// fb_log( "Open window "+id );
var feat = "resizable=yes,dependent=yes";
if( win.width ) {
feat += ",width="+win.width;
}
if( win.height ) {
feat += ",height="+win.height;
}
feat += ",location="+( win.location ? 'yes' : 'no' );
feat += ",menubar="+( win.menubar ? 'yes' : 'no' );
feat += ",toolbar="+( win.toolbar ? 'yes' : 'no' );
feat += ",status="+( win.status ? 'yes' : 'no' );
feat += ",scrollbars="+( win.status ? 'yes' : 'no' );
if( ! win.url ) {
win.url = $application.baseURI();
win.url = win.url.replace( "/xul",
"/popup.xul?SID=" + $application.getSID() +
"&app=" + $application.applicationName );
}
$application.openWindow( win.url, id, feat );
}
// ------------------------------------------------------------------
_.commandCloseWindow = function (id) {
fb_log( "Close window "+id );
$application.closeWindow( id );
}
// private --------------------------------------------------------------------
_.getNode = function (nodeId, safe) {
var node = this._getNode(nodeId);
if ( !node && !safe ) Throw("Cannot find node by Id: " + nodeId);
return node;
}
_._getNode = function (nodeId) {
if( this.windowId == nodeId ) {
return this.windowEl;
}
else {
return this.document.getElementById(nodeId);
}
}
_.createElement = function (tagName, nodeId) {
var NS = $application.xulNS;
if( tagName.match(/^html_/) ) {
NS = $application.htmlNS;
tagName = tagName.replace(/^html_/, '');
}
var element = this.document.createElementNS( NS, tagName );
element.id = nodeId;
return element;
}
_.addElementAtIndex = function ( parent, child ) {
var index = child.getAttribute('_addAtIndex');
child.removeAttribute('_addAtIndex');
var count = parent.childNodes.length;
if (index == null || index < 0 || count == 0 || index >= count ) {
parent.appendChild(child);
return;
}
else {
parent.insertBefore( child, parent.childNodes[ index ] );
}
}
// Node is being hidden, we clear its content
// This is a work around for Mozilla keeping old values in XBL nodes.
// This technique sucks, because our node is now out of sync with the
// POE::XUL::Node. This should propably be implemented in the widgets, but...
_.clearGroupbox = function ( node ) {
( run in 2.020 seconds using v1.01-cache-2.11-cpan-364913b4093 )