From 8d3840c2532a32a16aff6c7b27125c784b1c6f6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9C=D0=B8=D1=85=D0=B0=D0=B8=D0=BB=20=D0=94=D1=83=D0=BA?= =?UTF-8?q?=D0=B8=D0=BD?= Date: Mon, 3 Mar 2025 00:18:08 +0300 Subject: [PATCH 01/26] =?UTF-8?q?errorCode200=20=D0=A5=D0=B0=D0=BA=D0=B0?= =?UTF-8?q?=D1=82=D0=BE=D0=BD=20$mol?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- License.MD | 7 + index.html | 505 ---- jquery.min.js | 2 - mevents.js | 160 - mgui.js | 327 -- mrouter.js | 115 - optimade_zero/entry.ts | 115 + optimade_zero/index.html | 25 + optimade_zero/input.view.css.ts | 56 + optimade_zero/input.view.tree | 14 + optimade_zero/input.view.ts | 57 + optimade_zero/optimade_zero.test.ts | 17 + optimade_zero/optimade_zero.view.css.ts | 62 + optimade_zero/optimade_zero.view.tree | 61 + optimade_zero/optimade_zero.view.ts | 137 + optimade_zero/search.ts | 254 ++ optimade_zero/tag.view.css.ts | 31 + optimade_zero/tag.view.tree | 7 + optimade_zero/tag.view.ts | 9 + selectize.js | 3684 ----------------------- selectize_preserve_on_blur.js | 41 - wmcore.js | 498 --- wmsettings.js | 52 - 23 files changed, 852 insertions(+), 5384 deletions(-) create mode 100644 License.MD delete mode 100644 index.html delete mode 100644 jquery.min.js delete mode 100644 mevents.js delete mode 100644 mgui.js delete mode 100644 mrouter.js create mode 100644 optimade_zero/entry.ts create mode 100644 optimade_zero/index.html create mode 100644 optimade_zero/input.view.css.ts create mode 100644 optimade_zero/input.view.tree create mode 100644 optimade_zero/input.view.ts create mode 100644 optimade_zero/optimade_zero.test.ts create mode 100644 optimade_zero/optimade_zero.view.css.ts create mode 100644 optimade_zero/optimade_zero.view.tree create mode 100644 optimade_zero/optimade_zero.view.ts create mode 100644 optimade_zero/search.ts create mode 100644 optimade_zero/tag.view.css.ts create mode 100644 optimade_zero/tag.view.tree create mode 100644 optimade_zero/tag.view.ts delete mode 100644 selectize.js delete mode 100644 selectize_preserve_on_blur.js delete mode 100644 wmcore.js delete mode 100644 wmsettings.js diff --git a/License.MD b/License.MD new file mode 100644 index 0000000..29cc5a5 --- /dev/null +++ b/License.MD @@ -0,0 +1,7 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/index.html b/index.html deleted file mode 100644 index 3a549d0..0000000 --- a/index.html +++ /dev/null @@ -1,505 +0,0 @@ - - - - - - - - - - - - - -−273.15°C - - - - - - -
- -
- -
Unrecognized input
- -
- - - -
- -
- -
-
Login
- -
- -
- -
-
Send link
-
or login with password
-
- -
-
- -
−273.15°C
-
-
- -
-
- -
−273.15°C
-
- -
Input
-
    - -
    Data summary
    -
      - -
      Results
      -
      - -
      New search
      -
      -
      - - - - - - diff --git a/jquery.min.js b/jquery.min.js deleted file mode 100644 index 7f37b5d..0000000 --- a/jquery.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! jQuery v3.7.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */ -!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(ie,e){"use strict";var oe=[],r=Object.getPrototypeOf,ae=oe.slice,g=oe.flat?function(e){return oe.flat.call(e)}:function(e){return oe.concat.apply([],e)},s=oe.push,se=oe.indexOf,n={},i=n.toString,ue=n.hasOwnProperty,o=ue.toString,a=o.call(Object),le={},v=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},y=function(e){return null!=e&&e===e.window},C=ie.document,u={type:!0,src:!0,nonce:!0,noModule:!0};function m(e,t,n){var r,i,o=(n=n||C).createElement("script");if(o.text=e,t)for(r in u)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function x(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[i.call(e)]||"object":typeof e}var t="3.7.1",l=/HTML$/i,ce=function(e,t){return new ce.fn.init(e,t)};function c(e){var t=!!e&&"length"in e&&e.length,n=x(e);return!v(e)&&!y(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+ge+")"+ge+"*"),x=new RegExp(ge+"|>"),j=new RegExp(g),A=new RegExp("^"+t+"$"),D={ID:new RegExp("^#("+t+")"),CLASS:new RegExp("^\\.("+t+")"),TAG:new RegExp("^("+t+"|[*])"),ATTR:new RegExp("^"+p),PSEUDO:new RegExp("^"+g),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+ge+"*(even|odd|(([+-]|)(\\d*)n|)"+ge+"*(?:([+-]|)"+ge+"*(\\d+)|))"+ge+"*\\)|)","i"),bool:new RegExp("^(?:"+f+")$","i"),needsContext:new RegExp("^"+ge+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+ge+"*((?:-\\d)?\\d*)"+ge+"*\\)|)(?=[^-]|$)","i")},N=/^(?:input|select|textarea|button)$/i,q=/^h\d$/i,L=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,H=/[+~]/,O=new RegExp("\\\\[\\da-fA-F]{1,6}"+ge+"?|\\\\([^\\r\\n\\f])","g"),P=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},M=function(){V()},R=J(function(e){return!0===e.disabled&&fe(e,"fieldset")},{dir:"parentNode",next:"legend"});try{k.apply(oe=ae.call(ye.childNodes),ye.childNodes),oe[ye.childNodes.length].nodeType}catch(e){k={apply:function(e,t){me.apply(e,ae.call(t))},call:function(e){me.apply(e,ae.call(arguments,1))}}}function I(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(V(e),e=e||T,C)){if(11!==p&&(u=L.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return k.call(n,a),n}else if(f&&(a=f.getElementById(i))&&I.contains(e,a)&&a.id===i)return k.call(n,a),n}else{if(u[2])return k.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&e.getElementsByClassName)return k.apply(n,e.getElementsByClassName(i)),n}if(!(h[t+" "]||d&&d.test(t))){if(c=t,f=e,1===p&&(x.test(t)||m.test(t))){(f=H.test(t)&&U(e.parentNode)||e)==e&&le.scope||((s=e.getAttribute("id"))?s=ce.escapeSelector(s):e.setAttribute("id",s=S)),o=(l=Y(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+Q(l[o]);c=l.join(",")}try{return k.apply(n,f.querySelectorAll(c)),n}catch(e){h(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return re(t.replace(ve,"$1"),e,n,r)}function W(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function F(e){return e[S]=!0,e}function $(e){var t=T.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function B(t){return function(e){return fe(e,"input")&&e.type===t}}function _(t){return function(e){return(fe(e,"input")||fe(e,"button"))&&e.type===t}}function z(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&R(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function X(a){return F(function(o){return o=+o,F(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function U(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}function V(e){var t,n=e?e.ownerDocument||e:ye;return n!=T&&9===n.nodeType&&n.documentElement&&(r=(T=n).documentElement,C=!ce.isXMLDoc(T),i=r.matches||r.webkitMatchesSelector||r.msMatchesSelector,r.msMatchesSelector&&ye!=T&&(t=T.defaultView)&&t.top!==t&&t.addEventListener("unload",M),le.getById=$(function(e){return r.appendChild(e).id=ce.expando,!T.getElementsByName||!T.getElementsByName(ce.expando).length}),le.disconnectedMatch=$(function(e){return i.call(e,"*")}),le.scope=$(function(){return T.querySelectorAll(":scope")}),le.cssHas=$(function(){try{return T.querySelector(":has(*,:jqfake)"),!1}catch(e){return!0}}),le.getById?(b.filter.ID=function(e){var t=e.replace(O,P);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&C){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(O,P);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&C){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):t.querySelectorAll(e)},b.find.CLASS=function(e,t){if("undefined"!=typeof t.getElementsByClassName&&C)return t.getElementsByClassName(e)},d=[],$(function(e){var t;r.appendChild(e).innerHTML="",e.querySelectorAll("[selected]").length||d.push("\\["+ge+"*(?:value|"+f+")"),e.querySelectorAll("[id~="+S+"-]").length||d.push("~="),e.querySelectorAll("a#"+S+"+*").length||d.push(".#.+[+~]"),e.querySelectorAll(":checked").length||d.push(":checked"),(t=T.createElement("input")).setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),r.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&d.push(":enabled",":disabled"),(t=T.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||d.push("\\["+ge+"*name"+ge+"*="+ge+"*(?:''|\"\")")}),le.cssHas||d.push(":has"),d=d.length&&new RegExp(d.join("|")),l=function(e,t){if(e===t)return a=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!le.sortDetached&&t.compareDocumentPosition(e)===n?e===T||e.ownerDocument==ye&&I.contains(ye,e)?-1:t===T||t.ownerDocument==ye&&I.contains(ye,t)?1:o?se.call(o,e)-se.call(o,t):0:4&n?-1:1)}),T}for(e in I.matches=function(e,t){return I(e,null,null,t)},I.matchesSelector=function(e,t){if(V(e),C&&!h[t+" "]&&(!d||!d.test(t)))try{var n=i.call(e,t);if(n||le.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){h(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(O,P),e[3]=(e[3]||e[4]||e[5]||"").replace(O,P),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||I.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&I.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return D.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&j.test(n)&&(t=Y(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(O,P).toLowerCase();return"*"===e?function(){return!0}:function(e){return fe(e,t)}},CLASS:function(e){var t=s[e+" "];return t||(t=new RegExp("(^|"+ge+")"+e+"("+ge+"|$)"))&&s(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=I.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function T(e,n,r){return v(n)?ce.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?ce.grep(e,function(e){return e===n!==r}):"string"!=typeof n?ce.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(ce.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||k,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:S.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof ce?t[0]:t,ce.merge(this,ce.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:C,!0)),w.test(r[1])&&ce.isPlainObject(t))for(r in t)v(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=C.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):v(e)?void 0!==n.ready?n.ready(e):e(ce):ce.makeArray(e,this)}).prototype=ce.fn,k=ce(C);var E=/^(?:parents|prev(?:Until|All))/,j={children:!0,contents:!0,next:!0,prev:!0};function A(e,t){while((e=e[t])&&1!==e.nodeType);return e}ce.fn.extend({has:function(e){var t=ce(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,Ce=/^$|^module$|\/(?:java|ecma)script/i;xe=C.createDocumentFragment().appendChild(C.createElement("div")),(be=C.createElement("input")).setAttribute("type","radio"),be.setAttribute("checked","checked"),be.setAttribute("name","t"),xe.appendChild(be),le.checkClone=xe.cloneNode(!0).cloneNode(!0).lastChild.checked,xe.innerHTML="",le.noCloneChecked=!!xe.cloneNode(!0).lastChild.defaultValue,xe.innerHTML="",le.option=!!xe.lastChild;var ke={thead:[1,"","
      "],col:[2,"","
      "],tr:[2,"","
      "],td:[3,"","
      "],_default:[0,"",""]};function Se(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&fe(e,t)?ce.merge([e],n):n}function Ee(e,t){for(var n=0,r=e.length;n",""]);var je=/<|&#?\w+;/;function Ae(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function Re(e,t){return fe(e,"table")&&fe(11!==t.nodeType?t:t.firstChild,"tr")&&ce(e).children("tbody")[0]||e}function Ie(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function We(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Fe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(_.hasData(e)&&(s=_.get(e).events))for(i in _.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),C.head.appendChild(r[0])},abort:function(){i&&i()}}});var Jt,Kt=[],Zt=/(=)\?(?=&|$)|\?\?/;ce.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Kt.pop()||ce.expando+"_"+jt.guid++;return this[e]=!0,e}}),ce.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Zt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Zt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=v(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Zt,"$1"+r):!1!==e.jsonp&&(e.url+=(At.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||ce.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=ie[r],ie[r]=function(){o=arguments},n.always(function(){void 0===i?ce(ie).removeProp(r):ie[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Kt.push(r)),o&&v(i)&&i(o[0]),o=i=void 0}),"script"}),le.createHTMLDocument=((Jt=C.implementation.createHTMLDocument("").body).innerHTML="
      ",2===Jt.childNodes.length),ce.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(le.createHTMLDocument?((r=(t=C.implementation.createHTMLDocument("")).createElement("base")).href=C.location.href,t.head.appendChild(r)):t=C),o=!n&&[],(i=w.exec(e))?[t.createElement(i[1])]:(i=Ae([e],t,o),o&&o.length&&ce(o).remove(),ce.merge([],i.childNodes)));var r,i,o},ce.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(ce.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},ce.expr.pseudos.animated=function(t){return ce.grep(ce.timers,function(e){return t===e.elem}).length},ce.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=ce.css(e,"position"),c=ce(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=ce.css(e,"top"),u=ce.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),v(t)&&(t=t.call(e,n,ce.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},ce.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){ce.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===ce.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===ce.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=ce(e).offset()).top+=ce.css(e,"borderTopWidth",!0),i.left+=ce.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-ce.css(r,"marginTop",!0),left:t.left-i.left-ce.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===ce.css(e,"position"))e=e.offsetParent;return e||J})}}),ce.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;ce.fn[t]=function(e){return M(this,function(e,t,n){var r;if(y(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),ce.each(["top","left"],function(e,n){ce.cssHooks[n]=Ye(le.pixelPosition,function(e,t){if(t)return t=Ge(e,n),_e.test(t)?ce(e).position()[n]+"px":t})}),ce.each({Height:"height",Width:"width"},function(a,s){ce.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){ce.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return M(this,function(e,t,n){var r;return y(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?ce.css(e,t,i):ce.style(e,t,n,i)},s,n?e:void 0,n)}})}),ce.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){ce.fn[t]=function(e){return this.on(t,e)}}),ce.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.on("mouseenter",e).on("mouseleave",t||e)}}),ce.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){ce.fn[n]=function(e,t){return 0' + link_text + ''; - }); - $('a.extd_refine[rel=' + facet + ']').parent().hide().after(z(html)); - - }).fail(function(xhr, textStatus, errorThrown){ - if (textStatus != 'abort') wmgui.notify('Connection to server is lost, please try to reload'); - }); - return false; - }); - - $('#navicon').click(function(){ - if ($(this).hasClass('opened')){ - $(this).removeClass('opened'); - $('#hamburger').addClass('closed'); - $('#overlay, #menu_content').hide(); - } else { - $(this).addClass('opened'); - $('#hamburger').removeClass('closed'); - $('#overlay, #menu_content').show(); - } - }); - - $('#menu_content > ul > li > a').click(function(){ - $('#navicon').removeClass('opened'); - $('#hamburger').addClass('closed'); - $('#overlay, #menu_content').hide(); - return true; - }); - - $('#login_trigger').click(function(){ - if ($(this).data('busy')) return; - $(this).data('busy', true); - $.ajax({type: 'POST', url: wmgui.login_endpoint, data: {login: $('#login_email').val().trim(), pass: $('#login_password').val()}, beforeSend: show_preloader}).always(function(){ - $('#login_trigger').data('busy', false); - hide_preloader(); - - }).done(function(data){ - if (data.error) return wmgui.notify(data.error); - if (!data.sid || !data.name || !data.acclogin) return wmgui.notify('Connection to server is lost, please try to reload'); - user_login(data.sid, data.name, data.acclogin, data.admin); - window.location.hash = '#start'; - $('#navicon').trigger('click'); - $('#loginbox, #restorebox').hide(); - - }).fail(function(xhr, textStatus, errorThrown){ - wmgui.notify("Login unsuccessful"); - }); - }); - - $('#restore_trigger').click(function(){ - if ($(this).data('busy')) return; - $(this).data('busy', true); - $.ajax({type: 'POST', url: wmgui.restore_endpoint, data: {login: $('#restore_by_email').val().trim()}, beforeSend: show_preloader}).always(function(){ - $('#restore_trigger').data('busy', false); - hide_preloader(); - - }).done(function(data){ - if (data.error) return wmgui.notify(data.error); - wmgui.notify('Please, check your inbox (and spam)'); - $('#navicon').trigger('click'); - $('#loginbox, #restorebox').hide(); - - }).fail(function(xhr, textStatus, errorThrown){ - if (textStatus != 'abort') wmgui.notify('A network error occured. Please, try again'); - }); - }); - - $('div.cross').click(function(){ - window.location.hash = '#start'; - }); - - $('#logout_item').click(function(){ - $.ajax({type: 'POST', url: wmgui.logout_endpoint, data: {sid: wmgui.sid}}).done(function(data){}).fail(function(xhr, textStatus, errorThrown){}); - user_logout(); - }); - - $(document).keydown(function(e){ - var key = window.event ? e.keyCode : e.which; - if (key == 13) $('#search_trigger').trigger('click'); - }); - - $(window).bind('hashchange', url_redraw_react); -} diff --git a/mgui.js b/mgui.js deleted file mode 100644 index e95a7a9..0000000 --- a/mgui.js +++ /dev/null @@ -1,327 +0,0 @@ -/** - * Mobile GUI for the chemistry DB - * Version: 0.5.5ce - */ -"use strict"; - -wmgui.notify = function(msg){ - console.log(msg); - alert(msg); - close_vibox(); -} - -function switch_viewmode(mode){ - - wmgui.viewmode = mode; - - if (mode == 2){ - $('#branding').hide(); - $('#content').show(); - window.scrollTo(0, 0); - - $('#summary, #results, #summary_caption, #results_caption').hide(); - - } else { - $('#content').hide(); - $('#branding').show(); - $('#search_field-selectized').focus(); - } -} - -function request_analysis(query_obj){ - var given_search = {}; - $.extend(given_search, query_obj); - try { wmgui.active_ajax.abort() } catch(e){} - wmgui.active_ajax = $.ajax({type: 'GET', url: wmgui.rfn_endpoint, data: {q: JSON.stringify(given_search)}, beforeSend: show_preloader}).always(hide_preloader).done(function(data){ - if (data.error) return wmgui.notify(data.error); - - var was_facet = null, - refine_html = '', - classes_chk = [], - max_count = 0; - - if (query_obj.classes){ // no whitespace in multiple classes - classes_chk = given_search.classes.split(',').map(function(i){ return i.trim() }); - given_search.classes = classes_chk.join(','); - } - - $.each(data.payload, function(i, found_obj){ - if (query_obj.formulae && found_obj.facet == 'elements') return true; // NB no sense to show elements in this context - - var link_text = found_obj.value, - nested_skip = false, - orepr = {}; - - if (found_obj.count > max_count) max_count = found_obj.count; - - $.each(given_search, function(key, val){ // compile individual search link - if (found_obj.facet == 'elements' && (key == 'elements' || key == 'formulae')) return true; - else if (found_obj.facet == 'props' && key == 'props') return true; - else if (orepr[key] && key == 'classes') val += ', ' + orepr[key]; - orepr[key] = val; - }); - - if (query_obj.classes && found_obj.facet == 'classes'){ - $.each(classes_chk, function(n, cls){ - if (cls == found_obj.value){ nested_skip = true; return false; } - }); - } - if (nested_skip) return true; - - if (found_obj.facet != was_facet){ - if (was_facet) refine_html += '
    • Show more
    • '; - refine_html += '
    • ' + wmgui.facet_names[found_obj.facet] + '
    • '; - was_facet = found_obj.facet; - } - if (found_obj.facet == 'props'){ - found_obj.value = found_obj.value.replace(/\(|\)/g, "").replace(/\/[\w\-]*/g, ""); // FIXME! - } - - // FIXME!!! lost classes in refinement: see #inquiry/classes=alkaline&years=2010-2018 - orepr[found_obj.facet] = found_obj.value; - if (orepr['elements']) orepr['elements'] = orepr['elements'].replaceAll(', ', '-'); - - refine_html += '
    • ' + link_text + '
    • '; - }); - - if (refine_html.length){ - refine_html += '
    • Show more
    • '; - if (max_count > 50){ - $('#summary > ul').empty().append(z(refine_html)).parent().show(); - $('#summary_caption').show(); - } - } - - request_data(query_obj); - - }).fail(function(xhr, textStatus, errorThrown){ - if (textStatus != 'abort') wmgui.notify('Connection to server is lost, please try to reload'); - }); -} - -function request_data(query_obj){ - wmgui.active_ajax = $.ajax({type: 'GET', url: wmgui.srch_endpoint, data: {q: JSON.stringify(query_obj)}, beforeSend: show_preloader}).always(hide_preloader).done(function(data){ - if (data.error) - return wmgui.notify(data.error); - if (!data.out.length) - return wmgui.notify('Nothing found!'); - if (data.notice) - wmgui.notify(data.notice); - if (data.fuzzy_notice) - wmgui.notify(data.fuzzy_notice); - - var cls_map = {7: ' ml_data', 8: ' ab_data', 9: ' ab_data', 10: ' ab_data'}, // NB space - result_cells = ''; - - data.out.sort(function(a, b){ - var x = a[2].toLowerCase(), - y = b[2].toLowerCase(); - return x < y ? -1 : x > y ? 1 : 0; - }); - - $.each(data.out, function(k, row){ - row[7] = parseInt(row[7]); - var dtype = row[0].substr(0, 1), - content, - dlinks = 'Log in to access', - biblio_html = (row[7] == 999999) ? '' : - '
      [' + row[5] + '’' + row[6].toString().substr(2, 2) + ']'; // special *ref_id*, only handled in GUI - - if (wmgui.sid && biblio_html) dlinks = 'Ref.PDF'; - - if (dtype == 'P'){ - content = '
      ' + row[2] + '
      '; - - } else if (dtype == 'C'){ - content = '' + row[0] + ''; // NB handled remotely - if (wmgui.sid) dlinks = 'PNG'; - - } else { - content = '' + row[0] + ''; // NB handled remotely - dlinks = 'PNGanim'; - } - - result_cells += ''; - }); - - if (result_cells.length){ - $('#results').empty().append(result_cells).show(); - $('#results_caption').show(); - } - }).fail(function(xhr, textStatus, errorThrown){ - if (textStatus != 'abort') wmgui.notify('Connection to server is lost, please try to reload'); - }); -} - -function close_vibox(){ - var iframe = $('#iframe'); - if (iframe.length){ - $('#iframe').remove(); - $('#overlay').hide(); - $('#hamburger').show(); - return true; - } - return false; -} - -function rotate_example(){ - var example = WMCORE.generate_example(); - $('#legend').html('e.g. ' + example['text'].replace(/\d/g, "Ȉ$&;") + ''); -} - -function rotate_motto(){ - $('#motto > span').animate({ opacity: 'hide' }, 2500, function(){ - $('#motto > span').html(wmgui.mob_motto[ Math.floor(Math.random() * wmgui.mob_motto.length) ]).animate({ opacity: 'show' }, 1500, function(){ - setTimeout(rotate_motto, 2500); - }); - }); -} - -function user_login(sid, name, acclogin, admin){ - $('#user_status > span').text(name); - $('#login_item').hide(); - $('#logout_item').show(); - wmgui.sid = sid; - window.localStorage.setItem('wm', JSON.stringify({sid: sid, name: name, acclogin: acclogin, admin: admin})); -} - -function user_logout(){ - $('#user_status > span').text('Hi, guest'); - $('#logout_item').hide(); - $('#login_item').show(); - wmgui.sid = null; - window.localStorage.removeItem('wm'); -} - -function satisfy_requirements(){ - - var locals = JSON.parse(window.localStorage.getItem('wm') || '{}'); - if (locals.sid && locals.name && locals.acclogin){ - user_login(locals.sid, locals.name, locals.acclogin, locals.admin); - } - - WMCORE = WMCORE(); - - rotate_example(); - setInterval(rotate_example, 2250); - $('#motto > span').html(wmgui.mob_motto[ Math.floor(Math.random() * wmgui.mob_motto.length) ]); - setTimeout(rotate_motto, 2500); - - var control = $('#search_field').selectize({ - plugins: ['remove_button', 'preserve_on_blur'], - dropdownParent: '#suggestions', - valueField: 'id', - labelField: 'label', - searchField: 'label', - create: false, - maxItems: 5, - closeAfterSelect: true, - diacritics: false, - options: [], - onInitialize: function(){ - $('#searchbox > div.selectize-control').append(''); - $('#search_field-selectized').focus(); - }, - load: function(query, callback){ - this.clearOptions(); - $('#selectize_msg').hide(); - if (!query.length) return callback(); - $.ajax({ - url: wmgui.api_host + '/search/selectize?q=' + encodeURIComponent(query), - type: 'GET', - error: callback, - success: function(res){ - //console.log(res.length); - $('#suggestions').show(); - if (!res.length){ - $('#selectize_msg').show(); - $('#search_trigger').hide(); - return; - } - callback(res); - } - }); - }, - score: function(){ return function(){ return 1 } }, // no client scoring - onFocus: function(){ - if ($.isEmptyObject(this.renderCache)) return; - $('#suggestions').show(); - }, - onBlur: function(){ - $('#suggestions').hide(); - }, - render: { - option: function(item, escape){ - return '
      ' + item.label + '
      '; - }, - item: function(item, escape){ - return '
      ' + item.label + '
      '; - } - }, - onItemAdd: function(value, item){ - $('#search_trigger').show(); - }, - onItemRemove: function(value){ - if ($.isEmptyObject(wmgui.selectize.read())) $('#search_trigger').hide(); - } - }); - wmgui.selectize = control[0].selectize; - - wmgui.selectize.read = function(){ - var result = {}; - $('div.selectize-input.items').children().each(function(){ - if (this.tagName == 'DIV'){ - var facet = this.getAttribute('data-facet'); - - if (result[facet] && facet == 'elements') - result[facet] += '-' + this.getAttribute('data-term'); - else if (result[facet] && (facet == 'classes' || facet == 'aetypes')) - result[facet] += ', ' + this.getAttribute('data-term'); - else if (facet == 'formulae') - result[facet] = this.getAttribute('data-term').replaceAll('', '').replaceAll('', ''); - else - result[facet] = this.getAttribute('data-term'); - } - }); - return result; - } - - wmgui.selectize.write = function(search_obj){ - var given_search = {}; - $.extend(given_search, search_obj); - - ['formulae', 'props', 'elements', 'classes', 'lattices', 'aetypes'].forEach(function(facet){ - if (!given_search[facet]) - return; - - else if (facet == 'elements' && given_search[facet].indexOf('-') > 0){ - given_search[facet].split('-').forEach(function(part){ - wmgui.selectize.display(facet, part); - }); - } else if ((facet == 'classes' || facet == 'aetypes') && given_search[facet].indexOf(',') > 0){ - given_search[facet].split(',').forEach(function(part){ - wmgui.selectize.display(facet, part); - }); - } else if (facet == 'formulae'){ - given_search[facet] = WMCORE.to_formula(given_search[facet]); - wmgui.selectize.display(facet, given_search[facet]); - - } else wmgui.selectize.display(facet, given_search[facet]); - }); - wmgui.selectize.clearOptions(); - } - - wmgui.selectize.display = function(facet, term){ - var random_id = Math.floor((Math.random() * 1000)); - wmgui.selectize.addOption({facet: facet, label: term, id: random_id}); - wmgui.selectize.addItem(random_id); - } - - window.location.hash ? url_redraw_react() : window.location.replace('#start'); -} - -// now, fire in the holl! - -satisfy_requirements(); - -register_events(); diff --git a/mrouter.js b/mrouter.js deleted file mode 100644 index d38eeef..0000000 --- a/mrouter.js +++ /dev/null @@ -1,115 +0,0 @@ -/** - * Mobile GUI for the chemistry DB - * Version: 0.5.5ce - */ -"use strict"; - -function url_redraw_react(){ - var anchors = window.location.hash.substr(1).split('/'); - - if (!anchors.length) return; - $('#loginbox, #restorebox').hide(); - try { wmgui.active_ajax.abort() } catch(e){} - - if (window['url__' + anchors[0]]) window['url__' + anchors[0]](anchors.slice(1).join('/')); - else window.location.hash = '#start'; -} - -function url__start(arg){ - switch_viewmode(1); -} - -function url__search(arg){ - window.location.replace('#start'); -} - -function url__phase_id(arg){ - switch_viewmode(2); - var phid = parseInt(arg); - $('#input > ul').empty().append('
    • Distinct phase
      #' + phid + '
    • '); - request_data({'phid': phid}); -} - -function url__inquiry(arg){ - var inquiry = arg.split("&").map( function(n){ return n = n.split("="), this[n[0]] = n[1], this }.bind({}) )[0]; - - wmgui.facets.forEach(function(item){ - if (inquiry[item]) inquiry[item] = unescape(inquiry[item].replaceAll('\\+', ' ')); - }); - - wmgui.search = inquiry; - - switch_viewmode(2); - - $('#input > ul').empty().append( - z(WMCORE.get_interpretation(inquiry, wmgui.facet_names)) - ); - - $('#search_field-selectized').val(''); - wmgui.selectize.clear(); - wmgui.selectize.write(inquiry); - - request_analysis(inquiry); -} - -function url__modal(arg){ - if (arg == "login"){ - if (wmgui.sid){ - $('#navicon').trigger('click'); - - } else { - if ($("#restore_by_email").val()) $("#login_email").val($("#restore_by_email").val()); - else $("#login_email").val(''); - $("#login_password").val(''); - $('#restorebox').hide(); - $('#loginbox').show(); - } - - // for OAuth linking redirect only - var u_email = window.localStorage.getItem('wm_u_email') || false; - if (u_email){ - $("#login_email").val(u_email); - window.localStorage.removeItem('wm_u_email'); - } - - } else if (arg == "restore"){ - if (wmgui.sid){ - $('#navicon').trigger('click'); - - } else { - if ($("#login_email").val()) $("#restore_by_email").val($("#login_email").val()); - else $("#restore_by_email").val(''); - $('#loginbox').hide(); - $('#restorebox').show(); - } - } -} - -function url__access(arg){ - $.ajax({type: 'POST', url: wmgui.access_endpoint, data: {a: arg}}).done(function(data){ - window.location.replace('#start'); - if (data.error){ - return wmgui.notify(data.error); - } - if (!data.sid || !data.name || !data.acclogin){ - return wmgui.notify('Connection to server is lost, please try to reload'); - } - user_login(data.sid, data.name, data.acclogin, data.admin); - $('#navicon').trigger('click'); - $('#loginbox, #restorebox').hide(); - - }).fail(function(xhr, textStatus, errorThrown){ - return wmgui.notify('A network error occured. Please, try again'); - }); -} - -function url__entry(arg){ - switch_viewmode(2); - $('#input > ul').empty().append('
    • Entry
      ' + arg + '
    • '); - request_data({'entry': arg}); -} - -function url__junction(arg){ - wmgui.notify('Please retry to log in'); - window.location.replace('#start'); -} diff --git a/optimade_zero/entry.ts b/optimade_zero/entry.ts new file mode 100644 index 0000000..1ed9f65 --- /dev/null +++ b/optimade_zero/entry.ts @@ -0,0 +1,115 @@ +namespace $ { + + // Определяем маппинг полей записи + enum EntryField { + ID = 0, + FORMULA = 1, + PROPERTY = 2, + DATA_TYPE_INDEX = 3, + IS_PUBLIC = 4, + BIB_ID = 5, + YEAR = 6, + REF_ID = 7, + } + + export class $optimade_zero_entry extends $mol_store { + + cdn_uri() { + return 'https://mpds.io'; + } + + api_uri() { + return 'https://api.mpds.io/v0'; + } + + // Геттеры с использованием enum + id(): string { + return this.value( EntryField.ID ); + } + + id_prefix(): string { + return this.id().split( '-' )[ 0 ]; + } + + type(): string { + return this.id()[ 0 ]; + } + + formula_html(): string { + return this.value( EntryField.FORMULA ); + } + + property(): string { + return this.value( EntryField.PROPERTY ); + } + + data_type(): string { + const dt = this.value( EntryField.DATA_TYPE_INDEX ); + if( dt === 7 ) return 'ml_data'; + if( [ 8, 9, 10, 11 ].includes( dt ) ) return 'ab_data'; + return ''; + } + + is_public(): boolean { + return this.value( EntryField.IS_PUBLIC ); + } + + bib_id(): string { + return this.ref_id() === 999999 ? '0' : this.value( EntryField.BIB_ID ); + } + + year(): number { + return this.value( EntryField.YEAR ); + } + + ref_id(): number { + return this.value( EntryField.REF_ID ); + } + + // Универсальная функция для формирования ссылок на скачивание + private downloadLink( format: 'bib' | 'pdf' | 'png' | 'gif' ): string { + const t = this.type(); + const api = this.api_uri(); + const prefix = this.id_prefix(); + const refId = this.ref_id(); + switch( format ) { + case 'bib': + return t === 'P' ? `${ api }/download/bib?ref_id=${ refId }&sid=&fmt=bib` : ''; + case 'pdf': + return t === 'P' ? `${ api }/download/${ t.toLowerCase() }?q=${ prefix }&sid=&fmt=pdf` : ''; + case 'png': + return t !== 'P' ? `${ api }/download/${ t.toLowerCase() }?q=${ prefix }&sid=&fmt=png` : ''; + case 'gif': + return t === 'S' ? `${ api }/download/${ t.toLowerCase() }?q=${ prefix }&fmt=gif` : ''; + default: + return ''; + } + } + + // Методы, использующие универсальную функцию + ref_link(): string { + return this.downloadLink( 'bib' ); + } + + pdf_link(): string { + return this.downloadLink( 'pdf' ); + } + + png_link(): string { + return this.downloadLink( 'png' ); + } + + gif_link(): string { + return this.downloadLink( 'gif' ); + } + + // Отдельная функция для формирования ссылки миниатюры + thumbs_link(): string { + const t = this.type(); + if( t === 'P' ) return ''; + const cdn = this.cdn_uri(); + const folder = t === 'C' ? 'pd_thumbs' : 'rd_thumbs'; + return `${ cdn }/${ folder }/${ this.id_prefix() }/.png`; + } + } +} diff --git a/optimade_zero/index.html b/optimade_zero/index.html new file mode 100644 index 0000000..9fbf633 --- /dev/null +++ b/optimade_zero/index.html @@ -0,0 +1,25 @@ + + + + + + + Absolute Zero — −273.15°C + + + + + + +
      + + + + diff --git a/optimade_zero/input.view.css.ts b/optimade_zero/input.view.css.ts new file mode 100644 index 0000000..9d39dc3 --- /dev/null +++ b/optimade_zero/input.view.css.ts @@ -0,0 +1,56 @@ +namespace $.$$ { + + $mol_style_define( $optimade_zero_search_input, { + + width: '100%', + + Anchor: { + flex: { + direction: 'column', + }, + }, + + Suggest_formula: { + Paragraph: { + padding: 0, + }, + }, + + /* Стили для поля ввода (Query) – аналог input[type="text"] */ + Query: { + height: '6vh', + padding: '1vh', + fontSize: '5vmin', + border: '1px solid #555', + borderRadius: '2px', + boxShadow: 'inset 0 5px 5px rgba(0,0,0,0.15)', + outline: 'none', + }, + + /* Кнопка очистки ввода */ + Clear: { + fontSize: '5vmin', + color: '#3e3f95', + cursor: 'pointer', + padding: '1vh', + }, + + /* Контейнер для тегов выбранных параметров */ + Tags: { + padding: '1vh', + marginTop: '1vh', + }, + + /* Стили для отдельного тега (будет применяться через компонент Tag) */ + Tag: { + display: 'inline-block', + background: '#3e3f95', + color: '#fff', + padding: '0.5vh 1vh', + marginRight: '0.5vh', + borderRadius: '2px', + fontSize: '4vmin', + }, + + } ) +} diff --git a/optimade_zero/input.view.tree b/optimade_zero/input.view.tree new file mode 100644 index 0000000..302ddab --- /dev/null +++ b/optimade_zero/input.view.tree @@ -0,0 +1,14 @@ +$optimade_zero_search_input $mol_search + Search $optimade_zero_search + Suggest_formula* $mol_html_view + html <= suggest_html_label* <= suggest_label* + anchor_content / + <= Input $mol_view + sub / + <= Query + <= Clear + <= Tags $mol_view + sub <= tags / + <= Tag*0 $optimade_zero_search_tag + close? <=> tag_drop*? null + label <= tag_label* \ diff --git a/optimade_zero/input.view.ts b/optimade_zero/input.view.ts new file mode 100644 index 0000000..3452e2d --- /dev/null +++ b/optimade_zero/input.view.ts @@ -0,0 +1,57 @@ +namespace $.$$ { + + type Search_params_label = ReturnType<$optimade_zero_search['params_labels']>[number] + + export class $optimade_zero_search_input extends $.$optimade_zero_search_input { + + @$mol_mem_key + suggests_request( key: string ) { + console.log('suggests_request', `"${key}"`) + return this.Search().suggests( key ) + } + + suggests() { + console.log('suggests', `"${this.query()}"`) + if( !this.query().trim() ) return [] + + this.$.$mol_wait_timeout( 1000 ) + + const list = this.suggests_request( this.query() ).map( obj => obj.label ) + return list + } + + suggest_select( query: string, event?: MouseEvent ) { + console.log('suggest_select', `"${query}"`) + const suggest = this.suggests_request(this.query()).find(obj => obj.label === query) + if (!suggest) throw new Error('OPS') + + this.Search().param_add(suggest.facet, suggest.label) + this.query('') + this.Query().focused( true ) + } + + @ $mol_mem + tags() { + return this.Search().params_labels().map(obj => this.Tag(obj)) + } + + tag_label(obj: Search_params_label) { + return obj.label + } + + tag_drop(obj: Search_params_label) { + this.Search().param_drop(obj.facet, obj.label) + } + + suggest_html_label( suggest_label: string ) { + return `
      ${suggest_label}
      ` + } + + suggest_content( suggest_label: string ) { + const suggest = this.suggests_request(this.query()).find(obj => obj.label === suggest_label)! + + return suggest.facet === 'formulae' ? [this.Suggest_formula(suggest_label)] : super.suggest_content(suggest_label) + } + + } +} diff --git a/optimade_zero/optimade_zero.test.ts b/optimade_zero/optimade_zero.test.ts new file mode 100644 index 0000000..358e44a --- /dev/null +++ b/optimade_zero/optimade_zero.test.ts @@ -0,0 +1,17 @@ +namespace $.$$ { + + $mol_test({ + + // 'Generating greeting message'() { + // + // const app = new $my_hello + // $mol_assert_equal( app.message() , '' ) + // + // app.name( 'Jin' ) + // $mol_assert_equal( app.message() , 'Hello, Jin!' ) + // + // } + + }) + +} diff --git a/optimade_zero/optimade_zero.view.css.ts b/optimade_zero/optimade_zero.view.css.ts new file mode 100644 index 0000000..747101f --- /dev/null +++ b/optimade_zero/optimade_zero.view.css.ts @@ -0,0 +1,62 @@ +namespace $.$$ { + + $mol_style_define( $optimade_zero, { + + /* Шапка */ + $mol_page_head: { + backgroundColor: 'transparent', + boxShadow: 'none', + }, + /* Контейнер страницы результатов */ + Search_page: { + flex: { + basis: 'auto', + grow: 1, + }, + padding: '2vh 2vw', + background: '#fff', + }, + + /* Стили для ячеек списка результатов */ + Id: { + padding: $mol_gap.text, + // width: '7rem', + // fontSize: '4vh', + }, + + Bib: { + padding: $mol_gap.text, + // width: '7rem', + // fontSize: '4vh', + }, + + Property: { + padding: $mol_gap.text, + // fontSize: '3.5vh', + }, + + /* Сообщения об ошибке или отсутствии результатов */ + Search_error: { + padding: '100px', + margin: 'auto', + color: 'red', + textAlign: 'center', + }, + + Search_nothing_found: { + padding: '100px', + margin: 'auto', + fontSize: '4vh', + color: '#555', + textAlign: 'center', + }, + + /* Дополнительное оформление строки результата */ + $mol_row: { + margin: '1vh 0', + padding: '1vh 0', + borderBottom: '1px solid #ddd', + }, + + } ) +} diff --git a/optimade_zero/optimade_zero.view.tree b/optimade_zero/optimade_zero.view.tree new file mode 100644 index 0000000..e788257 --- /dev/null +++ b/optimade_zero/optimade_zero.view.tree @@ -0,0 +1,61 @@ +$optimade_zero $mol_book2 + Search $optimade_zero_search + params? <=> search_params? * + error => search_error + pages / + <= Search_page $mol_page + title \−273.15°C + body <= search_page_body / + <= Search_input $optimade_zero_search_input + Search <= Search + <= Arity $mol_labeler + title @ \Arity + content / + <= Arity_switch $mol_switch + value? <=> arity? \ + options <= arity_dict * + <= Refinements $mol_list + rows <= refinements / + <= Refinement*0 $mol_labeler + title <= refinement_title* \ + content <= refinement_content* / + <= Refinement_link*0 $mol_link + arg <= refinement_link_arg* * + title <= refinement_link_title* \ + <= Search_error $mol_view + sub / <= search_error + <= Search_nothing_found $mol_view + sub / <= nothing_found @ \Nothing found + <= Search_results $mol_list + rows <= search_results / + <= Item*0 $mol_row + sub <= item_row* / + <= Id* $mol_paragraph + title <= item_id* \ + <= Thumbs* $mol_image + uri <= item_thumbs* \ + <= Bib* $mol_view + sub / + \[ + <= item_bib* \ + \] + <= Formula* $mol_html_view + html <= item_html* \ + <= Property* $mol_view + sub / <= item_property* \ + <= Ref* $mol_link + uri <= item_ref* \ + title \Ref. + target \_blank + <= Pdf* $mol_link + uri <= item_pdf* \ + title \PDF + target \_blank + <= Png* $mol_link + uri <= item_png* \ + title \PNG + target \_blank + <= Gif* $mol_link + uri <= item_gif* \ + title \GIF + target \_blank diff --git a/optimade_zero/optimade_zero.view.ts b/optimade_zero/optimade_zero.view.ts new file mode 100644 index 0000000..1c2fb1a --- /dev/null +++ b/optimade_zero/optimade_zero.view.ts @@ -0,0 +1,137 @@ +namespace $.$$ { + export class $optimade_zero extends $.$optimade_zero { + + @ $mol_mem + search_params( next?: $optimade_zero_search_params ): $optimade_zero_search_params { + return this.$.$mol_state_arg.dict( next ) ?? {} + } + + search_page_body() { + if( this.search_error() ) { + return [ + this.Search_input(), + this.Search_error(), + ] + } + + return [ + this.Search_input(), + ... this.Search().arity().length > 0 ? [ this.Arity() ] : [], + this.Refinements(), + ... this.Search().results().length === 0 ? [ this.Search_nothing_found() ] : [], + this.Search_results(), + ] + } + + search_results() { + if( !this.Search().params_labels().length ) return [] + + return this.Search().results().map( obj => this.Item( obj ) ) + } + + item_row( obj: $optimade_zero_entry ) { + return [ + this.Id( obj ), + // obj.thumbs_link() ? this.Thumbs(obj) : null, + obj.bib_id() ? this.Bib( obj ) : null, + this.Formula( obj ), + this.Property( obj ), + obj.ref_link() ? this.Ref( obj ) : null, + obj.pdf_link() ? this.Pdf( obj ) : null, + obj.png_link() ? this.Png( obj ) : null, + obj.gif_link() ? this.Gif( obj ) : null, + ] + } + + item_id( obj: $optimade_zero_entry ) { + return obj.id() + } + + item_thumbs( obj: $optimade_zero_entry ) { + return obj.thumbs_link() + } + + item_html( obj: $optimade_zero_entry ) { + return `
      ${ obj.formula_html() }
      ` + } + + item_property( obj: $optimade_zero_entry ) { + return obj.property() + } + + item_bib( obj: $optimade_zero_entry ) { + return `${ obj.bib_id() }'${ obj.year().toString().slice( -2 ) }` + } + + item_ref( obj: $optimade_zero_entry ) { + return obj.ref_link() + } + + item_pdf( obj: $optimade_zero_entry ) { + return obj.pdf_link() + } + + item_png( obj: $optimade_zero_entry ) { + return obj.png_link() + } + + item_gif( obj: $optimade_zero_entry ) { + return obj.gif_link() + } + + arity_dict() { + return this.Search().arity().reduce( ( dict, name ) => { + dict[ name ] = name + return dict + }, {} as Record ) + } + + @$mol_mem + refinements() { + const order: ( keyof $optimade_zero_search_params )[] = [ + 'elements', + 'formulae', + 'props', + 'classes', + 'lattices', + ] + const obj = this.Search().refinements() + + return order.map( facet => obj[ facet ]?.length ? this.Refinement( facet ) : null ).filter( Boolean ) + } + + refinement_title( facet: keyof $optimade_zero_search_params ) { + return this.Search().param_names()[ facet ] + } + + refinement_content( facet: keyof $optimade_zero_search_params ) { + return this.Search().refinements()[ facet ]!.map( obj => this.Refinement_link( obj ) ) + } + + refinement_link_title( obj: typeof $optimade_zero_search_refinement_item.Value ) { + return `${ obj.value }` + } + + @ $mol_mem_key + refinement_link_arg( obj: typeof $optimade_zero_search_refinement_item.Value ) { + console.log($) + const search = new this.$.$optimade_zero_search() + search.params( this.search_params() ) + search.param_drop(obj.facet) + search.param_add(obj.facet, obj.value) + return search.params() + } + + @$mol_mem + arity( next?: string ) { + if (next !== undefined) { + const reset = Object.values(this.Search().arity_names()) + reset.forEach(val => this.Search().param_drop('classes', val)) + + this.Search().param_add('classes', next) + } + + return next ?? '' + } + } +} diff --git a/optimade_zero/search.ts b/optimade_zero/search.ts new file mode 100644 index 0000000..d6fc40e --- /dev/null +++ b/optimade_zero/search.ts @@ -0,0 +1,254 @@ +namespace $.$$ { + + const Rec = $mol_data_record + const Str = $mol_data_string + const Maybe = $mol_data_optional + const Nully = $mol_data_nullable + const Arr = $mol_data_array + const Int = $mol_data_integer + const Bool = $mol_data_boolean + + export const $optimade_zero_search_refinement_item = Rec( { + facet: val => val as keyof $optimade_zero_search_params, + value: Str, + count: Int, + } ) + + const Refinement_response = Rec( { + error: Nully( Str ), + total_count: Int, + payload: Arr( $optimade_zero_search_refinement_item ), + } ) + + export const $optimade_zero_search_entry = Rec( { + 0: Str, // Entry + 1: Str, // Formula + 2: Str, // Property + 3: Int, + 4: Bool, // Is public data + 5: Str, // Biblio id? + 6: Int, // Year + 7: Int, // Ref id + } ) + + const Facet_response = Rec( { + error: Nully( Str ), + fuzzy_notice: Maybe( Nully( Str ) ), + notice: Maybe( Str ), + estimated_count: Maybe( Int ), + out: Maybe( Arr( $optimade_zero_search_entry ) ), + } ) + + const Suggest_response = Arr( Rec( { + facet: val => val as keyof $optimade_zero_search_params, + label: Str, + id: Str, + } ) ) + + export type $optimade_zero_search_params = { + props?: string + elements?: string + classes?: string + lattices?: string + formulae?: string + sgs?: string + protos?: string + aeatoms?: string + aetypes?: string + authors?: string + codens?: string + years?: string + geos?: string + orgs?: string + doi?: string + numeric?: string + } + + export class $optimade_zero_search extends $mol_object { + + @$mol_mem + params( next?: $optimade_zero_search_params ): $optimade_zero_search_params { + return next ?? {} + } + + param_add( facet: keyof $optimade_zero_search_params, value: string ) { + const params = this.params() + let next = params[ facet ] ?? '' + + if( next.includes( value ) ) return + + if( !next ) next = value + else next += `${ this.separator( facet ) }${ value }` + + this.params( { ...params, [ facet ]: next } ) + } + + param_drop( facet: keyof $optimade_zero_search_params, value?: string ) { + let { [ facet ]: next, ...params } = this.params() + + if( !value ) { + this.params( { ...params } ) + return + } + + const sep = this.separator( facet ) + next = next?.split( sep ).filter( val => val !== value ).join( sep ) + + this.params( { ...params, [ facet ]: next } ) + } + + separator_default() { + return ',' + } + + separator( facet: keyof $optimade_zero_search_params ) { + const obj = { + elements: '-', + } as Record + return obj[ facet ] ?? this.separator_default() + } + + @$mol_mem + params_api() { + const params = { ...this.params() } + if( params.formulae ) { + params.formulae = params.formulae.replace( /<\/?sub>/g, '' ) + } + const query = JSON.stringify( params ) + return query + } + + @$mol_mem + params_labels() { + const result = [] as { facet: keyof $optimade_zero_search_params, label: string }[] + + const keys = Object.keys( this.params() ) as Array + + for( const facet of keys ) { + const val = this.params()[ facet ] + if( !val ) continue + + const values = val.split( this.separator( facet ) ) + values.forEach( label => result.push( { facet, label } ) ) + } + + return result + } + + @$mol_mem + results_response() { + const res = $mol_fetch.json( `https://api.mpds.io/v0/search/facet?q=${ this.params_api() }` ) + return Facet_response( res as any ) + } + + @$mol_mem + results() { + // Преобразуем каждый элемент ответа в массив (если требуется) + return this.results_response().out?.map( tuple => new $optimade_zero_entry( this.mapEntry( tuple ) ) ) ?? [] + } + + @$mol_mem + error() { + return this.results_response().error ?? '' + } + + @$mol_mem_key + suggests( query: string ) { + const res = $mol_fetch.json( `https://api.mpds.io/v0/search/selectize?q=${ query }` ) + return Suggest_response( res as any ) + } + + arity_names() { + return { + 0: 'unary', + 1: 'binary', + 2: 'ternary', + 3: 'quaternary', + 4: 'quinary', + 5: 'multinary', + } as { [ key: string ]: string } + } + + param_names() { + return { + aeatoms: 'Polyhedron atoms', + aetypes: 'Polyhedral types', + authors: 'Authors', + classes: 'Materials classes', + codens: 'Journal codes', + doi: 'DOI', + elements: 'Chemical elements', + formulae: 'Chemical formulae', + geos: 'Geography', + lattices: 'Crystal systems', + numeric: 'Numerical search', + orgs: 'Organization', + props: 'Physical properties', + protos: 'Prototypes', + sgs: 'Space groups', + years: 'Years', + } + } + + @$mol_mem + refinements_response() { + const res = $mol_fetch.json( `https://api.mpds.io/v0/search/refinement?q=${ this.params_api() }` ) + const json = Refinement_response( res as any ) + + for (const item of json.payload) { + if (item.facet === 'elements') { + (item.value as any) = item.value.split(',').map(v => v.trim()).join( this.separator('elements') ) + } + } + + return json + } + + @$mol_mem + refinements() { + const refinements = {} as Record + + for( const item of this.refinements_response().payload ) { + const list = refinements[ item.facet ] = refinements[ item.facet ] ?? [] + list.push( item ) + } + + return refinements + } + + @$mol_mem + arity() { + const arity = [] as string[] + + const params = this.params() + + if( !params.formulae ) { + const current_arity = params.elements?.split( this.separator( 'elements' ) ).length ?? 0 + + for( let i = current_arity; i < 5; i++ ) { + const name = this.arity_names()[ i ] + arity.push( name ) + } + } + + return arity + } + + // Новая вспомогательная функция для маппинга входящего объекта + private mapEntry(entry: any): any { + // Если запись уже имеет числовой ключ "0", считаем, что она в нужном формате + if (entry["0"] !== undefined) return entry; + // Иначе, преобразуем объект с именованными полями в массив + return [ + entry.id, + entry.formula, + entry.property, + entry.data_type_index, + entry.is_public, + entry.bib_id, + entry.year, + entry.ref_id + ]; + } + } +} diff --git a/optimade_zero/tag.view.css.ts b/optimade_zero/tag.view.css.ts new file mode 100644 index 0000000..8ad41dd --- /dev/null +++ b/optimade_zero/tag.view.css.ts @@ -0,0 +1,31 @@ +namespace $.$$ { + + $mol_style_define( $optimade_zero_search_tag, { + + /* Контейнер метки тега */ + Label: { + padding: '0.5vh 1vh', + fontSize: '4vmin', + lineHeight: '6vh', + background: '#3e3f95', + color: '#fff', + borderRadius: '2px', + display: 'inline-block', + marginRight: '0.5vh', + }, + + /* Кнопка закрытия тега */ + Close: { + padding: '0.5vh 1vh', + fontSize: '4vmin', + cursor: 'pointer', + }, + + /* Иконка закрытия */ + Close_icon: { + width: '2vh', + height: '2vh', + }, + + } ) +} diff --git a/optimade_zero/tag.view.tree b/optimade_zero/tag.view.tree new file mode 100644 index 0000000..5252b0a --- /dev/null +++ b/optimade_zero/tag.view.tree @@ -0,0 +1,7 @@ +$optimade_zero_search_tag $mol_view + sub / + <= Label $mol_html_view + html <= html_label <= label \ + <= Close $mol_button_minor + click? <=> close? null + sub / <= Close_icon $mol_icon_close diff --git a/optimade_zero/tag.view.ts b/optimade_zero/tag.view.ts new file mode 100644 index 0000000..864669b --- /dev/null +++ b/optimade_zero/tag.view.ts @@ -0,0 +1,9 @@ +namespace $.$$ { + export class $optimade_zero_search_tag extends $.$optimade_zero_search_tag { + + html_label() { + return `
      ${this.label()}
      ` + } + + } +} diff --git a/selectize.js b/selectize.js deleted file mode 100644 index 39ebad5..0000000 --- a/selectize.js +++ /dev/null @@ -1,3684 +0,0 @@ -/** - * sifter.js - * Copyright (c) 2013 Brian Reavis & contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this - * file except in compliance with the License. You may obtain a copy of the License at: - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under - * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF - * ANY KIND, either express or implied. See the License for the specific language - * governing permissions and limitations under the License. - * - * @author Brian Reavis - */ - -(function(root, factory) { - if (typeof define === 'function' && define.amd) { - define('sifter', factory); - } else if (typeof exports === 'object') { - module.exports = factory(); - } else { - root.Sifter = factory(); - } -}(this, function() { - - /** - * Textually searches arrays and hashes of objects - * by property (or multiple properties). Designed - * specifically for autocomplete. - * - * @constructor - * @param {array|object} items - * @param {object} items - */ - var Sifter = function(items, settings) { - this.items = items; - this.settings = settings || {diacritics: true}; - }; - - /** - * Splits a search string into an array of individual - * regexps to be used to match results. - * - * @param {string} query - * @returns {array} - */ - Sifter.prototype.tokenize = function(query) { - query = trim(String(query || '').toLowerCase()); - if (!query || !query.length) return []; - - var i, n, regex, letter; - var tokens = []; - var words = query.split(/ +/); - - for (i = 0, n = words.length; i < n; i++) { - regex = escape_regex(words[i]); - if (this.settings.diacritics) { - for (letter in DIACRITICS) { - if (DIACRITICS.hasOwnProperty(letter)) { - regex = regex.replace(new RegExp(letter, 'g'), DIACRITICS[letter]); - } - } - } - tokens.push({ - string : words[i], - regex : new RegExp(regex, 'i') - }); - } - - return tokens; - }; - - /** - * Iterates over arrays and hashes. - * - * ``` - * this.iterator(this.items, function(item, id) { - * // invoked for each item - * }); - * ``` - * - * @param {array|object} object - */ - Sifter.prototype.iterator = function(object, callback) { - var iterator; - if (is_array(object)) { - iterator = Array.prototype.forEach || function(callback) { - for (var i = 0, n = this.length; i < n; i++) { - callback(this[i], i, this); - } - }; - } else { - iterator = function(callback) { - for (var key in this) { - if (this.hasOwnProperty(key)) { - callback(this[key], key, this); - } - } - }; - } - - iterator.apply(object, [callback]); - }; - - /** - * Returns a function to be used to score individual results. - * - * Good matches will have a higher score than poor matches. - * If an item is not a match, 0 will be returned by the function. - * - * @param {object|string} search - * @param {object} options (optional) - * @returns {function} - */ - Sifter.prototype.getScoreFunction = function(search, options) { - var self, fields, tokens, token_count, nesting; - - self = this; - search = self.prepareSearch(search, options); - tokens = search.tokens; - fields = search.options.fields; - token_count = tokens.length; - nesting = search.options.nesting; - - /** - * Calculates how close of a match the - * given value is against a search token. - * - * @param {mixed} value - * @param {object} token - * @return {number} - */ - var scoreValue = function(value, token) { - var score, pos; - - if (!value) return 0; - value = String(value || ''); - pos = value.search(token.regex); - if (pos === -1) return 0; - score = token.string.length / value.length; - if (pos === 0) score += 0.5; - return score; - }; - - /** - * Calculates the score of an object - * against the search query. - * - * @param {object} token - * @param {object} data - * @return {number} - */ - var scoreObject = (function() { - var field_count = fields.length; - if (!field_count) { - return function() { return 0; }; - } - if (field_count === 1) { - return function(token, data) { - return scoreValue(getattr(data, fields[0], nesting), token); - }; - } - return function(token, data) { - for (var i = 0, sum = 0; i < field_count; i++) { - sum += scoreValue(getattr(data, fields[i], nesting), token); - } - return sum / field_count; - }; - })(); - - if (!token_count) { - return function() { return 0; }; - } - if (token_count === 1) { - return function(data) { - return scoreObject(tokens[0], data); - }; - } - - if (search.options.conjunction === 'and') { - return function(data) { - var score; - for (var i = 0, sum = 0; i < token_count; i++) { - score = scoreObject(tokens[i], data); - if (score <= 0) return 0; - sum += score; - } - return sum / token_count; - }; - } else { - return function(data) { - for (var i = 0, sum = 0; i < token_count; i++) { - sum += scoreObject(tokens[i], data); - } - return sum / token_count; - }; - } - }; - - /** - * Returns a function that can be used to compare two - * results, for sorting purposes. If no sorting should - * be performed, `null` will be returned. - * - * @param {string|object} search - * @param {object} options - * @return function(a,b) - */ - Sifter.prototype.getSortFunction = function(search, options) { - var i, n, self, field, fields, fields_count, multiplier, multipliers, get_field, implicit_score, sort; - - self = this; - search = self.prepareSearch(search, options); - sort = (!search.query && options.sort_empty) || options.sort; - - /** - * Fetches the specified sort field value - * from a search result item. - * - * @param {string} name - * @param {object} result - * @return {mixed} - */ - get_field = function(name, result) { - if (name === '$score') return result.score; - return getattr(self.items[result.id], name, options.nesting); - }; - - // parse options - fields = []; - if (sort) { - for (i = 0, n = sort.length; i < n; i++) { - if (search.query || sort[i].field !== '$score') { - fields.push(sort[i]); - } - } - } - - // the "$score" field is implied to be the primary - // sort field, unless it's manually specified - if (search.query) { - implicit_score = true; - for (i = 0, n = fields.length; i < n; i++) { - if (fields[i].field === '$score') { - implicit_score = false; - break; - } - } - if (implicit_score) { - fields.unshift({field: '$score', direction: 'desc'}); - } - } else { - for (i = 0, n = fields.length; i < n; i++) { - if (fields[i].field === '$score') { - fields.splice(i, 1); - break; - } - } - } - - multipliers = []; - for (i = 0, n = fields.length; i < n; i++) { - multipliers.push(fields[i].direction === 'desc' ? -1 : 1); - } - - // build function - fields_count = fields.length; - if (!fields_count) { - return null; - } else if (fields_count === 1) { - field = fields[0].field; - multiplier = multipliers[0]; - return function(a, b) { - return multiplier * cmp( - get_field(field, a), - get_field(field, b) - ); - }; - } else { - return function(a, b) { - var i, result, a_value, b_value, field; - for (i = 0; i < fields_count; i++) { - field = fields[i].field; - result = multipliers[i] * cmp( - get_field(field, a), - get_field(field, b) - ); - if (result) return result; - } - return 0; - }; - } - }; - - /** - * Parses a search query and returns an object - * with tokens and fields ready to be populated - * with results. - * - * @param {string} query - * @param {object} options - * @returns {object} - */ - Sifter.prototype.prepareSearch = function(query, options) { - if (typeof query === 'object') return query; - - options = extend({}, options); - - var option_fields = options.fields; - var option_sort = options.sort; - var option_sort_empty = options.sort_empty; - - if (option_fields && !is_array(option_fields)) options.fields = [option_fields]; - if (option_sort && !is_array(option_sort)) options.sort = [option_sort]; - if (option_sort_empty && !is_array(option_sort_empty)) options.sort_empty = [option_sort_empty]; - - return { - options : options, - query : String(query || '').toLowerCase(), - tokens : this.tokenize(query), - total : 0, - items : [] - }; - }; - - /** - * Searches through all items and returns a sorted array of matches. - * - * The `options` parameter can contain: - * - * - fields {string|array} - * - sort {array} - * - score {function} - * - filter {bool} - * - limit {integer} - * - * Returns an object containing: - * - * - options {object} - * - query {string} - * - tokens {array} - * - total {int} - * - items {array} - * - * @param {string} query - * @param {object} options - * @returns {object} - */ - Sifter.prototype.search = function(query, options) { - var self = this, value, score, search, calculateScore; - var fn_sort; - var fn_score; - - search = this.prepareSearch(query, options); - options = search.options; - query = search.query; - - // generate result scoring function - fn_score = options.score || self.getScoreFunction(search); - - // perform search and sort - if (query.length) { - self.iterator(self.items, function(item, id) { - score = fn_score(item); - if (options.filter === false || score > 0) { - search.items.push({'score': score, 'id': id}); - } - }); - } else { - self.iterator(self.items, function(item, id) { - search.items.push({'score': 1, 'id': id}); - }); - } - - fn_sort = self.getSortFunction(search, options); - if (fn_sort) search.items.sort(fn_sort); - - // apply limits - search.total = search.items.length; - if (typeof options.limit === 'number') { - search.items = search.items.slice(0, options.limit); - } - - return search; - }; - - // utilities - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - var cmp = function(a, b) { - if (typeof a === 'number' && typeof b === 'number') { - return a > b ? 1 : (a < b ? -1 : 0); - } - a = asciifold(String(a || '')); - b = asciifold(String(b || '')); - if (a > b) return 1; - if (b > a) return -1; - return 0; - }; - - var extend = function(a, b) { - var i, n, k, object; - for (i = 1, n = arguments.length; i < n; i++) { - object = arguments[i]; - if (!object) continue; - for (k in object) { - if (object.hasOwnProperty(k)) { - a[k] = object[k]; - } - } - } - return a; - }; - - /** - * A property getter resolving dot-notation - * @param {Object} obj The root object to fetch property on - * @param {String} name The optionally dotted property name to fetch - * @param {Boolean} nesting Handle nesting or not - * @return {Object} The resolved property value - */ - var getattr = function(obj, name, nesting) { - if (!obj || !name) return; - if (!nesting) return obj[name]; - var names = name.split("."); - while(names.length && (obj = obj[names.shift()])); - return obj; - }; - - var trim = function(str) { - return (str + '').replace(/^\s+|\s+$|/g, ''); - }; - - var escape_regex = function(str) { - return (str + '').replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1'); - }; - - var is_array = Array.isArray || (typeof $ !== 'undefined' && $.isArray) || function(object) { - return Object.prototype.toString.call(object) === '[object Array]'; - }; - - var DIACRITICS = { - 'a': '[aḀḁĂăÂâǍǎȺⱥȦȧẠạÄäÀàÁáĀāÃãÅåąĄÃąĄ]', - 'b': '[b␢βΒB฿𐌁ᛒ]', - 'c': '[cĆćĈĉČčĊċC̄c̄ÇçḈḉȻȼƇƈɕᴄCc]', - 'd': '[dĎďḊḋḐḑḌḍḒḓḎḏĐđD̦d̦ƉɖƊɗƋƌᵭᶁᶑȡᴅDdð]', - 'e': '[eÉéÈèÊêḘḙĚěĔĕẼẽḚḛẺẻĖėËëĒēȨȩĘęᶒɆɇȄȅẾếỀềỄễỂểḜḝḖḗḔḕȆȇẸẹỆệⱸᴇEeɘǝƏƐε]', - 'f': '[fƑƒḞḟ]', - 'g': '[gɢ₲ǤǥĜĝĞğĢģƓɠĠġ]', - 'h': '[hĤĥĦħḨḩẖẖḤḥḢḣɦʰǶƕ]', - 'i': '[iÍíÌìĬĭÎîǏǐÏïḮḯĨĩĮįĪīỈỉȈȉȊȋỊịḬḭƗɨɨ̆ᵻᶖİiIıɪIi]', - 'j': '[jȷĴĵɈɉʝɟʲ]', - 'k': '[kƘƙꝀꝁḰḱǨǩḲḳḴḵκϰ₭]', - 'l': '[lŁłĽľĻļĹĺḶḷḸḹḼḽḺḻĿŀȽƚⱠⱡⱢɫɬᶅɭȴʟLl]', - 'n': '[nŃńǸǹŇňÑñṄṅŅņṆṇṊṋṈṉN̈n̈ƝɲȠƞᵰᶇɳȵɴNnŊŋ]', - 'o': '[oØøÖöÓóÒòÔôǑǒŐőŎŏȮȯỌọƟɵƠơỎỏŌōÕõǪǫȌȍՕօ]', - 'p': '[pṔṕṖṗⱣᵽƤƥᵱ]', - 'q': '[qꝖꝗʠɊɋꝘꝙq̃]', - 'r': '[rŔŕɌɍŘřŖŗṘṙȐȑȒȓṚṛⱤɽ]', - 's': '[sŚśṠṡṢṣꞨꞩŜŝŠšŞşȘșS̈s̈]', - 't': '[tŤťṪṫŢţṬṭƮʈȚțṰṱṮṯƬƭ]', - 'u': '[uŬŭɄʉỤụÜüÚúÙùÛûǓǔŰűŬŭƯưỦủŪūŨũŲųȔȕ∪]', - 'v': '[vṼṽṾṿƲʋꝞꝟⱱʋ]', - 'w': '[wẂẃẀẁŴŵẄẅẆẇẈẉ]', - 'x': '[xẌẍẊẋχ]', - 'y': '[yÝýỲỳŶŷŸÿỸỹẎẏỴỵɎɏƳƴ]', - 'z': '[zŹźẐẑŽžŻżẒẓẔẕƵƶ]' - }; - - var asciifold = (function() { - var i, n, k, chunk; - var foreignletters = ''; - var lookup = {}; - for (k in DIACRITICS) { - if (DIACRITICS.hasOwnProperty(k)) { - chunk = DIACRITICS[k].substring(2, DIACRITICS[k].length - 1); - foreignletters += chunk; - for (i = 0, n = chunk.length; i < n; i++) { - lookup[chunk.charAt(i)] = k; - } - } - } - var regexp = new RegExp('[' + foreignletters + ']', 'g'); - return function(str) { - return str.replace(regexp, function(foreignletter) { - return lookup[foreignletter]; - }).toLowerCase(); - }; - })(); - - - // export - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - return Sifter; -})); - - - -/** - * microplugin.js - * Copyright (c) 2013 Brian Reavis & contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this - * file except in compliance with the License. You may obtain a copy of the License at: - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under - * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF - * ANY KIND, either express or implied. See the License for the specific language - * governing permissions and limitations under the License. - * - * @author Brian Reavis - */ - -(function(root, factory) { - if (typeof define === 'function' && define.amd) { - define('microplugin', factory); - } else if (typeof exports === 'object') { - module.exports = factory(); - } else { - root.MicroPlugin = factory(); - } -}(this, function() { - var MicroPlugin = {}; - - MicroPlugin.mixin = function(Interface) { - Interface.plugins = {}; - - /** - * Initializes the listed plugins (with options). - * Acceptable formats: - * - * List (without options): - * ['a', 'b', 'c'] - * - * List (with options): - * [{'name': 'a', options: {}}, {'name': 'b', options: {}}] - * - * Hash (with options): - * {'a': { ... }, 'b': { ... }, 'c': { ... }} - * - * @param {mixed} plugins - */ - Interface.prototype.initializePlugins = function(plugins) { - var i, n, key; - var self = this; - var queue = []; - - self.plugins = { - names : [], - settings : {}, - requested : {}, - loaded : {} - }; - - if (utils.isArray(plugins)) { - for (i = 0, n = plugins.length; i < n; i++) { - if (typeof plugins[i] === 'string') { - queue.push(plugins[i]); - } else { - self.plugins.settings[plugins[i].name] = plugins[i].options; - queue.push(plugins[i].name); - } - } - } else if (plugins) { - for (key in plugins) { - if (plugins.hasOwnProperty(key)) { - self.plugins.settings[key] = plugins[key]; - queue.push(key); - } - } - } - - while (queue.length) { - self.require(queue.shift()); - } - }; - - Interface.prototype.loadPlugin = function(name) { - var self = this; - var plugins = self.plugins; - var plugin = Interface.plugins[name]; - - if (!Interface.plugins.hasOwnProperty(name)) { - throw new Error('Unable to find "' + name + '" plugin'); - } - - plugins.requested[name] = true; - plugins.loaded[name] = plugin.fn.apply(self, [self.plugins.settings[name] || {}]); - plugins.names.push(name); - }; - - /** - * Initializes a plugin. - * - * @param {string} name - */ - Interface.prototype.require = function(name) { - var self = this; - var plugins = self.plugins; - - if (!self.plugins.loaded.hasOwnProperty(name)) { - if (plugins.requested[name]) { - throw new Error('Plugin has circular dependency ("' + name + '")'); - } - self.loadPlugin(name); - } - - return plugins.loaded[name]; - }; - - /** - * Registers a plugin. - * - * @param {string} name - * @param {function} fn - */ - Interface.define = function(name, fn) { - Interface.plugins[name] = { - 'name' : name, - 'fn' : fn - }; - }; - }; - - var utils = { - isArray: Array.isArray || function(vArg) { - return Object.prototype.toString.call(vArg) === '[object Array]'; - } - }; - - return MicroPlugin; -})); - -/** - * selectize.js (v0.12.6) - * Copyright (c) 2013–2015 Brian Reavis & contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this - * file except in compliance with the License. You may obtain a copy of the License at: - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under - * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF - * ANY KIND, either express or implied. See the License for the specific language - * governing permissions and limitations under the License. - * - * @author Brian Reavis - */ - -/*jshint curly:false */ -/*jshint browser:true */ - -(function(root, factory) { - if (typeof define === 'function' && define.amd) { - define('selectize', ['jquery','sifter','microplugin'], factory); - } else if (typeof exports === 'object') { - module.exports = factory(require('jquery'), require('sifter'), require('microplugin')); - } else { - root.Selectize = factory(root.jQuery, root.Sifter, root.MicroPlugin); - } -}(this, function($, Sifter, MicroPlugin) { - 'use strict'; - - var highlight = function($element, pattern) { - if (typeof pattern === 'string' && !pattern.length) return; - var regex = (typeof pattern === 'string') ? new RegExp(pattern, 'i') : pattern; - - var highlight = function(node) { - var skip = 0; - // Wrap matching part of text node with highlighting , e.g. - // Soccer -> Soccer for regex = /soc/i - if (node.nodeType === 3) { - var pos = node.data.search(regex); - if (pos >= 0 && node.data.length > 0) { - var match = node.data.match(regex); - var spannode = document.createElement('span'); - spannode.className = 'highlight'; - var middlebit = node.splitText(pos); - var endbit = middlebit.splitText(match[0].length); - var middleclone = middlebit.cloneNode(true); - spannode.appendChild(middleclone); - middlebit.parentNode.replaceChild(spannode, middlebit); - skip = 1; - } - } - // Recurse element node, looking for child text nodes to highlight, unless element - // is childless,