Changeset 8106

Show
Ignore:
Timestamp:
12/19/11 19:55:59 (17 months ago)
Author:
jow
Message:

libs/web: rework DynamicList? widget to support dynamic lists composed of comboboxes

Location:
luci/trunk/libs/web
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • luci/trunk/libs/web/htdocs/luci-static/resources/cbi.js

    r8104 r8106  
    495495} 
    496496 
    497 function cbi_dynlist_init(name, respath) 
     497function cbi_dynlist_init(name, respath, datatype, optional, choices) 
    498498{ 
    499     function cbi_dynlist_renumber(e) 
    500     { 
    501         /* in a perfect world, we could just getElementsByName() - but not if 
    502          * MSIE is involved... */ 
    503         var inputs = [ ]; // = document.getElementsByName(name); 
    504         for (var i = 0; i < e.parentNode.childNodes.length; i++) 
    505             if (e.parentNode.childNodes[i].name == name) 
    506                 inputs.push(e.parentNode.childNodes[i]); 
    507  
    508         for (var i = 0; i < inputs.length; i++) 
    509         { 
    510             inputs[i].id = name + '.' + (i + 1); 
    511             inputs[i].nextSibling.src = respath + ( 
    512                 (i+1) < inputs.length ? '/cbi/remove.gif' : '/cbi/add.gif' 
    513             ); 
    514         } 
    515  
    516         e.focus(); 
     499    var input0 = document.getElementsByName(name)[0]; 
     500    var prefix = input0.name; 
     501    var parent = input0.parentNode; 
     502 
     503    var values; 
     504 
     505    function cbi_dynlist_redraw(focus, add, del) 
     506    { 
     507        values = [ ]; 
     508 
     509        while (parent.firstChild) 
     510        { 
     511            var n = parent.firstChild; 
     512            var i = parseInt(n.index); 
     513 
     514            if (i != del) 
     515            { 
     516                if (n.nodeName.toLowerCase() == 'input') 
     517                    values.push(n.value || ''); 
     518                else if (n.nodeName.toLowerCase() == 'select') 
     519                    values[values.length-1] = n.options[n.selectedIndex].value; 
     520            } 
     521 
     522            parent.removeChild(n); 
     523        } 
     524 
     525        if (add >= 0) 
     526        { 
     527            focus = add+1; 
     528            values.splice(focus, 0, ''); 
     529        } 
     530        else if (values.length == 0) 
     531        { 
     532            focus = 0; 
     533            values.push(''); 
     534        } 
     535 
     536        for (var i = 0; i < values.length; i++) 
     537        { 
     538            var t = document.createElement('input'); 
     539                t.id = prefix + '.' + (i+1); 
     540                t.name = prefix; 
     541                t.value = values[i]; 
     542                t.type = 'text'; 
     543                t.index = i; 
     544                t.className = 'cbi-input-text'; 
     545 
     546            var b = document.createElement('img'); 
     547                b.src = respath + ((i+1) < values.length ? '/cbi/remove.gif' : '/cbi/add.gif'); 
     548                b.className = 'cbi-image-button'; 
     549 
     550            parent.appendChild(t); 
     551            parent.appendChild(b); 
     552            parent.appendChild(document.createElement('br')); 
     553 
     554            if (datatype) 
     555            { 
     556                cbi_validate_field(t.id, ((i+1) == values.length) || optional, datatype); 
     557            } 
     558 
     559            if (choices) 
     560            { 
     561                cbi_combobox_init(t.id, choices[0], '', choices[1]); 
     562                t.nextSibling.index = i; 
     563 
     564                cbi_bind(t.nextSibling, 'keydown',  cbi_dynlist_keydown); 
     565                cbi_bind(t.nextSibling, 'keypress', cbi_dynlist_keypress); 
     566 
     567                if (i == focus || -i == focus) 
     568                    t.nextSibling.focus(); 
     569            } 
     570            else 
     571            { 
     572                cbi_bind(t, 'keydown',  cbi_dynlist_keydown); 
     573                cbi_bind(t, 'keypress', cbi_dynlist_keypress); 
     574 
     575                if (i == focus) 
     576                { 
     577                    t.focus(); 
     578                } 
     579                else if (-i == focus) 
     580                { 
     581                    t.focus(); 
     582 
     583                    /* force cursor to end */ 
     584                    var v = t.value; 
     585                    t.value = ' ' 
     586                    t.value = v; 
     587                } 
     588            } 
     589 
     590            cbi_bind(b, 'click', cbi_dynlist_btnclick); 
     591        } 
    517592    } 
    518593 
     
    571646            next = next.nextSibling; 
    572647 
     648        /* advance one further in combobox case */ 
     649        if (next && next.nextSibling.name == name) 
     650            next = next.nextSibling; 
     651 
    573652        switch (ev.keyCode) 
    574653        { 
     
    576655            case 8: 
    577656            case 46: 
    578                 var jump = (ev.keyCode == 8) 
    579                     ? (prev || next) : (next || prev); 
    580  
    581                 if (se.value.length == 0 && jump) 
     657                var del = (se.nodeName.toLowerCase() == 'select') 
     658                    ? true : (se.value.length == 0); 
     659 
     660                if (del) 
    582661                { 
    583                     se.parentNode.removeChild(se.nextSibling.nextSibling); 
    584                     se.parentNode.removeChild(se.nextSibling); 
    585                     se.parentNode.removeChild(se); 
    586  
    587                     cbi_dynlist_renumber(jump); 
    588  
    589662                    if (ev.preventDefault) 
    590663                        ev.preventDefault(); 
    591664 
    592                     /* IE Quirk, needs double focus somehow */ 
    593                     jump.focus(); 
     665                    var focus = se.index; 
     666                    if (ev.keyCode == 8) 
     667                        focus = -focus+1; 
     668 
     669                    cbi_dynlist_redraw(focus, -1, se.index); 
    594670 
    595671                    return false; 
     
    600676            /* enter */ 
    601677            case 13: 
    602                 var n = document.createElement('input'); 
    603                     n.name       = se.name; 
    604                     n.type       = se.type; 
    605  
    606                 var b = document.createElement('img'); 
    607  
    608                 cbi_bind(n, 'keydown',  cbi_dynlist_keydown); 
    609                 cbi_bind(n, 'keypress', cbi_dynlist_keypress); 
    610                 cbi_bind(b, 'click',    cbi_dynlist_btnclick); 
    611  
    612                 if (next) 
    613                 { 
    614                     se.parentNode.insertBefore(n, next); 
    615                     se.parentNode.insertBefore(b, next); 
    616                     se.parentNode.insertBefore(document.createElement('br'), next); 
    617                 } 
    618                 else 
    619                 { 
    620                     se.parentNode.appendChild(n); 
    621                     se.parentNode.appendChild(b); 
    622                     se.parentNode.appendChild(document.createElement('br')); 
    623                 } 
    624  
    625                 var dt = se.getAttribute('cbi_datatype'); 
    626                 var op = se.getAttribute('cbi_optional') == 'true'; 
    627  
    628                 if (dt) 
    629                     cbi_validate_field(n, op, dt); 
    630  
    631                 cbi_dynlist_renumber(n); 
     678                cbi_dynlist_redraw(-1, se.index, -1); 
    632679                break; 
    633680 
     
    676723    } 
    677724 
    678     var inputs = document.getElementsByName(name); 
    679     for( var i = 0; i < inputs.length; i++ ) 
    680     { 
    681         var btn = document.createElement('img'); 
    682             btn.className = 'cbi-image-button'; 
    683             btn.src = respath + ( 
    684                 (i+1) < inputs.length ? '/cbi/remove.gif' : '/cbi/add.gif' 
    685             ); 
    686  
    687         inputs[i].parentNode.insertBefore(btn, inputs[i].nextSibling); 
    688  
    689         cbi_bind(inputs[i], 'keydown',  cbi_dynlist_keydown); 
    690         cbi_bind(inputs[i], 'keypress', cbi_dynlist_keypress); 
    691         cbi_bind(btn,       'click',    cbi_dynlist_btnclick); 
    692     } 
     725    cbi_dynlist_redraw(0, -1, -1); 
    693726} 
    694727 
  • luci/trunk/libs/web/luasrc/view/cbi/dynlist.htm

    r7021 r8106  
    1414</div> 
    1515<script type="text/javascript"> 
    16 cbi_dynlist_init('<%=cbid%>', '<%=resource%>'); 
    17 <% if self.datatype then -%> 
    18     <% if #self.keylist > 0 then -%> 
    19         cbi_combobox_init('<%=cbid .. "." .. i%>', { 
     16cbi_dynlist_init( 
     17    '<%=cbid%>', '<%=resource%>', '<%=self.datatype%>', 
     18    <%=tostring(self.optional or self.rmempty)%> 
     19    <%- if #self.keylist > 0 then -%>, [{ 
    2020        <%- for i, k in ipairs(self.keylist) do -%> 
    2121            <%-=string.format("%q", k) .. ":" .. string.format("%q", self.vallist[i])-%> 
    2222            <%-if i<#self.keylist then-%>,<%-end-%> 
    2323        <%- end -%> 
    24         }, '<%- if not self.rmempty and not self.optional then -%> 
    25             <%-: -- Please choose -- -%> 
    26         <%- end -%>', '<%: -- custom -- %>'); 
    27     <% end -%> 
    28     <% for i=1, #vals + 1 do -%> 
    29     cbi_validate_field('<%=cbid%>.<%=i%>', <%=tostring((self.optional or self.rmempty) == true or i > #vals)%>, '<%=self.datatype%>'); 
    30     <%- end %> 
    31 <% end -%> 
     24    }, '<%: -- custom -- %>']<% end -%>); 
    3225</script> 
    3326<%+cbi/valuefooter%>