package sample.yuitree; import jaxcent.*; /** * Jaxcent YUI (Yahoo User Interface) tree sample. * * Provides a simple wrapper around the tree's JavaScript API. */ public class YuiTree extends JaxcentPage { // Date formatting variables. char dateSep = '/'; // Separator character boolean dateMonthFirst = true; // Month first or day-of-month first boolean dateCreated = false; // Dates already created (cannot be changed after creation) /** * init must be called with the ID of the DIV where * the tree is to be created. */ public void init( String treeDivId ) throws Jaxception { execJavaScriptCode( "YuiTreeVar = new YAHOO.widget.TreeView( '" + treeDivId + "');" ); execJavaScriptCode( "YuiTreeVar.subscribe('clickEvent', yuiTreeClickHandler );" ); draw(); } /** * (Re)Draw the tree. MUST be called after insert/delete etc operations. */ public void draw() throws Jaxception { execJavaScriptCode( "YuiTreeVar.draw();" ); } /* Internal method for quoting strings for JavaScript */ String quote( String str ) { if ( str.indexOf( '\'' ) < 0 && str.indexOf( '\\' ) < 0 ) return str; StringBuffer sb = new StringBuffer(); for ( int i = 0; i < str.length(); i++ ) { char ch = str.charAt( i ); if ( ch == '\'' || ch == '\\' ) sb.append( '\\' ); sb.append( ch ); } return sb.toString(); } /* Makes sure variables names are valid JavaScript names */ void checkVarName( String varname ) throws Jaxception { if ( varname == null ) return; if ( varname.equals( "" )) throw new Jaxception( "Empty variable name" ); char ch = varname.charAt( 0 ); if (( ! Character.isLetter( ch )) && ch != '_' ) throw new Jaxception( "Variable name \"" + varname + "\" is not valid, must start with letter or underscore" ); for ( int i = 1; i < varname.length(); i++ ) { ch = varname.charAt( i ); if (( ! Character.isLetterOrDigit( ch )) && ch != '_' ) throw new Jaxception( "Variable name \"" + varname + "\" is not valid, must consist of letters, digits and underscores" ); } if ( varname.toLowerCase().startsWith( "jaxcent" )) { throw new Jaxception( "String \"" + varname + "\" is not a valid identifier (must not start with \"jaxcent\" to avoid conflict)" ); } if ( varname.equalsIgnoreCase( "yuiTreeClickHandler" ) || varname.equalsIgnoreCase( "YuiTreeVar" )) { throw new Jaxception( "String \"" + varname + "\" is not a valid identifier (conflicting name)" ); } } /** * Add a text node. * First argument is an optional variable name to hold the new node. * Second argument specifies the label text of the node. * Third argument specifies if the node should be made editable. * Fourth argument is the parent of the node, if null, the node * is added at the top level. */ public void addTextNode( String varname, String text, boolean editable, String parent ) throws Jaxception { String str = ""; if ( varname != null ) { checkVarName( varname ); str += varname; str += " = "; } if ( parent == null ) parent = "YuiTreeVar.getRoot()"; str += "new YAHOO.widget.TextNode('" + quote( text ) + "', " + parent + ", true)"; if ( editable && varname == null ) str += ".editable = true"; execJavaScriptCode( str ); if ( varname != null ) { execJavaScriptCode( varname + ".varname = '" + varname + "'" ); if ( editable ) execJavaScriptCode( varname + ".editable = true" ); } } /** * Sets date formatting separator character, and whether month comes first. */ public void setDateFormat( char sep, boolean monthFirst ) throws Jaxception { if ( dateCreated ) throw new Jaxception( "Dates have already been created, cannot change separator" ); if ( sep == '\'' || sep == '"' ) throw new Jaxception( "Invalid date separator" ); dateSep = sep; dateMonthFirst = monthFirst; } /** * Similar to addTextNode, but second argument specifies a date. */ public void addDateNode( String varname, java.util.Date date, boolean editable, String parent ) throws Jaxception { java.util.Calendar cal = java.util.Calendar.getInstance(); cal.setTime( date ); String datestr = ""; dateCreated = true; if ( dateMonthFirst ) { datestr += 1 + cal.get( cal.MONTH ); datestr += dateSep; datestr += cal.get( cal.DAY_OF_MONTH ); } else { datestr += cal.get( cal.DAY_OF_MONTH ); datestr += dateSep; datestr += 1 + cal.get( cal.MONTH ); } datestr += dateSep; datestr += cal.get( cal.YEAR ); String str = ""; if ( varname != null ) { checkVarName( varname ); str += varname; str += " = "; } str += "new YAHOO.widget.DateNode({type:'DateNode',label:'" + datestr + "',"; if ( editable ) { str += "editable:true,"; } else str += "editable:false,"; str += "calendarConfig: { DATE_FIELD_DELIMITER:'" + dateSep + "',"; if ( dateMonthFirst ) str += "MDY_MONTH_POSITION:1,MDY_DAY_POSITION:2,MDY_YEAR_POSITION:3"; else str += "MDY_DAY_POSITION:1,MDY_MONTH_POSITION:2,MDY_YEAR_POSITION:3"; str += "}}, "; if ( parent == null ) parent = "YuiTreeVar.getRoot()"; str += parent; str += ", true )"; execJavaScriptCode( str ); if ( varname != null ) { execJavaScriptCode( varname + ".varname = '" + varname + "'" ); } } /** * Gets the current label for a node. */ public String getNodeLabel( String name ) throws Jaxception { return evalJavaScriptCode( name + ".label", false, null ); } /** Delete a given node and all its children. * Important: When a node is deleted, the name that * used to refer to it should be removed from any Maps, * Lists, etc! */ public void deleteNode( String node ) throws Jaxception { execJavaScriptCode( "YuiTreeVar.removeNode( " + node + ", true );" ); draw(); } /** * Expand the entire tree. */ public void expandAll() throws Jaxception { execJavaScriptCode( "YuiTreeVar.expandAll();" ); } /** * Expand a node. */ public void expand( String node ) throws Jaxception { execJavaScriptCode( node + ".expand();" ); } /** * Collapse the entire tree. */ public void collapseAll() throws Jaxception { execJavaScriptCode( "YuiTreeVar.collapseAll();" ); } /** * Collapse a node. */ public void collapse( String node ) throws Jaxception { execJavaScriptCode( node + ".collapse();" ); } /** * Override to receive click events on nodes. */ protected void onClick( String nodeName ) { } protected void onJavaScriptRequest(java.lang.String cmd, java.lang.String[] args) { if ( cmd.equals( "YuiTreeOnClick" )) { onClick( args[0] ); } } }