NAME
POE::XUL::Node - XUL element
SYNOPSIS
use POE::XUL::Node;
# Flexible way of creating an element
my $box = POE::XUL::Node->new( tag => 'HBox',
Description( "Something" ),
class => 'css-class',
style => $css,
Click => $poe_event
);
# DWIM way
$window = Window( # window with a header,
HTML_H1(textNode => 'a heading'), # a label, and a button
$label = Label(FILL, value => 'a label'),
Button(label => 'a button'),
);
# attributes
$window->width( 800 );
$window->height( 600 );
$label->value('a value');
$label->style('color:red');
print $label->flex;
# compositing
print $window->child_count; # prints 2
$window->Label(value => 'another label'); # add a label to window
$window->appendChild(Label); # same but takes child as param
$button = $window->get_child(1); # navigate the widget tree
$window->add_child(Label, 0); # add a child at an index
# events
$window->Button(Click => sub { $label->value('clicked!') });
$window->MenuList(
MenuPopup(map { MenuItem( label => "item #$_", ) } 1..10 ),
Select => sub { $label->value( $_[0]->selectedIndex ) },
);
# disposing
$window->removeChild($button); # remove child widget
$window->remove_child(1); # remove child by index
DESCRIPTION
POE::XUL::Node is a DOM-like object that encapsulates a XUL element. It uses POE::XUL::ChangeManager to make sure all changes are mirrored in the browser's DOM.
Elements
To create a UI, an application must create a Window
with some elements in it. Elements are created by calling a function or method named after their tag:
$button = Button; # orphan button with no label
$box->Button; # another, but added to a box
$widget = POE::XUL::Node->new(tag => $tag); # using dynamic tag
After creating a widget, you must add it to a parent. The widget will show when there is a containment path between it and a window. There are multiple ways to set an elements parent:
$parent->appendChild($button); # DOM-like
$parent->replaceChild( $old, $new ); # DOM-like
$parent->add_child($button); # left over from XUL-Node
$parent->add_child($button, 1); # at an index
$parent->Button(label => 'hi!'); # create and add in one shot
$parent = Box(style => 'color:red', $label);# add in parent constructor
Elements can be removed from the document by removing them from their parent:
$parent->removeChild($button); # DOM-like
$parent->remove_child(0); # index
$parent->replaceChild( $old, $new ); # DOM-like
Elements have attributes. These can be set in the constructor, or via a method of the same name:
my $button = Button( value => 'one button' );
$button->value('a button');
print $button->value; # prints 'a button'
You can configure all attributes, event handlers, and children of a element, in the constructor. There are also constants for commonly used attributes. This allows for some nice code:
Window( SIZE_TO_CONTENT,
Grid( FLEX,
Columns( Column(FLEX), Column(FLEX) ),
Rows(
Row(
Button( label => "cell 1", Click => $poe_event ),
Button( label => "cell 2", Click => $poe_event ),
),
Row(
Button( label => "cell 3", Click => $poe_event ),
Button( label => "cell 4", Click => $poe_event ),
),
),
),
);
Check out the XUL references (http://developer.mozilla.org/en/docs/XUL) for an explanation of available elements and their attributes.
Events are removed with the "detach" method:
$button->detach( 'Click' );
Events
Elements receive events from their client halves, and pass them on to attached listeners in the application. You attach a listener to a widget so:
# listening to existing widget
$textbox->attach( Change => sub { print 'clicked!' } );
# listening to widget in constructor
TextBox( Change => $poe_event );
You attach events by providing an event name and a listener. Possible event names are Click
, Change
, Select
, and Pick
. Different widgets fire different events. These are listed in POE::XUL::Event.
Listener are either the name of a POE event, or a callbacks that receives a single argument: the event object (POE::XUL::Event). POE events are called on the application session, NOT the current session when an event is defined. If you want to post to another session, use "callback" in POE::Session.
You can query the Event object for information about the event: name
, source
, and depending on the event type: checked
, value
, color
, and selectedIndex
.
Here is an example of listening to the Select
event of a list box:
Window(
VBox(FILL,
$label = Label(value => 'select item from list'),
ListBox(FILL, selectedIndex => 2,
(map { ListItem(label => "item #$_") } 1..10),
Select => sub {
$label->value
("selected item #${\( shift->selectedIndex + 1 )}");
},
),
),
);
Events are removed with the "detach" method:
$button->detach( 'Click' );
XUL-Node API vs. the Javascript XUL API
The XUL-Node API is different in the following ways:
Booleans are Perl booleans.
All nodes must have an
id
attribute. If you do not specify one, it will be automatically generated by POE::XUL::Node.There is little difference between attributes, properties, and methods. They are all attributes on the POE::XUL::Node object. However, the javascript client library handles them differently.
This means that to call a method or a property, you have to specify at least one parameter:
$node->blur( 0 ); # Equiv to node.blur() in JS
While all attribute and properties are mirrored from the Perl object to the DOM object, only a select few are mirrored back (
value
,selected
,selectedIndex
).There exist constants for common attribute key/value pairs. See POE::XUL::Node.
ELEMENT CONSTRUCTORS
To make life funner, a bunch of constructor functions have been defined for the most commonly used elements. These functions are exported into any package that uses POE::XUL::Node.
XUL Elements
ArrowScrollBox, Box, Button, Caption, CheckBox, ColorPicker, Column, Columns, Deck, Description, Grid, Grippy, GroupBox, HBox, Image, Label, ListBox, ListCell, ListCol, ListCols, ListHead, ListHeader, ListItem, Menu, MenuBar, MenuItem, MenuList, MenuPopup, MenuSeparator, ProgressMeter, Radio, RadioGroup, Row, Rows, Seperator, Spacer, Splitter, Stack, StatusBar, StatusBarPanel, Tab, TabBox, TabPanel, TabPanels, Tabs, TextBox, ToolBar, ToolBarButton, ToolBarSeperator, ToolBox, VBox, Window.
It is of course possible to create any other XUL element with:
POE::XUL::Node->new( tag => $tag );
HTML Elements
HTML_Pre, HTML_H1, HTML_H2, HTML_H3, HTML_H4, HTML_A, HTML_Div, HTML_Br, HTML_Span.
It is of course possible to create any other HTML element with:
POE::XUL::Node->new( tag => "html:$tag" );
SPECIAL ELEMENTS
There are 4 special elements:
Script
Script( $JS );
Creates a script element, with type="text/javascript"
, and a single POE::XUL::CDATA child. The client library will eval()
the script.
Boot
Boot( $text );
Sends the boot command to the client library. Currently, the client library calls $status.title( $text );
, if the $status
object exists. Your application must create $status
.
RawCmd
RawCmd( \@cmd );
Allows you to send a raw command to the Javascript client library. Use at your own risk.
pxInstructions
pxInstructions( @instructions );
Send instructions to the ChangeManager. This is a slightly higher-level form of "RawCmd". Its presence indicates the immaturity of POE::XUL as a whole. These instructions are subject to change/removal in the future.
@instructions is an array instructions for the ChangeManager. See "instrction" in POE::XUL::ChangeManager for details.
METHODS
createTextNode =head2 textNode
children =head2 child_count =head2 hasChildNodes
add_child
$parent->add_child( $node, $index );
appendChild
$parent->appendChild( $node );
firstChild / first_child
my $node = $parent->firstChild;
get_child
my $node = $parent->get_child( $index );
getItemAtIndex / get_item
my $node = $menu->getItemAtIndex( $index );
Like "get_child", but works for menulist
and menupopup
.
lastChild / last_child
my $node = $parent->lastChild;
removeChild / remove_child
$parent->removeChild( $node );
$parent->removeChild( $index );
replaceChild
$parent->replaceChild( $old, $new );
attributes
my %hash = $node->attributes;
my $hashref = $node->attributes;
Note even if you manipulate $hashref
directly, changes will not be mirrored in the DOM node.
getAttribute / get_attribute
my $value = $node->getAttribute( $name );
setAttribute / set_attribute
$node->setAttribute( $name => $value );
removeAttribute / remove_attribute
$node->removeAttribute( $name );
hide
$node->hide;
Syntatic sugar that adds display: none
to the style attribute.
show
$node->show;
Syntatic sugar that removes display: none
from the style attribute.
close
Close a sub-window. Obviously may only be called on a Window element.
attach
$node->attach( $Event => $poe_event );
detach
$node->detach( $Event );
event
my $listener = $node->event( $Event );
dispose / distroy
Calls dispose
on all the child nodes, and drops all events.
as_xml
Returns this element and all its child elements as an unindented XML string. Useful for debuging.
LIMITATIONS
Some elements are not supported yet: tree, popup.
Some DOM features are not supported yet:
* multiple selections * node disposal * color picker will not fire events if type is set to button * equalsize attribute will not work * menus with no popups may not show
SEE ALSO
POE::XUL. POE::XUL::Event presents the list of all possible events.
http://developer.mozilla.org/en/docs/XUL has a good XUL reference.
AUTHOR
Philip Gwyn <gwyn-at-cpan.org>
CREDITS
Based on work by Ran Eilam.
COPYRIGHT AND LICENSE
Copyright 2007 by Philip Gwyn. All rights reserved;
Copyright 2003-2004 Ran Eilam. All rights reserved.
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.