[Chameleon] HTML Legend with Javascript

Paul Spencer pagameba at magma.ca
Tue Sep 28 20:44:18 EDT 2004


Robin,

I have put some thought into this and I cannot see how we could 
accomplish the same 'trick' in this scenario.

In Internet Explorer you can access an array document.all and search it 
for elements of a given name or id.  Now that I think about it, I don't 
think you can do that in Mozilla/Netscape.  So the following would be a 
better approach:

legend template:

[leg_group_html]
<div class="cssClickable cssExpander cssGroup" id="[leg_group_name]" 
onclick="this.expander.toggle()">
<script langauge="JavaScript" type="text/javascript">
oGroup = new cExpander( CWCDHTML_GetLayer( '[leg_group_name]', true ));
</script>
[leg_group_name]
</div>
[/leg_group_html]
[leg_layer_html order=ascending opt_flag=15]
<div class="cssClickable cssExpander cssLayer" id="[leg_layer_name]" 
style="display:none" onclick="this.expander.toggle()">
<script langauge="JavaScript" type="text/javascript">
oLayer = new cExpander( CWCDHTML_GetLayer( '[leg_layer_name]', true ));
oGroup.addElement( oLayer );
</script>
<input type="checkbox" name="legendlayername[]"
value="[leg_layer_name]"
     [if name=layer_status oper=eq value=1]CHECKED[/if]
     [if name=layer_status oper=eq value=2]CHECKED[/if]>[leg_layer_name]
</div>
[/leg_layer_html]
[leg_class_html]
<div class="cssExpander cssClass" id="[leg_class_name]" 
style='display:none'>
<script langauge="JavaScript" type="text/javascript">
oClass = new cExpander( CWCDHTML_GetLayer( '[leg_class_name]', true ));
oLayer.addElement( oClass );
</script>
<img src="[leg_icon width=20 height=18]" width="20" 
height="20">[leg_class_name]<br>
</div>
[/leg_class_html]

application template:

<script language="JavaScript">
function cExpander( elm )
{
     this.element = elm;
     this.element.expander = this;
     this.children = new Array();
     this.bIsOpen = false;

     this.addElement = cExpander_AddElement;
     this.open = cExpander_Open;
     this.close = cExpander_Close;
     this.expand = cExpander_Expand;
     this.contract = cExpander_Contract;
     this.toggle = cExpander_Toggle;
}

function cExpander_AddElement( elm )
{
     this.children[this.children.length] = elm;
}

function cExpander_Open()
{
     for( var i=0; i<this.children.length; i++)
     {
         this.children[i].element.style.display = 'block';
         if (this.children[i].bIsOpen)
         {
             this.children[i].open();
         }
     }
}

function cExpander_Close()
{
     for( var i=0; i<this.children.length; i++)
     {
         this.children[i].element.style.display = 'none';
         this.children[i].close();
     }
}

function cExpander_Expand()
{
     this.bIsOpen = true;
     this.open();
}

function cExpander_Contract()
{
     this.bIsOpen = false;
     this.close();
}

function cExpander_Toggle()
{
     if (this.bIsOpen)
         this.contract();
     else
         this.expand();
}

</script>
<style>
.cssClickable {
     cursor: pointer;
}

.cssExpander {
     width: 100px;
     font-family: arial;
     font-size: 12px;
     font-weight: normal;
     padding: 2px;
}

.cssGroup {
     font-size: 14px;
     font-weight: bold;
     background-color: #cccccc;
     border: 1px solid #c9c9c9;
}

.cssLayer {
     background-color: #dddddd;
     border: 1px solid #d9d9d9;
     padding: 5px 2px 2px 2px;

}

.cssClass {
     font-style: italic;
     background-color: #eeeeee;
     border: 1px solid #e9e9e9;
     padding: 10px 2px 2px 2px;
}

</style>

Note the css is just for effect ;)  Also, the open/close status is not 
preserved between page loads ... I leave that as an exercise for the 
reader :>

Cheers,

Paul

