From 6be015fafb81c9553f44b8e06ec3812ba6befe9e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Sven=20Sch=C3=B6ling?= Date: Mon, 26 Oct 2009 16:57:20 +0100 Subject: [PATCH] Feature Branch: Autocompletion. --- SL/Form.pm | 3 ++ SL/IC.pm | 2 + SL/Locale.pm | 2 +- bin/mozilla/ic.pl | 19 +++++++ css/jquery.autocomplete.css | 48 +++++++++++++++++ .../jquery.autocomplete.pack.js | 12 +++++ js/jquery.autocomplete.js | 1 + locale/de/ic | 1 + templates/webpages/generic/autocomplete.html | 52 +++++++++++++++++++ .../webpages/ic/ajax_autocomplete_de.html | 6 +++ .../webpages/ic/ajax_autocomplete_master.html | 6 +++ templates/webpages/oe/sales_order_de.html | 9 ++++ templates/webpages/oe/sales_order_master.html | 5 ++ 13 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 css/jquery.autocomplete.css create mode 100644 js/jquery-autocomplete/jquery.autocomplete.pack.js create mode 120000 js/jquery.autocomplete.js create mode 100644 templates/webpages/generic/autocomplete.html create mode 100644 templates/webpages/ic/ajax_autocomplete_de.html create mode 100644 templates/webpages/ic/ajax_autocomplete_master.html diff --git a/SL/Form.pm b/SL/Form.pm index 579b1ef65..d2a51e624 100644 --- a/SL/Form.pm +++ b/SL/Form.pm @@ -692,6 +692,7 @@ sub header { $jsscript = qq| + @@ -724,6 +725,8 @@ sub header { $fokus + + diff --git a/SL/IC.pm b/SL/IC.pm index 0bf015f3f..426fc9fc3 100644 --- a/SL/IC.pm +++ b/SL/IC.pm @@ -1060,6 +1060,8 @@ sub all_parts { } $main::lxdebug->leave_sub(); + + return wantarray ? @{ $form->{parts} } : $form->{parts}; } sub _create_filter_for_priceupdate { diff --git a/SL/Locale.pm b/SL/Locale.pm index b869587ca..d6ac18157 100644 --- a/SL/Locale.pm +++ b/SL/Locale.pm @@ -215,7 +215,7 @@ sub findsub { if (exists $self->{subs}{$text_rev}) { $text = $self->{subs}{$text_rev}; } elsif ($self->{countrycode} && $self->{NLS_file}) { - Form->error("$text not defined in locale/$self->{countrycode}/$self->{NLS_file}"); + $main::form->error("$text not defined in locale/$self->{countrycode}/$self->{NLS_file}"); } $main::lxdebug->leave_sub(); diff --git a/bin/mozilla/ic.pl b/bin/mozilla/ic.pl index 3042403da..346f7ad59 100644 --- a/bin/mozilla/ic.pl +++ b/bin/mozilla/ic.pl @@ -2010,4 +2010,23 @@ sub parts_language_selection { $lxdebug->leave_sub(); } +sub ajax_autocomplete { + $main::lxdebug->enter_sub(); + + my $form = $main::form; + my %myconfig = %main::myconfig; + + $form->{column} ||= 'description'; + $form->{$form->{column}} = $form->{q} || ''; + $form->{limit} = ($form->{limit} * 1) || 10; + $form->{searchitems} ||= ''; + + my @results = IC->all_parts(\%myconfig, $form); + + print $form->ajax_response_header(), + $form->parse_html_template('ic/ajax_autocomplete'); + + $main::lxdebug->leave_sub(); +} + sub continue { call_sub($form->{"nextsub"}); } diff --git a/css/jquery.autocomplete.css b/css/jquery.autocomplete.css new file mode 100644 index 000000000..91b622833 --- /dev/null +++ b/css/jquery.autocomplete.css @@ -0,0 +1,48 @@ +.ac_results { + padding: 0px; + border: 1px solid black; + background-color: white; + overflow: hidden; + z-index: 99999; +} + +.ac_results ul { + width: 100%; + list-style-position: outside; + list-style: none; + padding: 0; + margin: 0; +} + +.ac_results li { + margin: 0px; + padding: 2px 5px; + cursor: default; + display: block; + /* + if width will be 100% horizontal scrollbar will apear + when scroll mode will be used + */ + /*width: 100%;*/ + font: menu; + font-size: 12px; + /* + it is very important, if line-height not setted or setted + in relative units scroll will be broken in firefox + */ + line-height: 16px; + overflow: hidden; +} + +.ac_loading { + background: white url('indicator.gif') right center no-repeat; +} + +.ac_odd { + background-color: #eee; +} + +.ac_over { + background-color: #0A246A; + color: white; +} diff --git a/js/jquery-autocomplete/jquery.autocomplete.pack.js b/js/jquery-autocomplete/jquery.autocomplete.pack.js new file mode 100644 index 000000000..2d09b003d --- /dev/null +++ b/js/jquery-autocomplete/jquery.autocomplete.pack.js @@ -0,0 +1,12 @@ +/* + * jQuery Autocomplete plugin 1.1 + * + * Copyright (c) 2009 Jörn Zaefferer + * + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + * + * Revision: $Id: jquery.autocomplete.js 15 2009-08-22 10:30:27Z joern.zaefferer $ + */ +eval(function(p,a,c,k,e,r){e=function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}(';(3($){$.2e.1u({19:3(b,d){5 c=W b=="1B";d=$.1u({},$.M.1T,{Y:c?b:P,y:c?P:b,1J:c?$.M.1T.1J:10,X:d&&!d.1D?10:48},d);d.1y=d.1y||3(a){6 a};d.1v=d.1v||d.1R;6 A.I(3(){1M $.M(A,d)})},L:3(a){6 A.11("L",a)},1k:3(a){6 A.14("1k",[a])},2b:3(){6 A.14("2b")},28:3(a){6 A.14("28",[a])},24:3(){6 A.14("24")}});$.M=3(o,r){5 t={2Y:38,2S:40,2N:46,2I:9,2E:13,2B:27,2x:3I,2v:33,2p:34,2n:8};5 u=$(o).3r("19","3o").Q(r.2Q);5 p;5 m="";5 n=$.M.3c(r);5 s=0;5 k;5 h={1F:C};5 l=$.M.32(r,o,1Z,h);5 j;$.1Y.2X&&$(o.2U).11("45.19",3(){4(j){j=C;6 C}});u.11(($.1Y.2X?"43":"42")+".19",3(a){s=1;k=a.2M;3V(a.2M){O t.2Y:a.1d();4(l.N()){l.30()}w{12(0,D)}R;O t.2S:a.1d();4(l.N()){l.2D()}w{12(0,D)}R;O t.2v:a.1d();4(l.N()){l.2C()}w{12(0,D)}R;O t.2p:a.1d();4(l.N()){l.2A()}w{12(0,D)}R;O r.17&&$.1c(r.S)==","&&t.2x:O t.2I:O t.2E:4(1Z()){a.1d();j=D;6 C}R;O t.2B:l.Z();R;3J:1P(p);p=1O(12,r.1J);R}}).2t(3(){s++}).3E(3(){s=0;4(!h.1F){2r()}}).2q(3(){4(s++>1&&!l.N()){12(0,D)}}).11("1k",3(){5 c=(1r.7>1)?1r[1]:P;3 1N(q,a){5 b;4(a&&a.7){16(5 i=0;i1){5 f=r.S.7;5 c=$(o).18().1I;5 d,1H=0;$.I(b,3(i,a){1H+=a.7;4(c<=1H){d=i;6 C}1H+=f});b[d]=v;v=b.3f(r.S)}v+=r.S}u.K(v);1l();u.14("L",[e.y,e.F]);6 D}3 12(b,c){4(k==t.2N){l.Z();6}5 a=u.K();4(!c&&a==m)6;m=a;a=1m(a);4(a.7>=r.29){u.Q(r.26);4(!r.1s)a=a.J();21(a,3a,1l)}w{1q();l.Z()}};3 15(b){4(!b)6[""];4(!r.17)6[$.1c(b)];6 $.4h(b.23(r.S),3(a){6 $.1c(b).7?$.1c(a):P})}3 1m(a){4(!r.17)6 a;5 c=15(a);4(c.7==1)6 c[0];5 b=$(o).18().1I;4(b==a.7){c=15(a)}w{c=15(a.22(a.37(b),""))}6 c[c.7-1]}3 1G(q,a){4(r.1G&&(1m(u.K()).J()==q.J())&&k!=t.2n){u.K(u.K()+a.37(1m(m).7));$(o).18(m.7,m.7+a.7)}};3 2r(){1P(p);p=1O(1l,4g)};3 1l(){5 c=l.N();l.Z();1P(p);1q();4(r.36){u.1k(3(a){4(!a){4(r.17){5 b=15(u.K()).1n(0,-1);u.K(b.3f(r.S)+(b.7?r.S:""))}w{u.K("");u.14("L",P)}}})}};3 3a(q,a){4(a&&a.7&&s){1q();l.35(a,q);1G(q,a[0].F);l.20()}w{1l()}};3 21(f,d,g){4(!r.1s)f=f.J();5 e=n.31(f);4(e&&e.7){d(f,e)}w 4((W r.Y=="1B")&&(r.Y.7>0)){5 c={4f:+1M 4e()};$.I(r.2Z,3(a,b){c[a]=W b=="3"?b():b});$.4d({4c:"4b",4a:"19"+o.49,2V:r.2V,Y:r.Y,y:$.1u({q:1m(f),47:r.X},c),44:3(a){5 b=r.1A&&r.1A(a)||1A(a);n.1i(f,b);d(f,b)}})}w{l.2T();g(f)}};3 1A(c){5 d=[];5 b=c.23("\\n");16(5 i=0;i]*)("+a.22(/([\\^\\$\\(\\)\\[\\]\\{\\}\\*\\.\\+\\?\\|\\\\])/2K,"\\\\$1")+")(?![^<>]*>)(?![^&;]+;)","2K"),"<2J>$1")},1D:D,1E:3S};$.M.3c=3(g){5 h={};5 j=0;3 1f(s,a){4(!g.1s)s=s.J();5 i=s.2H(a);4(g.1w=="3R"){i=s.J().1k("\\\\b"+a.J())}4(i==-1)6 C;6 i==0||g.1w};3 1i(q,a){4(j>g.1g){1o()}4(!h[q]){j++}h[q]=a}3 1e(){4(!g.y)6 C;5 f={},2G=0;4(!g.Y)g.1g=1;f[""]=[];16(5 i=0,2F=g.y.7;i<2F;i++){5 c=g.y[i];c=(W c=="1B")?[c]:c;5 d=g.1v(c,i+1,g.y.7);4(d===C)1V;5 e=d.3Q(0).J();4(!f[e])f[e]=[];5 b={F:d,y:c,L:g.1z&&g.1z(c)||d};f[e].1U(b);4(2G++0){5 c=h[k];$.I(c,3(i,x){4(1f(x.F,q)){a.1U(x)}})}}6 a}w 4(h[q]){6 h[q]}w 4(g.1f){16(5 i=q.7-1;i>=g.29;i--){5 c=h[q.3O(0,i)];4(c){5 a=[];$.I(c,3(i,x){4(1f(x.F,q)){a[a.7]=x}});6 a}}}6 P}}};$.M.32=3(e,g,f,k){5 h={H:"3N"};5 j,z=-1,y,1t="",1S=D,G,B;3 2y(){4(!1S)6;G=$("<3M/>").Z().Q(e.2P).T("3L","3K").1Q(1K.2w);B=$("<3H/>").1Q(G).3G(3(a){4(U(a).2u&&U(a).2u.3F()==\'2s\'){z=$("1L",B).1h(h.H).3D(U(a));$(U(a)).Q(h.H)}}).2q(3(a){$(U(a)).Q(h.H);f();g.2t();6 C}).3C(3(){k.1F=D}).3B(3(){k.1F=C});4(e.E>0)G.T("E",e.E);1S=C}3 U(a){5 b=a.U;3A(b&&b.3z!="2s")b=b.3y;4(!b)6[];6 b}3 V(b){j.1n(z,z+1).1h(h.H);2o(b);5 a=j.1n(z,z+1).Q(h.H);4(e.1D){5 c=0;j.1n(0,z).I(3(){c+=A.1a});4((c+a[0].1a-B.1b())>B[0].3x){B.1b(c+a[0].1a-B.3w())}w 4(c=j.1j()){z=0}}3 2m(a){6 e.X&&e.X").3v(e.1y(a,1t)).Q(i%2==0?"3u":"3P").1Q(B)[0];$.y(c,"2k",y[i])}j=B.3t("1L");4(e.1X){j.1n(0,1).Q(h.H);z=0}4($.2e.2W)B.2W()}6{35:3(d,q){2y();y=d;1t=q;2l()},2D:3(){V(1)},30:3(){V(-1)},2C:3(){4(z!=0&&z-8<0){V(-z)}w{V(-8)}},2A:3(){4(z!=j.1j()-1&&z+8>j.1j()){V(j.1j()-1-z)}w{V(8)}},Z:3(){G&&G.Z();j&&j.1h(h.H);z=-1},N:3(){6 G&&G.3s(":N")},3q:3(){6 A.N()&&(j.2j("."+h.H)[0]||e.1X&&j[0])},20:3(){5 a=$(g).3p();G.T({E:W e.E=="1B"||e.E>0?e.E:$(g).E(),2i:a.2i+g.1a,1W:a.1W}).20();4(e.1D){B.1b(0);B.T({2L:e.1E,3n:\'3X\'});4($.1Y.3m&&W 1K.2w.3l.2L==="1x"){5 c=0;j.I(3(){c+=A.1a});5 b=c>e.1E;B.T(\'3k\',b?e.1E:c);4(!b){j.E(B.E()-2R(j.T("2O-1W"))-2R(j.T("2O-3j")))}}}},2g:3(){5 a=j&&j.2j("."+h.H).1h(h.H);6 a&&a.7&&$.y(a[0],"2k")},2T:3(){B&&B.2z()},1p:3(){G&&G.3i()}}};$.2e.18=3(b,f){4(b!==1x){6 A.I(3(){4(A.2d){5 a=A.2d();4(f===1x||b==f){a.4n("2c",b);a.3h()}w{a.4m(D);a.4l("2c",b);a.4k("2c",f);a.3h()}}w 4(A.3g){A.3g(b,f)}w 4(A.1C){A.1C=b;A.3e=f}})}5 c=A[0];4(c.2d){5 e=1K.18.4j(),3d=c.F,2a="<->",2f=e.3b.7;e.3b=2a;5 d=c.F.2H(2a);c.F=3d;A.18(d,d+2f);6{1I:d,39:d+2f}}w 4(c.1C!==1x){6{1I:c.1C,39:c.3e}}}})(4i);',62,272,'|||function|if|var|return|length|||||||||||||||||||||||||else||data|active|this|list|false|true|width|value|element|ACTIVE|each|toLowerCase|val|result|Autocompleter|visible|case|null|addClass|break|multipleSeparator|css|target|moveSelect|typeof|max|url|hide||bind|onChange||trigger|trimWords|for|multiple|selection|autocomplete|offsetHeight|scrollTop|trim|preventDefault|populate|matchSubset|cacheLength|removeClass|add|size|search|hideResultsNow|lastWord|slice|flush|unbind|stopLoading|arguments|matchCase|term|extend|formatMatch|matchContains|undefined|highlight|formatResult|parse|string|selectionStart|scroll|scrollHeight|mouseDownOnSelect|autoFill|progress|start|delay|document|li|new|findValueCallback|setTimeout|clearTimeout|appendTo|formatItem|needsInit|defaults|push|continue|left|selectFirst|browser|selectCurrent|show|request|replace|split|unautocomplete||loadingClass||setOptions|minChars|teststring|flushCache|character|createTextRange|fn|textLength|selected|in|top|filter|ac_data|fillList|limitNumberOfItems|BACKSPACE|movePosition|PAGEDOWN|click|hideResults|LI|focus|nodeName|PAGEUP|body|COMMA|init|empty|pageDown|ESC|pageUp|next|RETURN|ol|nullData|indexOf|TAB|strong|gi|maxHeight|keyCode|DEL|padding|resultsClass|inputClass|parseInt|DOWN|emptyList|form|dataType|bgiframe|opera|UP|extraParams|prev|load|Select|||display|mustMatch|substring||end|receiveData|text|Cache|orig|selectionEnd|join|setSelectionRange|select|remove|right|height|style|msie|overflow|off|offset|current|attr|is|find|ac_even|html|innerHeight|clientHeight|parentNode|tagName|while|mouseup|mousedown|index|blur|toUpperCase|mouseover|ul|188|default|absolute|position|div|ac_over|substr|ac_odd|charAt|word|180|RegExp|100|switch|400|auto|ac_loading|ac_results||ac_input|keydown|keypress|success|submit||limit|150|name|port|abort|mode|ajax|Date|timestamp|200|map|jQuery|createRange|moveEnd|moveStart|collapse|move'.split('|'),0,{})) \ No newline at end of file diff --git a/js/jquery.autocomplete.js b/js/jquery.autocomplete.js new file mode 120000 index 000000000..b44709853 --- /dev/null +++ b/js/jquery.autocomplete.js @@ -0,0 +1 @@ +jquery-autocomplete/jquery.autocomplete.pack.js \ No newline at end of file diff --git a/locale/de/ic b/locale/de/ic index 2741fd2a3..984553a37 100644 --- a/locale/de/ic +++ b/locale/de/ic @@ -357,6 +357,7 @@ $self->{subs} = { '_update_ship' => '_update_ship', 'add' => 'add', 'addtop100' => 'addtop100', + 'ajax_autocomplete' => 'ajax_autocomplete', 'ap_transaction' => 'ap_transaction', 'ar_transaction' => 'ar_transaction', 'assembly_row' => 'assembly_row', diff --git a/templates/webpages/generic/autocomplete.html b/templates/webpages/generic/autocomplete.html new file mode 100644 index 000000000..6b9681f14 --- /dev/null +++ b/templates/webpages/generic/autocomplete.html @@ -0,0 +1,52 @@ +[%#- + Autocompletion + + This template enables auto completion for input fields. + Calling Syntax is: + + INCLUDE 'generic/autocomlete', [ + { SPEC_1 }, + { SPEC_2 }, + ... + ] + + where SPEC is a hash containing the following keys: + + script : the script that is called for autocompletion, defaults to the invoking script + action : action in the ajax script, defaults to 'ajax_autocomplete' + selector : a jquery selector, specifying the input field + column : specifies the column that is represented by the bound field. typically description or name. + + TODO FIELDS: + - addition fields like type, vc etc. + - additional dependencies, see jquery.autocomplete documentation + - hook function on select, again see jquery documentation + + a simple SPEC would look like this: + + { selector => '#description', column => 'description' } + # field with id="description" should be autocompleted with descriptions + + { script => 'ic.pl', selector => '[name^="partnumber_"]', column => 'partnumber' } + # let ic.pl autocomplete by partnumbers, bind this to all fields where the name begins with "partnumber_" + + + + The Backend Side + + The called function will recieve the queried string as hashkey "q" in form, as well as every other param specified here. + It should generate a generic ajax header (see form), followed by newline separated list of possible completion values. + +%] + diff --git a/templates/webpages/ic/ajax_autocomplete_de.html b/templates/webpages/ic/ajax_autocomplete_de.html new file mode 100644 index 000000000..5bbd3b622 --- /dev/null +++ b/templates/webpages/ic/ajax_autocomplete_de.html @@ -0,0 +1,6 @@ +[%- USE HTML %] +[%- FOREACH part = parts %] +[% IF loop.count < limit %] +[% part.$column %] +[%- END %] +[%- END %] diff --git a/templates/webpages/ic/ajax_autocomplete_master.html b/templates/webpages/ic/ajax_autocomplete_master.html new file mode 100644 index 000000000..5bbd3b622 --- /dev/null +++ b/templates/webpages/ic/ajax_autocomplete_master.html @@ -0,0 +1,6 @@ +[%- USE HTML %] +[%- FOREACH part = parts %] +[% IF loop.count < limit %] +[% part.$column %] +[%- END %] +[%- END %] diff --git a/templates/webpages/oe/sales_order_de.html b/templates/webpages/oe/sales_order_de.html index fef6e59f0..5f4a0199f 100644 --- a/templates/webpages/oe/sales_order_de.html +++ b/templates/webpages/oe/sales_order_de.html @@ -25,6 +25,15 @@ [% END %] + + +[% INCLUDE 'generic/autocomplete.html', AUTOCOMPLETES => [ + { script => 'ic.pl', column => 'description', selector => '[name^="description_"]' }, + { script => 'ic.pl', column => 'partnumber', selector => '[name^="partnumber_"]' }, +] +%] diff --git a/templates/webpages/oe/sales_order_master.html b/templates/webpages/oe/sales_order_master.html index 5f7df7df8..18e99b500 100644 --- a/templates/webpages/oe/sales_order_master.html +++ b/templates/webpages/oe/sales_order_master.html @@ -28,3 +28,8 @@ +[% INCLUDE 'generic/autocomplete.html', AUTOCOMPLETES => [ + { script => 'ic.pl', column => 'description', selector => '[name^="description_"]' }, + { script => 'ic.pl', column => 'partnumber', selector => '[name^="partnumber_"]' }, +] +%] -- 2.20.1