| <!-- |
| The common.js file must be included before this file. |
| |
| This in an HTML Import-able file that contains the definition |
| of the following elements: |
| |
| <query-sk> |
| |
| To use this file import it: |
| |
| <link href="/res/imp/query.html" rel="import" /> |
| |
| Usage: |
| |
| <query-sk></query-sk> |
| |
| Properties: |
| currentQuery: The current URL query formatted selections. |
| whiteList: A list of keys for params that should always be shown. |
| hideCount: If false, then query back to the server for the count |
| of matching traces. |
| noClear: Don't display the clear selections button. |
| fast: Display a edit box for fast trimming of options. |
| |
| Methods: |
| setParamSet(set): Set the params to be displayed. |
| clearSelections(): Clear all selections. |
| setSelections(sel): Set the current selections. Must be called after |
| setParamSet. |
| |
| Events: |
| 'change' |
| The 'sk-query' element will produce 'change' events when the query |
| parameters chosen have changed. The event contains the current |
| selections formatted as a URL query, found in e.detail. |
| --> |
| <polymer-element name="query-sk" attributes="whiteList currentQuery hideCount noClear"> |
| <template> |
| <style type="text/css" media="screen"> |
| #more.display { |
| display: none; |
| } |
| toggle-display-sk { |
| display: none; |
| } |
| toggle-display-sk.display { |
| display: block; |
| } |
| select { |
| overflow: auto; |
| margin: 0.3em; |
| } |
| |
| .node { |
| margin: 0 0.5em; |
| } |
| .more { |
| width: 100% |
| } |
| .option { |
| padding: 0.2em; |
| } |
| .option.core-selected { |
| background: #ddd; |
| } |
| |
| .choices { |
| height: 15em; |
| overflow-y: auto; |
| border: solid lightgray 1px; |
| } |
| .hide { |
| display: none; |
| } |
| |
| </style> |
| <div> |
| <paper-button raised id="clear">Clear selections</paper-button> |
| <span id="count"></span> |
| </div> |
| <template if="{{fast}}"> |
| <div> |
| <paper-input id=fast label="Filter"></paper-input> |
| </div> |
| </template> |
| <div id="inputs" horizontal layout wrap> |
| <template repeat="{{sel in primary}}"> |
| <div class="node"> |
| <h4>{{sel.name}}</h4> |
| <div class="choices"> |
| <core-selector valueattr="label" data-name="{{sel.name}}" multi> |
| <template repeat="{{o in sel.values}}"> |
| <div class="option" label="{{o}}">{{o}}</div> |
| </template> |
| </core-selector> |
| </div> |
| </div> |
| </template> |
| </div> |
| <toggle-display-sk>More...</toggle-display-sk> |
| <div id="more" horizontal layout wrap class="display"> |
| <template repeat="{{sel in secondary}}"> |
| <div class="node"> |
| <h4>{{sel.name}}</h4> |
| <div class="choices"> |
| <core-selector valueattr="label" data-name="{{sel.name}}" multi> |
| <template repeat="{{o in sel.values}}"> |
| <div class="option" label="{{o}}">{{o}}</div> |
| </template> |
| </core-selector> |
| </div> |
| </div> |
| </template> |
| </div> |
| </template> |
| <script> |
| (function(){ |
| Polymer({ |
| publish: { |
| hideCount: { |
| value: false, |
| reflect: true |
| }, |
| noClear: { |
| value: false, |
| reflect: true |
| }, |
| fast: { |
| value: false, |
| reflect: true, |
| }, |
| }, |
| |
| created: function() { |
| // Both primary and secondary are arrays of objects that look like: |
| // |
| // { |
| // name: "config", |
| // values: ["565", "8888", "gpu"] |
| // } |
| // |
| // Where primary contains selections that are in the whiteList, and |
| // secondary contains all the other selections. |
| this.whiteList = ['name', 'bench_type', 'os', 'source_type', 'scale', 'extra_config', 'config', 'arch', 'sub_result']; |
| |
| this.primary = []; |
| this.secondary = []; |
| }, |
| |
| ready: function() { |
| var that = this; |
| this.currentQuery = ''; |
| |
| this.$.inputs.addEventListener('core-select', this.fireChange.bind(this)); |
| this.$.more.addEventListener('core-select', this.fireChange.bind(this)); |
| |
| this.$.clear.addEventListener('click', this.clearSelections.bind(this)); |
| |
| if (this.noClear) { |
| this.$.clear.style.display = 'none'; |
| } |
| if (this.$.fast) { |
| this.$.fast.addEventListener('input', function(e) { |
| $$$('toggle-display-sk', that.shadowRoot).open(); |
| that.fastFilter(); |
| }); |
| } |
| }, |
| |
| fastFilter: function() { |
| var filters = this.$.fast.value.trim().toLowerCase().split(/\s+/); |
| |
| // Create a closure that returns true if the given label |
| // matches the filter. |
| var matches = function(s) { |
| s = s.toLowerCase(); |
| for (var i=0; i<filters.length; i++) { |
| if (s.indexOf(filters[i]) >= 0) { |
| return true; |
| } |
| } |
| return false; |
| }; |
| |
| $$('div[label]', this.$.inputs).forEach(function(ele) { |
| ele.classList.toggle('hide', !matches(ele.getAttribute('label'))); |
| }); |
| $$('div[label]', this.$.more).forEach(function(ele) { |
| ele.classList.toggle('hide', !matches(ele.getAttribute('label'))); |
| }); |
| }, |
| |
| clearSelections: function() { |
| $$('core-selector', this.$.inputs).forEach(function(elem) { |
| elem.selected = []; |
| }); |
| $$('core-selector', this.$.more).forEach(function(elem) { |
| elem.selected = []; |
| }); |
| this.$.count.textContent = ''; |
| }, |
| |
| fireChange: function() { |
| var q = this.selectionsAsQuery(); |
| // Only fire if we see a real change in the state. |
| // See https://github.com/Polymer/core-selector/issues/6 |
| if (q != this.currentQuery) { |
| this.currentQuery = q; |
| this.dispatchEvent(new CustomEvent('change', {detail: q})); |
| |
| var countEle = this.$.count; |
| if (!this.hideCount) { |
| sk.get('/query/0/-1/?' + q).then(JSON.parse).then(function(json) { |
| countEle.innerHTML = json["matches"] + ' lines selected<br />'; |
| }); |
| } |
| } |
| }, |
| |
| |
| // selectionsAsQuery bundles up the current set of selections as a URL query |
| // suitable for passing to the /query/ endpoint. |
| // |
| selectionsAsQuery: function() { |
| var sel = []; |
| $$('core-selector', this.$.inputs).forEach(function(select) { |
| var key = select.dataset.name; |
| if (select.selected) { |
| select.selected.forEach(function(value) { |
| console.log(key, value); |
| sel.push(encodeURIComponent(key) + '=' + encodeURIComponent(value)); |
| }); |
| } |
| }); |
| $$('core-selector', this.$.more).forEach(function(select) { |
| var key = select.dataset.name; |
| if (select.selected) { |
| select.selected.forEach(function(value) { |
| console.log(key, value); |
| sel.push(encodeURIComponent(key) + '=' + encodeURIComponent(value)); |
| }); |
| } |
| }); |
| return sel.join('&'); |
| }, |
| |
| // Selects all the values in paramset. |
| // |
| // The argument is a URL query encoded paramset. |
| setSelections: function(paramset) { |
| paramset = sk.query.toParamSet(paramset); |
| this.clearSelections(); |
| $$('core-selector', this.$.inputs).forEach(function(sel) { |
| sel.selected = paramset[sel.dataset.name] || null; |
| }); |
| $$('core-selector', this.$.more).forEach(function(sel) { |
| sel.selected = paramset[sel.dataset.name] || null; |
| }); |
| }, |
| |
| // When paramset is changed we rebuild primary and secondary. |
| // |
| // The paramset is an object that maps selection names |
| // to a list of selection values, not necessarily in alphabetical |
| // order. |
| setParamSet: function(paramset) { |
| var keylist = Object.keys(paramset).sort(); |
| |
| this.primary = []; |
| this.secondary = []; |
| for (var i = 0; i < keylist.length; i++) { |
| var key = keylist[i]; |
| var sel = { |
| name: key, |
| values: paramset[key].sort() |
| } |
| if (this.whiteList.length == 0 || this.whiteList.indexOf(key) != -1) { |
| this.primary.push(sel); |
| } else { |
| this.secondary.push(sel); |
| } |
| } |
| if (this.secondary.length == 0) { |
| $$$('toggle-display-sk', this.shadowRoot).classList.remove('display'); |
| } else { |
| $$$('toggle-display-sk', this.shadowRoot).classList.add('display'); |
| } |
| } |
| }); |
| })(); |
| </script> |
| </polymer-element> |