[Chameleon] Layer order change WITHOUT reloading the page for JSAPI

Carlo Trönnberg carlo.t at chello.hu
Thu Jun 22 19:43:36 EDT 2006


Hi Julien,

Thanks for your tip!
I will look into this.
I have no experience with the JSAPI coding but will definitively try to get 
into it.

Concerning the draggable sorting of the layers, I based my solution on the 
excellent JavaScript library with DHTML from Tim Taylor
http://tool-man.org/examples/sorting.html
The sorting is made my manipulating the DOM (Document Object Model) with 
JavaScript, XHTML and CSS (DHTML), the same as used in Chameleon...
This code is very reliable and worked on all the browsers I have tried 
(which is rare).

I based my code on the long list example which has a function to query the 
order of the list (the values) as a delimited string.
Looking at the source through the browser of a running chameleon 
application, you can find a function called "LegendTemplateGetLayerName" 
which maps the order number and the name of a layer. I made an ugly double 
for loop to generate an array of numbers (the order of the layers compared 
to the order defined in the map file) from the list (with names) returned by 
the ordering JavaScript code. The reason I did it this way is that this 
mapping function (LegendTemplateGetLayerName) is regenerated at each reload 
of the page with the changed order from the previous state becoming the 
default ordering.
The generated numbered list is then stored in the hidden form element and 
parsed at page reload in my phtml file.

I am sure this can be solved in a much nicer and straightforward way and I 
think we all could profit from this highly interactive way. Anyone with a 
better approach?

My application of it is right now rather dirty (the code...). There is a lot 
of tweaking done to use the LegendTemplate...
Hereafter is my legend_template.html template as is (it might contain other 
interesting stuff for other newbies around :-) ). It still holds the 
previous radio button for selecting a layer for the promotion, demotion or 
removal of it. Right now I only use it for the removal. I am planning to 
make a trash can icon on which I could drop a layer I want to remove. Then 
this radio button would be obsolete. I use 2 LegendTemplates in my solution 
why I have the conditional  statement [if name=isStation oper=isnull]...

==== legend_template.html start =====
[leg_layer_html order=ascending opt_flag=15][if name=isStation oper=isnull]
    <li itemID="[leg_layer_name]" onmouseover="this.className = 
'highlighted';" onmouseout="this.className = 'nothighlighted';"><div 
class="handle2" TITLE="Move this layer by dragging it to desired 
position"></div>
    <div id="c4View" class="view"><table border=0 cellpadding="0" 
cellspacing="0"><tr id='[leg_layer_name]_t'>
        <td><input type="radio" name="my_legend" 
onclick="CWCSelectLayer('[leg_layer_name]', true)" [if name=selected 
value=1] CHECKED[/if] ></td>
        <td align="left" width=25><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]></td>
        <td width="24"><img src="[leg_icon width=20 height=18]" width="20" 
height="20"></td>
        [if name=wms_name oper=isnull]<td><a href="#" 
onclick="javascript:LegendTemplateLayerInfo('[leg_layer_name]');"><span 
class="label">[leg_layer_name]</span></a></td>
    </tr>[/if][if name=wms_name oper=isset]
        <td><a href="#" 
onclick="javascript:LegendTemplateLayerInfo('[leg_layer_name]');"><span 
class="label">[metadata name=WMS_TITLE]</span></a></td>
    </tr>
    [/if]</table></div></li>[/if][/leg_layer_html]
==== legend_template.html end =====

==== in my CSS file: ====

.highlighted {
 background-color: #CCCCFF;
 font-weight: bold;
}

.nothighlighted {
 background-color: #FFFFCC;
 font-weight: normal;
}

 #phoneticlong .handle2 {
  float: left;
  background-color: #ccc;
  background-image: url(images/handle.gif);
  width: 11px;
  height: 19px;
 }
 .handle2 {
  cursor: move;
 }
 #phoneticlong li .view {
  cursor: text;
 }