Robin Brown wrote:
> Paul,
> 
> thanks.  that makes sense.  The only problem is now that I am trying to extend this to
> groups, the layer division gets closed before anything gets in it. Here is my legend
> template code:
> 
> [leg_group_html] 
> </div></div>
> <div id=[leg_group_name]>
> <a href="javascript:void(0);" onclick="toggleLayer('[leg_group_name]_layer');"><img
> src="C:\ms4w\apps\chameleon\samples\htdocs\images\ClosedFolder.gif"></a>
> <b>[leg_group_name]</b><br> 
> </div>
> <div id="[leg_group_name]_layer" style='display:none'>
> [/leg_group_html] 
> 
> [leg_layer_html order=ascending opt_flag=15]
> 	</div>
> 	<a href="javascript:void(0);" onclick="toggleLayer('[leg_layer_name]_class');"><img
> src="C:\ms4w\apps\chameleon\samples\htdocs\images\ClosedFolder.gif"></a>
> 	<input type="radio" name="my_legend" onclick="CWCSelectLayer('[leg_layer_name]',
> true)"[if name=selected value=1] CHECKED[/if] >
> 	<input type="checkbox" name="legendlayername[]" value="[leg_layer_name]"[if
> name=layer_status oper=eq value=1]CHECKED[/if][if name=layer_status oper=eq
> value=2]CHECKED[/if]>
> 		[if name=wms_name oper=isnull]
>     			<a href="#"
> onclick="javascript:LegendTemplateLayerInfo('[leg_layer_name]');"><span
> class="label">[leg_layer_name]</span></a><BR>
> 		[/if]
> 
>     		[if name=wms_name oper=isset]
>     			<a href="#"
> onclick="javascript:LegendTemplateLayerInfo('[leg_layer_name]');"><span
> class="label">[metadata name=WMS_TITLE]</span></a><BR>
> 		[/if]
> 
> <div id="[leg_layer_name]_class" style='display:none'>
> [/leg_layer_html]
> 
> 
> [leg_class_html]
> <img src="[leg_icon width=20 height=18]" width="20" 
> height="20">[leg_class_name]<br>
> [/leg_class_html]
> 
> 
> I was wondering if it is possible to write a code in the Chameleon template called
> setName( name) an getName().  I was thinking that I could set the variable when a group
> was created then retrieve it to name the layers inside that group.  Inside each layer
> division I would then reset the name and retrieve it to name the classes inside that
> layer.  I think in theory this would work but I don't know how to call the function
> from within my legend template without having an event.  I would like it if I could do
> the following:
>  <div setName('[leg_#_name]')> replacing the # with group/layer as appropriate
> onclick="toggleLayer(getName()+'class/layer');"
> 
> I have tried this without success.  Does anyone with more javascripting experience know
> how to make this happen?
> 
> If this is not possible, Paul, can you expand on your suggestion below that I could
> search for the div id?
> 
> Thanks for any help
> 
> Robin Brown
> 
> 
> 
> Quoting Paul Spencer <pagameba at magma.ca>:
> 
> 
>>this is a side effect of where names are accessible in the legend template.
>>
>>In order to get the javascript to work, we need to be able to 'find' the 
>>div we want to expand/contract ... we can do this by either knowing the 
>>id of the div or by searching for it.  Searching is expensive, so 
>>knowing the id is much preferred.  Within the [leg_layer_html] block, 
>>the only unique value we know of is the [leg_layer_name] so it would be 
>>ideal if we could name the div associated with the classes using that 
>>name.  But [leg_layer_name] is not available in the [leg_class_html] 
>>block so I output the <div id='[leg_layer_name]_class'> at the end of 
>>[leg_layer_html].  Then the [leg_class_html] is invoked ... but this 
>>doesn't get output unless there is at least one class, which isn't 
>>always the case if you are using WMS or raster layers ... so the div 
>>would never get closed in those cases ... workaround is to close the div 
>>in the next layer block.  So the problem is on the very first layer, 
>>there is no opening div ... hence the div just before the widget tag ... 
>>and also on the last layer there is no closing div.
>>
>>Best thing to do is 'view source' to see how it works :)
>>
>>HTH
>>
>>Paul
>>
>>Robin Brown wrote:
>>
>>>Thanks.  I tried this and it works great.  I was wondering if you can explain the
>>
>>first
>>
>>></div> on line 2 of your legend template?  The templage doesn't work if this isn't
>>
>>here
>>
>>>so I'm wondering what it does...
>>>
>>>Thanks
>>>
>>>Robin
>>>
>>>Quoting Paul Spencer <pagameba at magma.ca>:
>>>
>>>
>>>
>>>>Robin,
>>>>I just tried this:
>>>>
>>>>
>>>>legend template file:
>>>>
>>>>[leg_layer_html order=ascending opt_flag=15]
>>>></div>
>>>><div id="[leg_layer_name]">
>>>><input type="checkbox" name="legendlayername[]"
>>>>value="[leg_layer_name]"
>>>>    [if name=layer_status oper=eq  value=1]CHECKED[/if]
>>>>    [if name=layer_status oper=eq value=2]CHECKED[/if]><a 
>>>>href="javascript:void(0)" 
>>>>onclick="toggleLayer('[leg_layer_name]_class')">[leg_layer_name]</a>
>>>></div>
>>>><div id="[leg_layer_name]_class" style='display:none'>
>>>>[/leg_layer_html]
>>>>[leg_class_html]
>>>><img src="[leg_icon width=20 height=18]" width="20" 
>>>>height="20">[leg_class_name]<br>
>>>>[/leg_class_html]
>>>>
>>>>
>>>>in chameleon template:
>>>>
>>>><script language="JavaScript" type="text/JavaScript">
>>>>function toggleLayer( szName )
>>>>{
>>>>    var layer = CWCDHTML_GetLayer( szName );
>>>>
>>>>    if (layer.display == 'block')
>>>>        layer.display = 'none';
>>>>    else
>>>>        layer.display = 'block';
>>>>}
>>>></script>
>>>><div>
>>>>  <cwc2 type="LegendTemplate" visible="true" embedded="true" 
>>>>template="fancy_legend.html" popupstyleresource="TextButtons" 
>>>>popupwidth="500" popupheight="400" status="false" menubar="false"/>
>>>></div>
>>>>
>>>>this displays each layer with a checkbox and a clickable layer name. 
>>>>Clicking the layer name expands the class list below the layer.
>>>>
>>>>I would assume you could extend this to support groups of layers too.
>>>>
>>>>Cheers,
>>>>
>>>>Paul
>>>>
>>>>Robin Brown wrote:
>>>>
>>>>
>>>>>Thanks Paul.  I wasn't sure if it was even possible.  Now that I know it is, is
>>>>
>>>>there
>>>>
>>>>
>>>>>anyone out there that has done this?  I am very new to Javascript (just did a
>>>>
>>>>tutorial
>>>>
>>>>
>>>>>last week).  I got the divisions in but I'm not sure how to make them
>>>>
>>>>expand/collapse
>>>>
>>>>
>>>>>when they are clicked on. I tried to write a script in the template but that
>>
>>seems
>>
>>>>to
>>>>
>>>>
>>>>>throw an error. Any  examples or suggestions are welcome.  Thanks again.
>>>>>
>>>>>Robin
>>>>>Quoting Paul Spencer <pagameba at magma.ca>:
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>>Robin,
>>>>>>
>>>>>>the XML Theme Legend doesn't display classes. It is intended more for 
>>>>>>use with OGC layers (WMS) which don't have that level of information 
>>>>>>available.  I may extend it in the future but not right now.
>>>>>>
>>>>>>So your only resource now is to use the html legend template.  It should 
>>>>>>be relatively easy (if you know dhtml/css/javascript) to make expandable 
>>>>>>sections in a legend template file.  For instance, you can place layer 
>>>>>>names and classes into separate div elements in the template and use 
>>>>>>javascript to set the display to block or none to show/hide the classes. 
>>>>>>Similarly you can use groups to do the same thing for layers.
>>>>>>
>>>>>>Cheers,
>>>>>>
>>>>>>Paul
>>>>>>
>>>>>>Robin Brown wrote:
>>>>>>
>>>>>>
>>>>>>
>>>>>>>Hi all,
>>>>>>>
>>>>>>>I am using an html legend template and I have a question.  Is there a way to
>>
>>make
>>
>>>>>>this
>>>>>>
>>>>>>
>>>>>>
>>>>>>>legend more dynamic?  I would like let the user expand and collapse the groups
>>
>>as
>>
>>>>>>my
>>>>>>
>>>>>>
>>>>>>
>>>>>>>legend is rather large.  I have tried doing this using the XML Theme legend but
>>
>>I
>>
>>>>>>want
>>>>>>
>>>>>>
>>>>>>
>>>>>>>to show layers as well as classes in my legend and I couldn't see how to do
>>
>>that
>>
>>>>>>with
>>>>>>
>>>>>>
>>>>>>
>>>>>>>the XML.  If anyone knows how to show layers and classes with XML this would
>>
>>also
>>
>>>>>>be
>>>>>>
>>>>>>
>>>>>>
>>>>>>>helpful since I think I may be able to get expanding and collapsing using this
>>>>>>
>>>>>>method. 
>>>>>>
>>>>>>
>>>>>>
>>>>>>>BTW, I do know that by only placing one layer in each group with xml you get
>>
>>the
>>
>>>>>>look
>>>>>>
>>>>>>
>>>>>>
>>>>>>>of layers displaying in the legend, but I haven't seen any solution for
>>
>>classes.
>>
>>>>>>>Thanks for any help you can give!
>>>>>>>
>>>>>>>Robin Brown
>>>>>>
>>>>>>-- 
>>>>>>-----------------------------------------------------------------
>>>>>>|Paul Spencer                           pspencer at dmsolutions.ca   |
>>>>>>|-----------------------------------------------------------------|
>>>>>>|Applications & Software Development                              |
>>>>>>|DM Solutions Group Inc                 http://www.dmsolutions.ca/|
>>>>>>-----------------------------------------------------------------
>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>>
>>>>-- 
>>>> -----------------------------------------------------------------
>>>>|Paul Spencer                           pspencer at dmsolutions.ca   |
>>>>|-----------------------------------------------------------------|
>>>>|Applications & Software Development                              |
>>>>|DM Solutions Group Inc                 http://www.dmsolutions.ca/|
>>>> -----------------------------------------------------------------
>>>>
>>>>
>>>
>>>
>>>
>>-- 
>>  -----------------------------------------------------------------
>>|Paul Spencer                           pspencer at dmsolutions.ca   |
>>|-----------------------------------------------------------------|
>>|Applications & Software Development                              |
>>|DM Solutions Group Inc                 http://www.dmsolutions.ca/|
>>  -----------------------------------------------------------------
>>
>>
> 
> 
> 

-- 
  -----------------------------------------------------------------
|Paul Spencer                           pspencer at dmsolutions.ca   |
|-----------------------------------------------------------------|
|Applications & Software Development                              |
|DM Solutions Group Inc                 http://www.dmsolutions.ca/|
  -----------------------------------------------------------------



More information about the Chameleon mailing list