Issue:
Create a multiselect combobox in CQ.
Layout:
Widget file (multiselectlist.js):
if ('function' !== typeof RegExp.escape) {
RegExp.escape = function(s) { if ('string' !== typeof s) { return s; } return s.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); }; } |
CQ.Ext.form.Multiselect = CQ.Ext.extend(CQ.Ext.form.ComboBox, {
checkField: 'checked', separator: ',', multiSelect: true, mode: "remote", isSelectAll: false, constructor: function(config) { config = config || {}; var nameTextField = config.name; var that = this; config.store = new CQ.Ext.data.Store({ //autoLoad: true, proxy: new CQ.Ext.data.HttpProxy({ url: config.options, method: 'GET' }), reader: new CQ.Ext.data.JsonReader({ root: 'root', fields: [config.valueField, config.displayField] }), }); config.store.on("load", function(store, records, options) { var v = document.getElementsByName(nameTextField)[0].value; var numberItem = v.split(",").length + 1; store.each(function(r) { var checked = false; var id = r.get(config.valueField); var value = r.data.name; if (v.indexOf(id) != -1 || v.indexOf(value) != -1 ) { checked = true; } r.set(that.checkField, checked); }, that); if(numberItem == records.length){ $('#' + that.innerList.id + '').find("input:first").attr('checked', 'checked'); that.isSelectAll = true; } that.value = that.getCheckedValue(); that.setRawValue(that.getCheckedDisplay()); }); config.triggerAction = "all"; CQ.Ext.form.Multiselect.superclass.constructor.call(this, config); }, initComponent: function() { if (!this.tpl) { this.tpl = '<tpl for=".">' + '<div class="x-combo-list-item">' + '<div class="ux-lovcombo-item-text"><input style="float:left;position: relative;top:2px" id="{' + this.valueField + '}" class="{' + this.valueField + '}" type="checkbox"/>' + '<label style="display:block;padding-left:20px" for="{' + this.valueField + '}">{' + this.displayField + '}</label>' + '</div>' + '</div>' + '</tpl>'; } CQ.Ext.form.Multiselect.superclass.initComponent.apply(this); this.on({ scope: this, beforequery: this.onBeforeQuery, blur: this.onRealBlur }); this.onLoad = this.onLoad.createSequence(function() { if (this.el) { var v = this.el.dom.value; this.el.dom.value = ''; this.el.dom.value = v; } }); }, initEvents: function() { CQ.Ext.form.Multiselect.superclass.initEvents.apply(this, arguments); this.keyNav.tab = false; }, clearValue: function() { this.value = ''; this.setRawValue(this.value); this.store.clearFilter(); this.store.each(function(r) { r.set(this.checkField, false); }, this); if (this.hiddenField) { this.hiddenField.value = ''; } this.applyEmptyText(); }, getCheckedDisplay: function() { var re = new RegExp(this.separator, "g"); return this.getCheckedValue(this.displayField).replace(re, this.separator + ' '); }, getCheckedValue: function(field) { field = field || this.valueField; var c = []; var value = ""; var snapshot = this.store.snapshot || this.store.data; snapshot.each(function(r) { var id = r.data.id; if(id != "selectAll"){ value = r.get(field); divItem = $('#' + id + ''); if (r.get(this.checkField)) { c.push(value); divItem.attr('checked', 'checked'); } else { divItem.removeAttr('checked'); } } }, this); return c.join(this.separator); }, onBeforeQuery: function(qe) { qe.query = qe.query.replace(new RegExp(RegExp.escape(this.getCheckedDisplay()) + '[ ' + this.separator + ']*'), ''); }, onRealBlur: function() { this.list.hide(); var rv = this.getRawValue(); var rva = rv.split(new RegExp(RegExp.escape(this.separator) + ' *')); var va = []; var snapshot = this.store.snapshot || this.store.data; CQ.Ext.each(rva, function(v) { snapshot.each(function(r) { if (v === r.get(this.displayField)) { va.push(r.get(this.valueField)); } }, this); }, this); this.setValue(va.join(this.separator)); this.store.clearFilter(); }, /** * Handle when click select item * @param {Mixed} * record : record contains item * index : position item */ onSelect: function(record, index) { if (this.fireEvent('beforeselect', this, record, index) !== false) { record.set(this.checkField, !record.get(this.checkField)); if (record.data.id == "selectAll") { if (!this.isSelectAll) { this.selectAll(); $('#' + this.innerList.id + '').find("input:first").attr('checked', 'checked'); this.isSelectAll = true; } else { this.deselectAll(); $('#' + this.innerList.id + '').find("input:first").removeAttr('checked'); this.isSelectAll = false; } } else { if (this.store.isFiltered()) { this.doQuery(this.allQuery); } this.setValue(this.getCheckedValue()); this.fireEvent('select', this, record, index); } } }, /** * Sets the value for textfield when load or click select item * @param {Mixed} * v:value */ setValue: function(v) { if (v) { v = '' + v; if (this.store.data.length != 0) { // this.store.clearFilter(); this.store.each(function(r) { var checked = false; var id = r.get(this.valueField); var value = r.data.name; if (v.indexOf(id) != -1 || v.indexOf(value) != -1 ) { checked = true; } r.set(this.checkField, checked); }, this); this.value = this.getCheckedValue(); this.setRawValue(this.getCheckedDisplay()); if (this.hiddenField) { this.hiddenField.value = this.value; } } else { this.value = v; this.setRawValue(v); if (this.hiddenField) { this.hiddenField.value = v; } } if (this.el) { this.el.removeClass(this.emptyClass); } } else { this.clearValue(); } }, /** * Selects all items */ selectAll: function() { this.store.each(function(record) { if (record.data.id != "") { record.set(this.checkField, true); } }, this); // display full list this.doQuery(this.allQuery); this.setValue(this.getCheckedValue()); }, /** * Deselects all items. */ deselectAll: function() { this.clearValue(); } }); CQ.Ext.reg('multiselect', CQ.Ext.form.Multiselect);
Config:
<changeLink
jcr:primaryType="cq:Widget" displayField="name" fieldLabel="Change Country Link" name="./changeLink" options="$PATH.seasonlist.json" valueField="id" xtype="multiselect"/>
Note: displayField, valueField, options are mandatory fields.
options: is the url that is used to call to servlet to get data map for combobox.
displayField: is the name of field to display which is returned from servlet.
valueField: is the name of value field which is returned from servlet.
Servlet:
@SlingServlet(
selectors = {"seasonlist"}, methods = {"GET"}, extensions = {"json"}, resourceTypes = {"sling/servlet/default"} ) @Properties({ @Property(name="service.pid", value="com.test.servlet.SeasonListServlet",propertyPrivate=false), @Property(name="service.description",value="Servlet to retrieve a season list", propertyPrivate=false), @Property(name="service.vendor",value="Test", propertyPrivate=false) }) public class SeasonListServlet extends SlingAllMethodsServlet { private static final long serialVersionUID = 1L; private static final Logger logger = LoggerFactory.getLogger(SeasonListServlet.class); @Override protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException { response.setContentType("text/json; charset=UTF-8"); Map<String, String> seasonList = new HashMap<String, String>(); getJsonSeasonList(seasonList); } private JSONObject getJsonSeasonList(HashMap<String, String> seasonList) throws JSONException { JSONObject jsonObj = new JSONObject(); JSONArray seasonArray = new JSONArray(); JSONObject jsonProd = null; for(String season : seasonList) { jsonProd = new JSONObject(); jsonProd.put("id", season.id); jsonProd.put("name", season.name); seasonArray.put(jsonProd); } jsonObj.put("root", seasonArray); return jsonObj; } } |
Note: to add "Select All" option into combobox list, please set it in the list which is returned from servlet. The value is:
jsonProd.put("id", "selectAll");
jsonProd.put("name", "Select All);
jsonProd.put("name", "Select All);
Nhận xét
Đăng nhận xét