ul.sortable li {
 position: relative;
}

ul.boxy {
 list-style-type: none;
 padding: 0px;
 margin: 0px;
 width: 100%;
 font-size: 13px;
 font-family: Arial, sans-serif;
}
ul.boxy li {
 cursor:move;
 padding: 0px 0px;
}
==================

In my html template I enclosed the LegendTemplate widget in a list structure 
(same as in the example on Tim Taylor's page):
...
<ul id="phoneticlong" class="sortable boxy">
  <cwc2 type="LegendTemplate" visible="true" embedded="true" 
template="legend_template.html" popupstyleresource="TextButtons" 
popupwidth="500" popupheight="400" status="false" menubar="false"/>
  </ul>
...
=====================================
Sorry for this long post, butI hope this is helpful and would really 
appreciate anybody's comments or ideas on this.

Cheers,

Carlo

----- Original Message ----- 
From: "Julien-Samuel Lacroix" <jlacroix at mapgears.com>
To: "Carlo Tronnberg" <temp at chello.hu>
Cc: <chameleon at lists.maptools.org>
Sent: Tuesday, June 20, 2006 16:41
Subject: Re: [Chameleon] Layer order change WITHOUT reloading the page for 
JSAPI


> Hi,
> Cool! That seems really great! Do you think you will be able to contribute 
> it back? For the page reloading, you ca check the file 
> chameleon/htdocs/widgets/NavTool.php
>
> In the NavSetActiveTool JS function, you will have some code that trig the 
> map refresh. It looks like:
>
>     {$this->mszHTMLForm}.NAV_CMD.value = "LEGENDTEMPLATE_LAYERS";
>     {$this->mszHTMLForm}.NAV_ALLOW_RECTANGLE.value=false;
>     {$this->mszHTMLForm}.NAV_SUBMIT.value=false;
>     goCWCJSAPI.UpdateNavTools();
>
>
> Then you will have to add a LEGENDTEMPLATE_LAYERS event in the 
> chameleon/htdocs/UpdateMap.php
>
> Hope that helps
>
> Julien
>
>
> Carlo Tronnberg wrote:
>> Dear List!
>>  I have made a sortable Legend management based on the LegendTemplate 
>> widget but using drag and drop to move the layers. It works very well but 
>> since I do not need to refresh the layer list anymore (reload the page). 
>> Is it possible to tell mapserver about the new order WITHOUT reloading 
>> the whole page?
>>  Right now, my JavaScript layer ordering code returns a string with the 
>> order of the layers stored in a hidden form element called 
>> 'setlayerorder'.
>> In the base phtml file of my solution, I simply split this string to an 
>> array which I pass to the setlayersdrawingorder function.
>>  $layerlist = split('~~', $_REQUEST['setlayerorder'] );
>>  $oApp->moMapSession->oMap->setlayersdrawingorder( $layerlist );
>>  The amount of code in the solution starts to be large why I want to 
>> minimize unnecessary reload of the page with JSAPI.
>> The layer list does not need to be reloaded anymore since I simply drag 
>> around the layers to wished position. Dropping the element should trigger 
>> the mapserver legend ordering if the element's position has changed.
>>  I think this approach is far more intuitive (and cool!) than having a 
>> radio button with option to promote or demote the layer. If you add a 
>> layer it will automatically get on top of all the others. The user might 
>> have to click several times on the demote button (with page reload in 
>> between) to get the layer to wished position.
>>  Any ideas how to avoid the page reloading but still tell mapserver to 
>> regenerate the map with the new legend order?
>>  Cheers,
>>  Carlo
>>
>>
>> ------------------------------------------------------------------------
>>
>> _______________________________________________
>> Chameleon mailing list
>> Chameleon at lists.maptools.org
>> http://lists.maptools.org/mailman/listinfo/chameleon
>
> -- 
> Julien-Samuel Lacroix
> Mapgears
> http://www.mapgears.com/
> 



More information about the Chameleon mailing list