$.extend(true, edges, { bs3 : { newFacetFilterSetterRenderer: function (params) { if (!params) { params = {} } edges.bs3.FacetFilterSetterRenderer.prototype = edges.newRenderer(params); return new edges.bs3.FacetFilterSetterRenderer(params); }, FacetFilterSetterRenderer: function (params) { // whether the facet should be open or closed // can be initialised and is then used to track internal state this.open = edges.getParam(params.open, false); // whether the facet can be opened and closed this.togglable = edges.getParam(params.togglable, true); // whether the count should be displayed along with the term // defaults to false because count may be confusing to the user in an OR selector this.showCount = edges.getParam(params.showCount, true); // The display title for the facet this.facetTitle = edges.getParam(params.facetTitle, "Untitled"); this.intro = edges.getParam(params.intro, false); this.openIcon = edges.getParam(params.openIcon, "glyphicon glyphicon-plus"); this.closeIcon = edges.getParam(params.closeIcon, "glyphicon glyphicon-minus"); this.layout = edges.getParam(params.layout, "left"); // namespace to use in the page this.namespace = "edges-bs3-facet-filter-setter"; this.draw = function () { // for convenient short references ... var comp = this.component; var namespace = this.namespace; // sort out all the classes that we're going to be using var filterClass = edges.css_classes(namespace, "filter", this); var valClass = edges.css_classes(namespace, "value", this); var filterRemoveClass = edges.css_classes(namespace, "filter-remove", this); var facetClass = edges.css_classes(namespace, "facet", this); var headerClass = edges.css_classes(namespace, "header", this); var bodyClass = edges.css_classes(this.namespace, "body", this); var introClass = edges.css_classes(this.namespace, "intro", this); var countClass = edges.css_classes(namespace, "count", this); var toggleId = edges.css_id(namespace, "toggle", this); var resultsId = edges.css_id(namespace, "results", this); var filters = ""; for (var i = 0; i < comp.filters.length; i++) { var filter = comp.filters[i]; var id = filter.id; var display = filter.display; var count = comp.filter_counts[id]; var active = comp.active_filters[id]; if (count === undefined) { count = 0; } filters += '<div class="' + filterClass + '">'; if (active) { filters += '<strong>' + edges.escapeHtml(display); if (this.showCount) { filters += " (" + count + ")"; } filters += ' <a href="#" class="' + filterRemoveClass + '" data-filter="' + edges.escapeHtml(id) + '">'; filters += '<i class="glyphicon glyphicon-black glyphicon-remove"></i></a>'; filters += "</strong>"; } else { filters += '<a href="#" class="' + valClass + '" data-filter="' + edges.escapeHtml(id) + '">' + edges.escapeHtml(display) + "</a>"; if (this.showCount) { filters += ' <span class="' + countClass + '">(' + count + ')</span>'; } } filters += "</div>"; } var header = this.headerLayout({toggleId: toggleId}); var introFrag = ""; if (this.intro !== false) { introFrag = '<div class="' + introClass + '">' + this.intro + '</div>'; } // render the overall facet var frag = '<div class="' + facetClass + '">\ <div class="' + headerClass + '"><div class="row"> \ <div class="col-md-12">\ ' + header + '\ </div>\ </div></div>\ <div class="' + bodyClass + '">\ <div class="row" style="display:none" id="' + resultsId + '">\ <div class="col-md-12">\ ' + introFrag + '\ {{FILTERS}}\ </div>\ </div></div>\ </div>'; // substitute in the component parts frag = frag.replace(/{{FILTERS}}/g, filters); // now render it into the page comp.context.html(frag); // trigger all the post-render set-up functions this.setUIOpen(); // sort out the selectors we're going to be needing var valueSelector = edges.css_class_selector(namespace, "value", this); var filterRemoveSelector = edges.css_class_selector(namespace, "filter-remove", this); var toggleSelector = edges.css_id_selector(namespace, "toggle", this); // for when a value in the facet is selected edges.on(valueSelector, "click", this, "filterSelected"); // for when the open button is clicked edges.on(toggleSelector, "click", this, "toggleOpen"); // for when a filter remove button is clicked edges.on(filterRemoveSelector, "click", this, "removeFilter"); }; this.headerLayout = function(params) { var toggleId = params.toggleId; var iconClass = edges.css_classes(this.namespace, "icon", this); if (this.layout === "left") { var tog = this.facetTitle; if (this.togglable) { tog = '<a href="#" id="' + toggleId + '"><i class="' + this.openIcon + '"></i> ' + tog + "</a>"; } return tog; } else if (this.layout === "right") { var tog = ""; if (this.togglable) { tog = '<a href="#" id="' + toggleId + '">' + this.facetTitle + ' <i class="' + this.openIcon + ' ' + iconClass + '"></i></a>'; } else { tog = this.facetTitle; } return tog; } }; this.setUIOpen = function () { // the selectors that we're going to use var resultsSelector = edges.css_id_selector(this.namespace, "results", this); var toggleSelector = edges.css_id_selector(this.namespace, "toggle", this); var results = this.component.jq(resultsSelector); var toggle = this.component.jq(toggleSelector); var openBits = this.openIcon.split(" "); var closeBits = this.closeIcon.split(" "); if (this.open) { var i = toggle.find("i"); for (var j = 0; j < openBits.length; j++) { i.removeClass(openBits[j]); } for (var j = 0; j < closeBits.length; j++) { i.addClass(closeBits[j]); } results.show(); } else { var i = toggle.find("i"); for (var j = 0; j < closeBits.length; j++) { i.removeClass(closeBits[j]); } for (var j = 0; j < openBits.length; j++) { i.addClass(openBits[j]); } results.hide(); } }; this.filterSelected = function (element) { var filter_id = this.component.jq(element).attr("data-filter"); this.component.addFilter(filter_id); }; this.removeFilter = function (element) { var filter_id = this.component.jq(element).attr("data-filter"); this.component.removeFilter(filter_id); }; this.toggleOpen = function (element) { this.open = !this.open; this.setUIOpen(); }; } } });