Index: /trunk/README
===================================================================
--- /trunk/README	(revision 16261)
+++ /trunk/README	(revision 16262)
@@ -123,6 +123,4 @@
     - help-browser.css      CSS file for the help sites (HTML content is downloaded from the website
                             on demand, but displayed inside the programm in a Java web browser component.)
-    - overpass-wizard.js    Javascript code to provide a wizard-GUI for creating Overpass requests
-                            (external library, see https://github.com/tyrasd/overpass-wizard)
     - *.lang                translation data
     - *.xsd                 xml schema files for validation of configuration files
Index: unk/resources/data/overpass-wizard.js
===================================================================
--- /trunk/resources/data/overpass-wizard.js	(revision 16261)
+++ 	(revision )
@@ -1,4 +1,0 @@
-var overpassWizard=function(){"use strict";function e(r,n,t,u){this.message=r,this.expected=n,this.found=t,this.location=u,this.name="SyntaxError","function"==typeof Error.captureStackTrace&&Error.captureStackTrace(this,e)}function r(e){var r={};if(e||(e={}),!e){if("undefined"==typeof $)return!1;try{$.ajax("data/iD_presets.json",{async:!1,dataType:"json"}).success((function(r){e=r})).error((function(){throw new Error}))}catch(e){console.error("failed to load presets file","data/iD_presets.json",e)}}return Object.keys(e).map((function(r){var n=e[r];n.nameCased=n.name,n.name=n.name.toLowerCase(),n.terms=n.terms?n.terms.map((function(e){return e.toLowerCase()})):[]})),function(){if("undefined"!=typeof $&&"undefined"!=typeof i18n){var r=i18n.getLanguage();if("en"!=r){var n="data/iD_presets_"+r+".json";try{$.ajax(n,{async:!1,dataType:"json"}).success((function(r){Object.keys(r).map((function(n){var t=r[n];(n=e[n]).translated=!0;var u=n.name;n.nameCased=t.name,n.name=t.name.toLowerCase(),t.terms&&(n.terms=t.terms.split(",").map((function(e){return e.trim().toLowerCase()})).concat(n.terms)),n.terms.unshift(u)}))})).error((function(){throw new Error}))}catch(e){console.error("failed to load preset translations file: "+n)}}}}(),r.get_query_clause=function(r){var n=r.free.toLowerCase(),t=Object.keys(e).map((function(r){return e[r]})).filter((function(e){return!1!==e.searchable&&(e.name===n||(e._termsIndex=e.terms.indexOf(n),-1!=e._termsIndex))}));if(0===t.length)return!1;t.sort((function(e,r){return e.name===n?-1:r.name===n?1:e._termsIndex-r._termsIndex}));var u=t[0],a=[];return u.geometry.forEach((function(e){switch(e){case"point":case"vertex":a.push("node");break;case"line":a.push("way");break;case"area":a.push("way"),a.push("relation");break;case"relation":a.push("relation");break;default:console.error("unknown geometry type "+e+" of preset "+u.name)}})),{types:a.filter((function(e,r,n){return n.indexOf(e)===r})),conditions:Object.keys(u.tags).map((function(e){var r=u.tags[e];return{query:"*"===r?"key":"eq",key:e,val:r}}))}},r.fuzzy_search=function(r){var n=r.free.toLowerCase(),t=2+Math.floor(n.length/7);function u(e){return levenshteinDistance(e,n)<=t}var a=Object.keys(e).map((function(r){return e[r]})).filter((function(e){return!1!==e.searchable&&(!!u(e.name)||e.terms.some(u))}));if(0===a.length)return!1;function o(e){return[e.name].concat(e.terms).map((function(e,r){return levenshteinDistance(e,n)})).reduce((function(e,r){return e<=r?e:r}))}return a.sort((function(e,r){return o(e)-o(r)})),a[0].nameCased},r}var n;return function(e,r){function n(){this.constructor=e}n.prototype=r.prototype,e.prototype=new n}(e,Error),e.buildMessage=function(e,r){var n={literal:function(e){return'"'+u(e.text)+'"'},class:function(e){var r=e.parts.map((function(e){return Array.isArray(e)?a(e[0])+"-"+a(e[1]):a(e)}));return"["+(e.inverted?"^":"")+r+"]"},any:function(){return"any character"},end:function(){return"end of input"},other:function(e){return e.description}};function t(e){return e.charCodeAt(0).toString(16).toUpperCase()}function u(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\0/g,"\\0").replace(/\t/g,"\\t").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/[\x00-\x0F]/g,(function(e){return"\\x0"+t(e)})).replace(/[\x10-\x1F\x7F-\x9F]/g,(function(e){return"\\x"+t(e)}))}function a(e){return e.replace(/\\/g,"\\\\").replace(/\]/g,"\\]").replace(/\^/g,"\\^").replace(/-/g,"\\-").replace(/\0/g,"\\0").replace(/\t/g,"\\t").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/[\x00-\x0F]/g,(function(e){return"\\x0"+t(e)})).replace(/[\x10-\x1F\x7F-\x9F]/g,(function(e){return"\\x"+t(e)}))}function o(e){return n[e.type](e)}return"Expected "+function(e){var r,n,t=e.map(o);if(t.sort(),t.length>0){for(r=1,n=1;r<t.length;r++)t[r-1]!==t[r]&&(t[n]=t[r],n++);t.length=n}switch(t.length){case 1:return t[0];case 2:return t[0]+" or "+t[1];default:return t.slice(0,-1).join(", ")+", or "+t[t.length-1]}}(e)+" but "+function(e){return e?'"'+u(e)+'"':"end of input"}(r)+" found."},function(t,u){var a,o={comment:!0,outputMode:"geom",globalBbox:!0,timeout:25,maxsize:void 0,outputFormat:"json",aroundRadius:1e3,freeFormPresets:void 0};for(var s in u)o[s]=u[s];function i(e){return e.replace(/\*\//g,"[…]").replace(/\n/g,"\\n")}u=o;try{a=function(r,n){n=void 0!==n?n:{};var t,u,a,o,s={},i={start:0},c=0,l=[function(e){return e},"in bbox",y("in bbox",!1),"IN BBOX",y("IN BBOX",!1),function(e){return{bounds:"bbox",query:e}},"in",y("in",!1),"IN",y("IN",!1),function(e,r){return{bounds:"area",query:e,area:r}},"around",y("around",!1),"AROUND",y("AROUND",!1),function(e,r){return{bounds:"around",query:e,area:r}},"global",y("global",!1),"GLOBAL",y("GLOBAL",!1),function(e){return{bounds:"global",query:e}},"or",y("or",!1),"OR",y("OR",!1),"||",y("||",!1),"|",y("|",!1),function(e,r){return{logical:"or",queries:[e,r]}},"and",y("and",!1),"AND",y("AND",!1),"&&",y("&&",!1),"&",y("&",!1),function(e,r){return{logical:"and",queries:[e,r]}},"(",y("(",!1),")",y(")",!1),function(e){return e},"==",y("==",!1),"=",y("=",!1),function(e,r){return{query:"eq",key:e,val:r}},"!=",y("!=",!1),"<>",y("<>",!1),function(e,r){return{query:"neq",key:e,val:r}},"*",y("*",!1),function(e){return{query:"key",key:e}},"is",y("is",!1),"not",y("not",!1),"null",y("null",!1),"IS",y("IS",!1),"NOT",y("NOT",!1),"NULL",y("NULL",!1),function(e){return{query:"nokey",key:e}},"~=",y("~=",!1),"~",y("~",!1),"=~",y("=~",!1),function(e,r){return{query:"like",key:e,val:r.regex?r:{regex:r}}},"like",y("like",!1),"LIKE",y("LIKE",!1),function(e,r){return{query:"likelike",key:e.regex?e:{regex:e},val:r.regex?r:{regex:r}}},"!~",y("!~",!1),function(e,r){return{query:"notlike",key:e,val:r.regex?r:{regex:r}}},":",y(":",!1),function(e,r){return{query:"substr",key:e,val:r}},"type",y("type",!1),function(e){return{query:"type",type:e}},"user",y("user",!1),"uid",y("uid",!1),"newer",y("newer",!1),"id",y("id",!1),function(e,r){return{query:"meta",meta:e,val:r}},function(e){return{query:"free form",free:e}},k("Key"),/^[a-zA-Z0-9_:\-]/,m([["a","z"],["A","Z"],["0","9"],"_",":","-"],!1,!1),function(e){return e.join("")},'"',y('"',!1),"'",y("'",!1),function(e){return e[1]},k("string"),/^[^'" ()~=!*\/:<>&|[\]{}#+@$%?\^.,]/,m(["'",'"'," ","(",")","~","=","!","*","/",":","<",">","&","|","[","]","{","}","#","+","@","$","%","?","^",".",","],!0,!1),function(e){return e.join("")},"\\",y("\\",!1),{type:"any"},function(e){return e},function(e){return e},/^['"\\bfnrtv]/,m(["'",'"',"\\","b","f","n","r","t","v"],!1,!1),function(e){return e.replace("b","\b").replace("f","\f").replace("n","\n").replace("r","\r").replace("t","\t").replace("v","\v")},"/",y("/",!1),"i",y("i",!1),"",function(e){return{regex:e[1],modifier:e[3]}},"\\/",y("\\/",!1),function(){return"/"},k("whitespace"),/^[ \t\n\r]/,m([" ","\t","\n","\r"],!1,!1)],f=[q("%;;/:#;!/1$;;/($8#: #!!)(#'#(\"'#&'#"),q('%;"/Y#$;</&#0#*;<&&&#/C$2!""6!7".) &2#""6#7$/($8#:%#!")(#\'#("\'#&\'#.Ł &%;"/y#$;</&#0#*;<&&&#/c$2&""6&7\'.) &2(""6(7)/H$$;</&#0#*;<&&&#/2$;2/)$8%:*%"$ )(%\'#($\'#(#\'#("\'#&\'#.Û &%;"/y#$;</&#0#*;<&&&#/c$2+""6+7,.) &2-""6-7./H$$;</&#0#*;<&&&#/2$;2/)$8%:/%"$ )(%\'#($\'#(#\'#("\'#&\'#.u &%;"/Y#$;</&#0#*;<&&&#/C$20""6071.) &22""6273/($8#:4#!")(#\'#("\'#&\'#./ &%;"/\' 8!:%!! )'),q('%;#/#$;</&#0#*;<&&&#/{$25""6576.A &27""6778.5 &29""697:.) &2;""6;7</H$$;</&#0#*;<&&&#/2$;"/)$8%:=%"$ )(%\'#($\'#(#\'#("\'#&\'#.# &;#'),q('%;$/#$;</&#0#*;<&&&#/{$2>""6>7?.A &2@""6@7A.5 &2B""6B7C.) &2D""6D7E/H$$;</&#0#*;<&&&#/2$;#/)$8%:F%"$ )(%\'#($\'#(#\'#("\'#&\'#.# &;$'),q(';%.b &%2G""6G7H/R#;;/I$;"/@$;;/7$2I""6I7J/($8%:K%!")(%\'#($\'#(#\'#("\'#&\'#'),q(";..Y &;/.S &;&.M &;'.G &;(.A &;).; &;*.5 &;+./ &;,.) &;-.# &;0"),q('%;1/_#;;/V$2L""6L7M.) &2N""6N7O/;$;;/2$;2/)$8%:P%"$ )(%\'#($\'#(#\'#("\'#&\'#'),q('%;1/_#;;/V$2Q""6Q7R.) &2S""6S7T/;$;;/2$;2/)$8%:U%"$ )(%\'#($\'#(#\'#("\'#&\'#'),q('%;1/d#;;/[$2L""6L7M.) &2N""6N7O/@$;;/7$2V""6V7W/($8%:X%!$)(%\'#($\'#(#\'#("\'#&\'#.ċ &%;2/ā#$;</&#0#*;<&&&#/ë$%2Y""6Y7Z/m#$;</&#0#*;<&&&#/W$2[""6[7\\/H$$;</&#0#*;<&&&#/2$2]""6]7^/#$+%)(%\'#($\'#(#\'#("\'#&\'#.} &%2_""6_7`/m#$;</&#0#*;<&&&#/W$2a""6a7b/H$$;</&#0#*;<&&&#/2$2c""6c7d/#$+%)(%\'#($\'#(#\'#("\'#&\'#/($8#:X#!")(#\'#("\'#&\'#'),q('%;1/d#;;/[$2Q""6Q7R.) &2S""6S7T/@$;;/7$2V""6V7W/($8%:e%!$)(%\'#($\'#(#\'#("\'#&\'#.Á &%;2/·#$;</&#0#*;<&&&#/¡$%2Y""6Y7Z/H#$;</&#0#*;<&&&#/2$2]""6]7^/#$+#)(#\'#("\'#&\'#.X &%2_""6_7`/H#$;</&#0#*;<&&&#/2$2c""6c7d/#$+#)(#\'#("\'#&\'#/($8#:e#!")(#\'#("\'#&\'#'),q('%;1/q#;;/h$2f""6f7g.5 &2h""6h7i.) &2j""6j7k/A$;;/8$;2.# &;8/)$8%:l%"$ )(%\'#($\'#(#\'#("\'#&\'#. &%;2/#$;</&#0#*;<&&&#/i$2m""6m7n.) &2o""6o7p/N$$;</&#0#*;<&&&#/8$;2.# &;8/)$8%:l%"$ )(%\'#($\'#(#\'#("\'#&\'#'),q("%2h\"\"6h7i/#;;/$;2.# &;8/q$;;/h$2f\"\"6f7g.5 &2h\"\"6h7i.) &2j\"\"6j7k/A$;;/8$;2.# &;8/)$8':q'\"$ )(''#(&'#(%'#($'#(#'#(\"'#&'#"),q("%;1/Y#;;/P$2r\"\"6r7s/A$;;/8$;2.# &;8/)$8%:t%\"$ )(%'#($'#(#'#(\"'#&'#.ç &%;2/Ý#$;</&#0#*;<&&&#/Ç$%2[\"\"6[7\\/H#$;</&#0#*;<&&&#/2$2m\"\"6m7n/#$+#)(#'#(\"'#&'#.X &%2a\"\"6a7b/H#$;</&#0#*;<&&&#/2$2o\"\"6o7p/#$+#)(#'#(\"'#&'#/N$$;</&#0#*;<&&&#/8$;2.# &;8/)$8%:t%\"$ )(%'#($'#(#'#(\"'#&'#"),q("%;2/S#;;/J$2u\"\"6u7v/;$;;/2$;2/)$8%:w%\"$ )(%'#($'#(#'#(\"'#&'#"),q("%2x\"\"6x7y/R#;;/I$2u\"\"6u7v/:$;;/1$;2/($8%:z%! )(%'#($'#(#'#(\"'#&'#"),q('%2{""6{7|.A &2}""6}7~.5 &2""67.) &2""67/S#;;/J$2u""6u7v/;$;;/2$;2/)$8%:%"$ )(%\'#($\'#(#\'#("\'#&\'#'),q("%;2/' 8!:!! )"),q('<%$4""5!7/,#0)*4""5!7&&&#/\' 8!:!! ).
- &%%2""67/;#;3/2$2""67/#$+#)(#\'#("\'#&\'#.K &%2""67/;#;4/2$2""67/#$+#)(#\'#("\'#&\'#/\' 8!:!! )=." 7
-'),q('<%$4""5!7/,#0)*4""5!7&&&#/\' 8!:!! ).
- &%%2""67/;#;3/2$2""67/#$+#)(#\'#("\'#&\'#.K &%2""67/;#;4/2$2""67/#$+#)(#\'#("\'#&\'#/\' 8!:!! )=." 7'),q("%$;50#*;5&/' 8!:!! )"),q("%$;60#*;6&/' 8!:!! )"),q('%%<2""67.) &2""67=.##&&!&\'#/6#1""5!7/($8":"! )("\'#&\'#.A &%2""67/1#;7/($8":"! )("\'#&\'#'),q('%%<2""67.) &2""67=.##&&!&\'#/6#1""5!7/($8":"! )("\'#&\'#.A &%2""67/1#;7/($8":"! )("\'#&\'#'),q('%4""5!7/\' 8!:!! )'),q('<%%2""67/U#;9/L$2""67/=$2""67.# & ." &"/#$+$)($\'#(#\'#("\'#&\'#/\' 8!:!! )=." 7'),q("%$;:/&#0#*;:&&&#/' 8!:!! )"),q('%%<2""67.) &2 ""6 7¡=.##&&!&\'#/6#1""5!7/($8":"! )("\'#&\'#.4 &%2 ""6 7¡/& 8!:¢! )'),q('<$;<0#*;<&=." 7£'),q('<4¤""5!7¥=." 7£')],p=0,$=[{line:1,column:1}],h=0,d=[],g=0;if("startRule"in n){if(!(n.startRule in i))throw new Error("Can't start parsing from rule \""+n.startRule+'".');c=i[n.startRule]}function y(e,r){return{type:"literal",text:e,ignoreCase:r}}function m(e,r,n){return{type:"class",parts:e,inverted:r,ignoreCase:n}}function k(e){return{type:"other",description:e}}function b(e){var n,t=$[e];if(t)return t;for(n=e-1;!$[n];)n--;for(t={line:(t=$[n]).line,column:t.column};n<e;)10===r.charCodeAt(n)?(t.line++,t.column=1):t.column++,n++;return $[e]=t,t}function v(e,r){var n=b(e),t=b(r);return{start:{offset:e,line:n.line,column:n.column},end:{offset:r,line:t.line,column:t.column}}}function x(e){p<h||(p>h&&(h=p,d=[]),d.push(e))}function q(e){return e.split("").map((function(e){return e.charCodeAt(0)-32}))}if((t=function e(n){for(var t,u=f[n],a=0,o=[],i=u.length,c=[],$=[];;){for(;a<i;)switch(u[a]){case 0:$.push(l[u[a+1]]),a+=2;break;case 1:$.push(void 0),a++;break;case 2:$.push(null),a++;break;case 3:$.push(s),a++;break;case 4:$.push([]),a++;break;case 5:$.push(p),a++;break;case 6:$.pop(),a++;break;case 7:p=$.pop(),a++;break;case 8:$.length-=u[a+1],a+=2;break;case 9:$.splice(-2,1),a++;break;case 10:$[$.length-2].push($.pop()),a++;break;case 11:$.push($.splice($.length-u[a+1],u[a+1])),a+=2;break;case 12:$.push(r.substring($.pop(),p)),a++;break;case 13:c.push(i),o.push(a+3+u[a+1]+u[a+2]),$[$.length-1]?(i=a+3+u[a+1],a+=3):(i=a+3+u[a+1]+u[a+2],a+=3+u[a+1]);break;case 14:c.push(i),o.push(a+3+u[a+1]+u[a+2]),$[$.length-1]===s?(i=a+3+u[a+1],a+=3):(i=a+3+u[a+1]+u[a+2],a+=3+u[a+1]);break;case 15:c.push(i),o.push(a+3+u[a+1]+u[a+2]),$[$.length-1]!==s?(i=a+3+u[a+1],a+=3):(i=a+3+u[a+1]+u[a+2],a+=3+u[a+1]);break;case 16:$[$.length-1]!==s?(c.push(i),o.push(a),i=a+2+u[a+1],a+=2):a+=2+u[a+1];break;case 17:c.push(i),o.push(a+3+u[a+1]+u[a+2]),r.length>p?(i=a+3+u[a+1],a+=3):(i=a+3+u[a+1]+u[a+2],a+=3+u[a+1]);break;case 18:c.push(i),o.push(a+4+u[a+2]+u[a+3]),r.substr(p,l[u[a+1]].length)===l[u[a+1]]?(i=a+4+u[a+2],a+=4):(i=a+4+u[a+2]+u[a+3],a+=4+u[a+2]);break;case 19:c.push(i),o.push(a+4+u[a+2]+u[a+3]),r.substr(p,l[u[a+1]].length).toLowerCase()===l[u[a+1]]?(i=a+4+u[a+2],a+=4):(i=a+4+u[a+2]+u[a+3],a+=4+u[a+2]);break;case 20:c.push(i),o.push(a+4+u[a+2]+u[a+3]),l[u[a+1]].test(r.charAt(p))?(i=a+4+u[a+2],a+=4):(i=a+4+u[a+2]+u[a+3],a+=4+u[a+2]);break;case 21:$.push(r.substr(p,u[a+1])),p+=u[a+1],a+=2;break;case 22:$.push(l[u[a+1]]),p+=l[u[a+1]].length,a+=2;break;case 23:$.push(s),0===g&&x(l[u[a+1]]),a+=2;break;case 24:$[$.length-1-u[a+1]],a+=2;break;case 25:p,a++;break;case 26:t=u.slice(a+4,a+4+u[a+3]).map((function(e){return $[$.length-1-e]})),$.splice($.length-u[a+2],u[a+2],l[u[a+1]].apply(null,t)),a+=4+u[a+3];break;case 27:$.push(e(u[a+1])),a+=2;break;case 28:g++,a++;break;case 29:g--,a++;break;default:throw new Error("Invalid opcode: "+u[a]+".")}if(!(c.length>0))break;i=c.pop(),a=o.pop()}return $[0]}(c))!==s&&p===r.length)return t;throw t!==s&&p<r.length&&x({type:"end"}),u=d,a=h<r.length?r.charAt(h):null,o=h<r.length?v(h,h+1):v(h,h),new e(e.buildMessage(u,a),u,a,o)}(t)}catch(e){return console.error("couldn't parse wizard input",e),!1}var c,l,f,p=[];switch(!0===u.comment?(p.push("/*"),p.push("This has been generated by the overpass-turbo wizard."),p.push("The original search was:"),p.push("“"+i(t)+"”"),p.push("*/")):"string"==typeof u.comment&&(p.push("/*"),p.push(u.comment),p.push("*/"),comment=!0),p.push("[out:"+u.outputFormat+"][timeout:"+u.timeout+"]"+(void 0!==u.maxsize?"[maxsize:"+u.maxsize+"]":"")+(u.globalBbox&&"bbox"===a.bounds?"[bbox:{{bbox}}]":"")+";"),a.bounds){case"area":u.comment&&p.push("// fetch area “"+a.area+"” to search in"),p.push("{{geocodeArea:"+a.area+"}}->.searchArea;"),c="(area.searchArea)";break;case"around":u.comment&&p.push("// adjust the search radius (in meters) here"),p.push("{{radius="+u.aroundRadius+"}}"),c="(around:{{radius}},{{geocodeCoords:"+a.area+"}})";break;case"bbox":c=u.globalBbox?"":"({{bbox}})";break;case"global":c=void 0;break;default:return console.error("unknown bounds condition: "+a.bounds),!1}function $(e){function r(e){return e.replace(/([()[{*+.$^\\|?])/g,"\\$1")}function n(e){if("string"==typeof e)return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\t/g,"\\t").replace(/\n/g,"\\n")}var t=n(e.key),u=n(e.val);switch("substr"===e.query&&(e.query="like",e.val={regex:r(e.val)}),""===u&&("eq"===e.query?(e.query="like",e.val={regex:"^$"}):"neq"===e.query&&(e.query="notlike",e.val={regex:"^$"})),""===t&&("key"===e.query?(e.query="likelike",e.key={regex:"^$"},e.val={regex:".*"}):"eq"===e.query?(e.query="likelike",e.key={regex:"^$"},e.val={regex:"^"+r(e.val)+"$"}):"like"===e.query&&(e.query="likelike",e.key={regex:"^$"})),e.query){case"key":return'["'+t+'"]';case"nokey":return'["'+t+'"!~".*"]';case"eq":return'["'+t+'"="'+u+'"]';case"neq":return'["'+t+'"!="'+u+'"]';case"like":return'["'+t+'"~"'+n(e.val.regex)+'"'+("i"===e.val.modifier?",i":"")+"]";case"likelike":return(e.key.modifier||"")==(e.val.modifier||"")?'[~"'+n(e.key.regex)+'"~"'+n(e.val.regex)+'"'+("i"===e.val.modifier?",i":"")+"]":"i"===e.val.modifier?'[~"'+n(e.key.regex)+'"~"'+n(e.val.regex)+'",i][~"'+n(e.key.regex)+'"~".*"]':'[~"'+n(e.key.regex)+'"~"'+n(e.val.regex)+'",i][~".*"~"'+n(e.val.regex)+'"]';case"notlike":return'["'+t+'"!~"'+n(e.val.regex)+'"'+("i"===e.val.modifier?",i":"")+"]";case"meta":switch(e.meta){case"id":return"("+u+")";case"newer":return e.val.match(/^-?\d+ ?(seconds?|minutes?|hours?|days?|weeks?|months?|years?)?$/)?'(newer:"{{date:'+u+'}}")':'(newer:"'+u+'")';case"user":return'(user:"'+u+'")';case"uid":return"(uid:"+u+")";default:return console.error("unknown query type: meta/"+e.meta),!1}case"free form":default:return console.error("unknown query type: "+e.query),!1}}function h(e){function r(e){return null===e.match(/^[a-zA-Z0-9_]+$/)?'"'+e.replace(/"/g,'\\"')+'"':e}function n(e){return null===e.regex.match(/^[a-zA-Z0-9_]+$/)||e.modifier?"/"+e.regex.replace(/\//g,"\\/")+"/"+(e.modifier||""):e.regex}switch(e.query){case"key":return i(r(e.key)+"=*");case"nokey":return i(r(e.key)+"!=*");case"eq":return i(r(e.key)+"="+r(e.val));case"neq":return i(r(e.key)+"!="+r(e.val));case"like":return i(r(e.key)+"~"+n(e.val));case"likelike":return i("~"+n(e.key)+"~"+n(e.val));case"notlike":return i(r(e.key)+"!~"+n(e.val));case"substr":return i(r(e.key)+":"+r(e.val));case"meta":switch(e.meta){case"id":return i("id:"+r(e.val));case"newer":return i("newer:"+r(e.val));case"user":return i("user:"+r(e.val));case"uid":return i("uid:"+r(e.val));default:return""}case"free form":return i(r(e.free));default:return""}}a.query=(l=a.query,(f={logical:"or",queries:[]}).queries=function e(r){if(!r.logical)return[{logical:"and",queries:[r]}];if("and"===r.logical){for(var n=e(r.queries[0]),t=e(r.queries[1]),u=[],a=0;a<n.length;a++)for(var o=0;o<t.length;o++)u.push({logical:"and",queries:n[a].queries.concat(t[o].queries)});return u}if("or"===r.logical)return n=e(r.queries[0]),t=e(r.queries[1]),[].concat(n,t);console.error("unsupported boolean operator: "+r.logical)}(l),f),u.comment&&p.push("// gather results"),p.push("(");for(var d=0;d<a.query.queries.length;d++){for(var g=a.query.queries[d],y=["node","way","relation"],m=[],k=[],b=0;b<g.queries.length;b++){var v=g.queries[b];if("free form"===v.query){n||(n=r(u.freeFormPresets));var x=n.get_query_clause(v);if(!1===x)return console.error("Couldn't find preset for free form input: "+v.free),!1;y=y.filter((function(e){return-1!=x.types.indexOf(e)})),u.comment&&k.push(h(v)),m=m.concat(x.conditions.map((function(e){return $(e)})))}else if("type"===v.query)y=-1!=y.indexOf(v.type)?[v.type]:[];else{u.comment&&k.push(h(v));var q=$(v);if(!1===q)return!1;m.push(q)}}k=k.join(" and "),u.comment&&p.push("  // query part for: “"+k+"”"),!1!==u.compactNWR&&3===y.length&&(y=["nwr"]);for(var w=0;w<y.length;w++){for(var A="  "+y[w],_=0;_<m.length;_++)A+=m[_];c&&(A+=c),A+=";",p.push(A)}}return p.push(");"),u.comment&&p.push("// print results"),"recursive"===u.outputMode?(p.push("out body;"),p.push(">;"),p.push("out skel qt;")):"recursive_meta"===u.outputMode?(p.push("(._;>;);"),p.push("out meta;")):p.push("out "+u.outputMode+";"),p.join("\n")}}();
Index: /trunk/src/org/openstreetmap/josm/data/osm/search/SearchCompiler.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/search/SearchCompiler.java	(revision 16261)
+++ /trunk/src/org/openstreetmap/josm/data/osm/search/SearchCompiler.java	(revision 16262)
@@ -505,5 +505,5 @@
      * Matches if the value of the corresponding key is ''yes'', ''true'', ''1'' or ''on''.
      */
-    private static class BooleanMatch extends TaggedMatch {
+    public static class BooleanMatch extends TaggedMatch {
         private final String key;
         private final boolean defaultValue;
@@ -512,4 +512,8 @@
             this.key = key;
             this.defaultValue = defaultValue;
+        }
+
+        public String getKey() {
+            return key;
         }
 
@@ -710,5 +714,5 @@
      * Matches objects with the given key-value pair.
      */
-    private static class KeyValue extends TaggedMatch {
+    public static class KeyValue extends TaggedMatch {
         private final String key;
         private final Pattern keyPattern;
@@ -775,4 +779,12 @@
         }
 
+        public String getKey() {
+            return key;
+        }
+
+        public String getValue() {
+            return value;
+        }
+
         @Override
         public String toString() {
@@ -891,5 +903,5 @@
     public static class ExactKeyValue extends TaggedMatch {
 
-        enum Mode {
+        public enum Mode {
             ANY, ANY_KEY, ANY_VALUE, EXACT, NONE, MISSING_KEY,
             ANY_KEY_REGEXP, ANY_VALUE_REGEXP, EXACT_REGEXP, MISSING_KEY_REGEXP;
@@ -1003,4 +1015,16 @@
         }
 
+        public String getKey() {
+            return key;
+        }
+
+        public String getValue() {
+            return value;
+        }
+
+        public Mode getMode() {
+            return mode;
+        }
+
         @Override
         public String toString() {
@@ -1148,5 +1172,5 @@
     }
 
-    private static class ExactType extends Match {
+    public static class ExactType extends Match {
         private final OsmPrimitiveType type;
 
@@ -1157,4 +1181,8 @@
         }
 
+        public OsmPrimitiveType getType() {
+            return type;
+        }
+
         @Override
         public boolean match(OsmPrimitive osm) {
@@ -1186,5 +1214,5 @@
      * Matches objects last changed by the given username.
      */
-    private static class UserMatch extends Match {
+    public static class UserMatch extends Match {
         private String user;
 
@@ -1195,4 +1223,8 @@
                 this.user = user;
             }
+        }
+
+        public String getUser() {
+            return user;
         }
 
Index: /trunk/src/org/openstreetmap/josm/gui/download/OverpassQueryWizardDialog.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/download/OverpassQueryWizardDialog.java	(revision 16261)
+++ /trunk/src/org/openstreetmap/josm/gui/download/OverpassQueryWizardDialog.java	(revision 16262)
@@ -221,5 +221,5 @@
                 .append(TR_START).append(TD_START)
                 .append(Utils.joinAsHtmlUnorderedList(Arrays.asList("<i>key=value</i>", "<i>key=*</i>", "<i>key~regex</i>",
-                        "<i>key!=value</i>", "<i>key!~regex</i>", "<i>key=\"combined value\"</i>")))
+                        "<i>-key=value</i>", "<i>-key~regex</i>", "<i>key=\"combined value\"</i>")))
                 .append(TD_END).append(TD_START)
                 .append(tr("<span>Download objects that have some concrete key/value pair, only the key with any contents for the value, " +
Index: /trunk/src/org/openstreetmap/josm/tools/OverpassTurboQueryWizard.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/tools/OverpassTurboQueryWizard.java	(revision 16261)
+++ /trunk/src/org/openstreetmap/josm/tools/OverpassTurboQueryWizard.java	(revision 16262)
@@ -2,25 +2,28 @@
 package org.openstreetmap.josm.tools;
 
-import java.io.IOException;
-import java.io.Reader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Optional;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 
-import javax.script.Invocable;
-import javax.script.ScriptEngine;
-import javax.script.ScriptException;
-
-import org.openstreetmap.josm.io.CachedFile;
-import org.openstreetmap.josm.spi.preferences.Config;
+import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
+import org.openstreetmap.josm.data.osm.search.SearchCompiler;
+import org.openstreetmap.josm.data.osm.search.SearchCompiler.Match;
+import org.openstreetmap.josm.data.osm.search.SearchParseError;
 
 /**
- * Uses <a href="https://github.com/tyrasd/overpass-wizard/">Overpass Turbo query wizard</a> code (MIT Licensed)
- * to build an Overpass QL from a {@link org.openstreetmap.josm.actions.search.SearchAction} like query.
+ * Builds an Overpass QL from a {@link org.openstreetmap.josm.actions.search.SearchAction} query.
  *
- * Requires a JavaScript {@link ScriptEngine}.
- * @since 8744
+ * @since 8744 (using tyrasd/overpass-wizard), 16262 (standalone)
  */
 public final class OverpassTurboQueryWizard {
 
-    private static OverpassTurboQueryWizard instance;
-    private final ScriptEngine engine = Utils.getJavaScriptEngine();
+    private static final OverpassTurboQueryWizard instance = new OverpassTurboQueryWizard();
 
     /**
@@ -29,30 +32,10 @@
      * @return the unique instance of this class
      */
-    public static synchronized OverpassTurboQueryWizard getInstance() {
-        if (instance == null) {
-            instance = new OverpassTurboQueryWizard();
-        }
+    public static OverpassTurboQueryWizard getInstance() {
         return instance;
     }
 
     private OverpassTurboQueryWizard() {
-        try (CachedFile file = new CachedFile("resource://data/overpass-wizard.js");
-             Reader reader = file.getContentReader()) {
-            if (engine != null) {
-                engine.eval("var console = {error: " + Logging.class.getCanonicalName() + ".warn};");
-                engine.eval("var global = {};");
-                engine.eval(reader);
-                engine.eval("var overpassWizardJOSM = function(query) {" +
-                        "  return overpassWizard(query, {" +
-                        "    comment: false," +
-                        "    timeout: " + Config.getPref().getInt("overpass.wizard.timeout", 90) + "," +
-                        "    outputFormat: 'xml'," +
-                        "    outputMode: 'recursive_meta'" +
-                        "  });" +
-                        "}");
-            }
-        } catch (ScriptException | IOException ex) {
-            throw new IllegalStateException("Failed to initialize OverpassTurboQueryWizard", ex);
-        }
+        // private constructor for utility class
     }
 
@@ -63,19 +46,151 @@
      * @throws UncheckedParseException when the parsing fails
      */
-    public String constructQuery(String search) {
-        if (engine == null) {
-            throw new IllegalStateException("Failed to retrieve JavaScript engine");
-        }
+    public String constructQuery(final String search) {
         try {
-            final Object result = ((Invocable) engine).invokeFunction("overpassWizardJOSM", search);
-            if (Boolean.FALSE.equals(result)) {
-                throw new UncheckedParseException();
+            Matcher matcher = Pattern.compile("\\s+GLOBAL\\s*$", Pattern.CASE_INSENSITIVE).matcher(search);
+            if (matcher.find()) {
+                final Match match = SearchCompiler.compile(matcher.replaceFirst(""));
+                return constructQuery(match, ";", "");
             }
-            return (String) result;
-        } catch (NoSuchMethodException e) {
-            throw new IllegalStateException(e);
-        } catch (ScriptException e) {
-            throw new UncheckedParseException("Failed to execute OverpassTurboQueryWizard", e);
+
+            matcher = Pattern.compile("\\s+IN BBOX\\s*$", Pattern.CASE_INSENSITIVE).matcher(search);
+            if (matcher.find()) {
+                final Match match = SearchCompiler.compile(matcher.replaceFirst(""));
+                return constructQuery(match, "[bbox:{{bbox}}];", "");
+            }
+
+            matcher = Pattern.compile("\\s+(?<mode>IN|AROUND)\\s+(?<area>[^\" ]+|\"[^\"]+\")\\s*$", Pattern.CASE_INSENSITIVE).matcher(search);
+            if (matcher.find()) {
+                final Match match = SearchCompiler.compile(matcher.replaceFirst(""));
+                final String mode = matcher.group("mode").toUpperCase(Locale.ENGLISH);
+                final String area = Utils.strip(matcher.group("area"), "\"");
+                if ("IN".equals(mode)) {
+                    return constructQuery(match, ";\n{{geocodeArea:" + area + "}}->.searchArea;", "(area.searchArea)");
+                } else if ("AROUND".equals(mode)) {
+                    return constructQuery(match, ";\n{{radius=1000}}", "(around:{{radius}},{{geocodeCoords:" + area + "}})");
+                } else {
+                    throw new IllegalStateException(mode);
+                }
+            }
+            
+            final Match match = SearchCompiler.compile(search);
+            return constructQuery(match, "[bbox:{{bbox}}];", "");
+        } catch (SearchParseError | UnsupportedOperationException e) {
+            throw new UncheckedParseException(e);
         }
     }
+
+    private String constructQuery(final Match match, final String bounds, final String queryLineSuffix) {
+        final List<Match> normalized = normalizeToDNF(match);
+        final List<String> queryLines = new ArrayList<>();
+        queryLines.add("[out:xml][timeout:90]" + bounds);
+        queryLines.add("(");
+        for (Match conjunction : normalized) {
+            final EnumSet<OsmPrimitiveType> types = EnumSet.noneOf(OsmPrimitiveType.class);
+            final String query = constructQuery(conjunction, types);
+            for (Object type : types.isEmpty() || types.size() == 3 ? Collections.singleton("nwr") : types) {
+                queryLines.add("  " + type + query + queryLineSuffix + ";");
+            }
+        }
+        queryLines.add(");");
+        queryLines.add("(._;>;);");
+        queryLines.add("out meta;");
+        return String.join("\n", queryLines);
+    }
+
+    private static String constructQuery(Match match, final Set<OsmPrimitiveType> types) {
+        final boolean negated;
+        if (match instanceof SearchCompiler.Not) {
+            negated = true;
+            match = ((SearchCompiler.Not) match).getMatch();
+        } else {
+            negated = false;
+        }
+        if (match instanceof SearchCompiler.And) {
+            return ((SearchCompiler.And) match).map(m -> constructQuery(m, types), (s1, s2) -> s1 + s2);
+        } else if (match instanceof SearchCompiler.KeyValue) {
+            final String key = ((SearchCompiler.KeyValue) match).getKey();
+            final String value = ((SearchCompiler.KeyValue) match).getValue();
+            return "[~" + quote(key) + "~" + quote(value) + "]";
+        } else if (match instanceof SearchCompiler.ExactKeyValue) {
+            // https://wiki.openstreetmap.org/wiki/Overpass_API/Language_Guide
+            // ["key"]             -- filter objects tagged with this key and any value
+            // [!"key"]            -- filter objects not tagged with this key and any value
+            // ["key"="value"]     -- filter objects tagged with this key and this value
+            // ["key"!="value"]    -- filter objects tagged with this key but not this value, or not tagged with this key
+            // ["key"~"value"]     -- filter objects tagged with this key and a value matching a regular expression
+            // ["key"!~"value"]    -- filter objects tagged with this key but a value not matching a regular expression
+            // [~"key"~"value"]    -- filter objects tagged with a key and a value matching regular expressions
+            // [~"key"~"value", i] -- filter objects tagged with a key and a case-insensitive value matching regular expressions
+            final String key = ((SearchCompiler.ExactKeyValue) match).getKey();
+            final String value = ((SearchCompiler.ExactKeyValue) match).getValue();
+            final SearchCompiler.ExactKeyValue.Mode mode = ((SearchCompiler.ExactKeyValue) match).getMode();
+            switch (mode) {
+                case ANY_VALUE:
+                    return "[" + (negated ? "!" : "") + quote(key) + "]";
+                case EXACT:
+                    return "[" + quote(key) + (negated ? "!=" : "=") + quote(value) + "]";
+                case EXACT_REGEXP:
+                    final Matcher matcher = Pattern.compile("/(?<regex>.*)/(?<flags>i)?").matcher(value);
+                    final String valueQuery = matcher.matches()
+                            ? quote(matcher.group("regex")) + Optional.ofNullable(matcher.group("flags")).map(f -> "," + f).orElse("")
+                            : quote(value);
+                    return "[" + quote(key) + (negated ? "!~" : "~") + valueQuery + "]";
+                case MISSING_KEY:
+                    // special case for empty values, see https://github.com/drolbr/Overpass-API/issues/53
+                    return "[" + quote(key) + (negated ? "!~" : "~") + quote("^$") + "]";
+                default:
+                    return "";
+            }
+        } else if (match instanceof SearchCompiler.BooleanMatch) {
+            final String key = ((SearchCompiler.BooleanMatch) match).getKey();
+            return negated
+                    ? "[" + quote(key) + "~\"false|no|0|off\"]"
+                    : "[" + quote(key) + "~\"true|yes|1|on\"]";
+        } else if (match instanceof SearchCompiler.UserMatch) {
+            final String user = ((SearchCompiler.UserMatch) match).getUser();
+            return user.matches("\\d+")
+                    ? "(uid:" + user + ")"
+                    : "(user:" + quote(user) + ")";
+        } else if (match instanceof SearchCompiler.ExactType) {
+            types.add(((SearchCompiler.ExactType) match).getType());
+            return "";
+        }
+        Logging.warn("Unsupported match type {0}: {1}", match.getClass(), match);
+        return "/*" + match + "*/";
+    }
+
+    /**
+     * Quotes the given string for its use in Overpass QL
+     */
+    private static String quote(final String s) {
+        return "\"" + s.replace("\\", "\\\\").replace("\"", "\\\"") + "\"";
+    }
+
+    /**
+     * Normalizes the match to disjunctive normal form: A∧(B∨C) ⇔ (A∧B)∨(A∧C)
+     */
+    private static List<Match> normalizeToDNF(final Match match) {
+        if (match instanceof SearchCompiler.And) {
+            return ((SearchCompiler.And) match).map(OverpassTurboQueryWizard::normalizeToDNF, (lhs, rhs) -> lhs.stream()
+                    .flatMap(l -> rhs.stream().map(r -> new SearchCompiler.And(l, r)))
+                    .collect(Collectors.toList()));
+        } else if (match instanceof SearchCompiler.Or) {
+            return ((SearchCompiler.Or) match).map(OverpassTurboQueryWizard::normalizeToDNF, CompositeList::new);
+        } else if (match instanceof SearchCompiler.Xor) {
+            throw new UnsupportedOperationException(match.toString());
+        } else if (match instanceof SearchCompiler.Not) {
+            // only support negated KeyValue or ExactKeyValue matches
+            final Match innerMatch = ((SearchCompiler.Not) match).getMatch();
+            if (innerMatch instanceof SearchCompiler.BooleanMatch
+                    || innerMatch instanceof SearchCompiler.KeyValue
+                    || innerMatch instanceof SearchCompiler.ExactKeyValue) {
+                return Collections.singletonList(match);
+            }
+            throw new UnsupportedOperationException(match.toString());
+        } else {
+            return Collections.singletonList(match);
+        }
+    }
+
 }
Index: /trunk/test/unit/org/openstreetmap/josm/tools/OverpassTurboQueryWizardTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/tools/OverpassTurboQueryWizardTest.java	(revision 16261)
+++ /trunk/test/unit/org/openstreetmap/josm/tools/OverpassTurboQueryWizardTest.java	(revision 16262)
@@ -39,4 +39,5 @@
     public void testKeyValue() {
         assertQueryEquals("  nwr[\"amenity\"=\"drinking_water\"];\n", "amenity=drinking_water");
+        assertQueryEquals("  nwr[\"amenity\"];\n", "amenity=*");
     }
 
@@ -46,6 +47,6 @@
     @Test
     public void testKeyNotValue() {
-        assertQueryEquals("  nwr[\"amenity\"!=\"drinking_water\"];\n", "amenity!=drinking_water");
-        assertQueryEquals("  nwr[\"amenity\"!=\"drinking_water\"];\n", "amenity<>drinking_water");
+        assertQueryEquals("  nwr[\"amenity\"!=\"drinking_water\"];\n", "-amenity=drinking_water");
+        assertQueryEquals("  nwr[!\"amenity\"];\n", "-amenity=*");
     }
 
@@ -57,13 +58,18 @@
         assertQueryEquals("  nwr[\"foo\"~\"bar\"];\n", "foo~bar");
         assertQueryEquals("  nwr[\"foo\"~\"bar\"];\n", "foo~/bar/");
-        assertQueryEquals("  nwr[\"foo\"~\"bar\"];\n", "foo~=bar");
-        assertQueryEquals("  nwr[\"foo\"~\"bar\"];\n", "foo~=/bar/");
-        assertQueryEquals("  nwr[\"foo\"~\"bar\"];\n", "foo like bar");
-        assertQueryEquals("  nwr[\"foo\"~\"bar\"];\n", "foo like /bar/");
         // case insensitive
         assertQueryEquals("  nwr[\"foo\"~\"bar\",i];\n", "foo~/bar/i");
         // negated
-        assertQueryEquals("  nwr[\"foo\"!~\"bar\"];\n", "foo!~bar");
-        assertQueryEquals("  nwr[\"foo\"!~\"bar\"];\n", "foo not like bar");
+        assertQueryEquals("  nwr[\"foo\"!~\"bar\"];\n", "-foo~bar");
+        assertQueryEquals("  nwr[\"foo\"!~\"bar\",i];\n", "-foo~/bar/i");
+    }
+
+    /**
+     * Test OSM boolean true/false.
+     */
+    @Test
+    public void testOsmBoolean() {
+        assertQueryEquals("  nwr[\"highway\"][\"oneway\"~\"true|yes|1|on\"];\n", "highway=* AND oneway?");
+        assertQueryEquals("  nwr[\"highway\"][\"oneway\"~\"false|no|0|off\"];\n", "highway=* AND -oneway?");
     }
 
@@ -84,5 +90,4 @@
     public void testBooleanOr() {
         assertQueryEquals("  nwr[\"foo\"=\"bar\"];\n  nwr[\"baz\"=\"42\"];\n", "foo=bar or baz=42");
-        assertQueryEquals("  nwr[\"foo\"=\"bar\"];\n  nwr[\"baz\"=\"42\"];\n", "foo=bar || baz=42");
         assertQueryEquals("  nwr[\"foo\"=\"bar\"];\n  nwr[\"baz\"=\"42\"];\n", "foo=bar | baz=42");
     }
@@ -118,5 +123,5 @@
     @Test
     public void testUser() {
-        assertQueryEquals("  nwr(user:\"foo\");\n  nwr(uid:42);\n", "user:foo or uid:42");
+        assertQueryEquals("  nwr(user:\"foo\");\n  nwr(uid:42);\n", "user:foo or user:42");
     }
 
@@ -126,5 +131,5 @@
     @Test
     public void testEmpty() {
-        assertQueryEquals("  way[\"foo\"~\"^$\"];\n", "foo='' and type:way");
+        assertQueryEquals("  way[\"foo\"~\"^$\"];\n", "foo=\"\" and type:way");
     }
 
@@ -220,5 +225,5 @@
     @Test(expected = UncheckedParseException.class)
     public void testErroneous() {
-        OverpassTurboQueryWizard.getInstance().constructQuery("foo");
+        OverpassTurboQueryWizard.getInstance().constructQuery("-(foo or bar)");
     }
 }
