From 7a8c04f14a5bf6251f42138072770dca79b2e436 Mon Sep 17 00:00:00 2001 From: Lena Daxenbichler Date: Thu, 26 Sep 2024 13:21:15 +0200 Subject: [PATCH] implement custom adapters. ajax fields should work as expected now --- js/src/bootstrap5/widget.js | 109 +++++++++++------- src/yafowil/widget/select2/example.py | 21 ++-- .../select2/resources/bootstrap5/widget.js | 94 +++++++++------ .../resources/bootstrap5/widget.min.js | 2 +- 4 files changed, 143 insertions(+), 83 deletions(-) diff --git a/js/src/bootstrap5/widget.js b/js/src/bootstrap5/widget.js index 50c3641..2c9b16c 100644 --- a/js/src/bootstrap5/widget.js +++ b/js/src/bootstrap5/widget.js @@ -1,6 +1,66 @@ import $ from 'jquery'; +// define custom adapters +$.fn.select2.amd.define('select2/data/singleValueAjaxAdapter',[ + 'select2/data/ajax', + 'select2/utils' + ], + function (AjaxAdapter, Utils) { + function SingleValueAjaxAdapter ($element, options) { + SingleValueAjaxAdapter.__super__.constructor.call(this, $element, options); + } + Utils.Extend(SingleValueAjaxAdapter, AjaxAdapter); + + SingleValueAjaxAdapter.prototype.current = function (callback) { + let value = this.$element.val(); + let vocab = this.$element.data('vocabulary'); + function label(key) { + return (!vocab || !vocab[key]) ? key : vocab[key]; + } + callback([{ id: value, text: label(value) }]); + }; + + SingleValueAjaxAdapter.prototype.select = function(data) { + this.$element.find('option[value="' + data.id + '"]').prop('selected', true); + AjaxAdapter.prototype.select.call(this, data) + }; + + return SingleValueAjaxAdapter; +}); + +$.fn.select2.amd.define('select2/data/multiValueAjaxAdapter',[ + 'select2/data/ajax', + 'select2/utils' +], +function (AjaxAdapter, Utils) { + function MultiValueAjaxAdapter ($element, options) { + MultiValueAjaxAdapter.__super__.constructor.call(this, $element, options); + } + Utils.Extend(MultiValueAjaxAdapter, AjaxAdapter); + + MultiValueAjaxAdapter.prototype.current = function (callback) { + let value = this.$element.val(); + let vocab = this.$element.data('vocabulary'); + function label(key) { + return (!vocab || !vocab[key]) ? key : vocab[key]; + } + let data = []; + value.split(',').forEach((v) => { + data.push({ id: v, text: label(v) }); + }); + callback(data); + }; + + MultiValueAjaxAdapter.prototype.select = function(data) { + AjaxAdapter.prototype.select.call(this, data); + }; + + return MultiValueAjaxAdapter; +}); +const singleValueAjaxAdapter=$.fn.select2.amd.require('select2/data/singleValueAjaxAdapter'); +const multiValueAjaxAdapter=$.fn.select2.amd.require('select2/data/multiValueAjaxAdapter'); + export class Select2Widget { static initialize(context) { @@ -35,56 +95,25 @@ export class Select2Widget { options.ajax = { url: options.ajaxurl, dataType: 'json', - data: function (params) { // `params` replaces `term` in Select2 v4.x + data: function (params) { return { q: params.term }; }, - processResults: function (data) { // `processResults` replaces `results` + processResults: function (data, params) { if (options.tags && !data.length) { data.push({ id: params.term, text: params.term }); } - return { results: data }; + let results = data.map(item => ({ id: item.id, text: item.text || item.id })); + return { results: results }; } }; - $.fn.select2.amd.require(["select2/data/select"], function(Select) { - let CustomDataAdapter = Select; - - CustomDataAdapter.prototype.current = function (callback) { - console.log('current') - let value = this.$element.val(); - console.log(value) - - let vocab = this.$element.data('vocabulary'); - function label(key) { - return (!vocab || !vocab[key]) ? key : vocab[key]; - } - - if (options.multiple) { - console.log('multi') - let data = []; - $(this.$element.val().split(",")).each(function() { - data.push({ id: this, text: label(this) }); - }); - callback(data); - } else { - console.log('single') - callback([{ id: 'foo', text: value }]); - } - }; - - let originalSelect = CustomDataAdapter.prototype.select; - CustomDataAdapter.prototype.select = function (data) { - console.log(data) - // Your own code - // Call the original function while keeping 'this' context - originalSelect.bind(this)(data); - }; - - // Finally, use the custom data adapter - options.dataAdapter = CustomDataAdapter; - }); + if (options.multiple) { + options.dataAdapter = multiValueAjaxAdapter; + } else { + options.dataAdapter = singleValueAjaxAdapter; + } } options.theme = 'bootstrap-5'; diff --git a/src/yafowil/widget/select2/example.py b/src/yafowil/widget/select2/example.py index 963eaae..6102ea7 100644 --- a/src/yafowil/widget/select2/example.py +++ b/src/yafowil/widget/select2/example.py @@ -255,31 +255,38 @@ def get_example(): }) select2_6_routes = {'yafowil.widget.select2.json': json_response} - return [{ + return [ + { 'widget': select2_1, 'doc': DOC_SELECT2_1, 'title': TITLE_SELECT2_1 - }, { + }, + { 'widget': select2_2, 'doc': DOC_SELECT2_2, 'title': TITLE_SELECT2_2 - }, { + }, + { 'widget': select2_3, 'doc': DOC_SELECT2_3, 'title': TITLE_SELECT2_3 - }, { + }, + { 'widget': select2_4, 'routes': select2_4_routes, 'doc': DOC_SELECT2_4, 'title': TITLE_SELECT2_4 - }, { + }, + { 'widget': select2_5, 'routes': select2_5_routes, 'doc': DOC_SELECT2_5, 'title': TITLE_SELECT2_5 - }, { + }, + { 'widget': select2_6, 'routes': select2_6_routes, 'doc': DOC_SELECT2_6, 'title': TITLE_SELECT2_6 - }] + } + ] diff --git a/src/yafowil/widget/select2/resources/bootstrap5/widget.js b/src/yafowil/widget/select2/resources/bootstrap5/widget.js index 9792418..4b6bf55 100644 --- a/src/yafowil/widget/select2/resources/bootstrap5/widget.js +++ b/src/yafowil/widget/select2/resources/bootstrap5/widget.js @@ -1,6 +1,57 @@ var yafowil_select2 = (function (exports, $) { 'use strict'; + $.fn.select2.amd.define('select2/data/singleValueAjaxAdapter',[ + 'select2/data/ajax', + 'select2/utils' + ], + function (AjaxAdapter, Utils) { + function SingleValueAjaxAdapter ($element, options) { + SingleValueAjaxAdapter.__super__.constructor.call(this, $element, options); + } + Utils.Extend(SingleValueAjaxAdapter, AjaxAdapter); + SingleValueAjaxAdapter.prototype.current = function (callback) { + let value = this.$element.val(); + let vocab = this.$element.data('vocabulary'); + function label(key) { + return (!vocab || !vocab[key]) ? key : vocab[key]; + } + callback([{ id: value, text: label(value) }]); + }; + SingleValueAjaxAdapter.prototype.select = function(data) { + this.$element.find('option[value="' + data.id + '"]').prop('selected', true); + AjaxAdapter.prototype.select.call(this, data); + }; + return SingleValueAjaxAdapter; + }); + $.fn.select2.amd.define('select2/data/multiValueAjaxAdapter',[ + 'select2/data/ajax', + 'select2/utils' + ], + function (AjaxAdapter, Utils) { + function MultiValueAjaxAdapter ($element, options) { + MultiValueAjaxAdapter.__super__.constructor.call(this, $element, options); + } + Utils.Extend(MultiValueAjaxAdapter, AjaxAdapter); + MultiValueAjaxAdapter.prototype.current = function (callback) { + let value = this.$element.val(); + let vocab = this.$element.data('vocabulary'); + function label(key) { + return (!vocab || !vocab[key]) ? key : vocab[key]; + } + let data = []; + value.split(',').forEach((v) => { + data.push({ id: v, text: label(v) }); + }); + callback(data); + }; + MultiValueAjaxAdapter.prototype.select = function(data) { + AjaxAdapter.prototype.select.call(this, data); + }; + return MultiValueAjaxAdapter; + }); + const singleValueAjaxAdapter=$.fn.select2.amd.require('select2/data/singleValueAjaxAdapter'); + const multiValueAjaxAdapter=$.fn.select2.amd.require('select2/data/multiValueAjaxAdapter'); class Select2Widget { static initialize(context) { $('.select2', context).each(function (event) { @@ -22,9 +73,6 @@ var yafowil_select2 = (function (exports, $) { throw `Failed to initialize select2: ${error}`; } elem.data('yafowil-select2', this); - if (this.elem.val()) { - this.elem.trigger('change'); - } } init_options(options) { for (let name in options) { @@ -37,46 +85,22 @@ var yafowil_select2 = (function (exports, $) { data: function (params) { return { q: params.term }; }, - processResults: function (data) { + processResults: function (data, params) { if (options.tags && !data.length) { data.push({ id: params.term, text: params.term }); } - return { results: data }; + let results = data.map(item => ({ id: item.id, text: item.text || item.id })); + return { results: results }; } }; - $.fn.select2.amd.require(["select2/data/select"], function(Select) { - let CustomDataAdapter = Select; - CustomDataAdapter.prototype.current = function (callback) { - console.log('current'); - let value = this.$element.val(); - console.log(value); - let vocab = this.$element.data('vocabulary'); - function label(key) { - return (!vocab || !vocab[key]) ? key : vocab[key]; - } - if (options.multiple) { - console.log('multi'); - let data = []; - $(this.$element.val().split(",")).each(function() { - data.push({ id: this, text: label(this) }); - }); - callback(data); - } else { - console.log('single'); - callback([{ id: 'foo', text: value }]); - } - }; - let originalSelect = CustomDataAdapter.prototype.select; - CustomDataAdapter.prototype.select = function (data) { - console.log(data); - console.log('ARHGHHGGH'); - originalSelect.bind(this)(data); - }; - options.dataAdapter = CustomDataAdapter; - }); + if (options.multiple) { + options.dataAdapter = multiValueAjaxAdapter; + } else { + options.dataAdapter = singleValueAjaxAdapter; + } } options.theme = 'bootstrap-5'; options.selectionCssClass = "select2--medium"; diff --git a/src/yafowil/widget/select2/resources/bootstrap5/widget.min.js b/src/yafowil/widget/select2/resources/bootstrap5/widget.min.js index 90eafae..315a940 100644 --- a/src/yafowil/widget/select2/resources/bootstrap5/widget.min.js +++ b/src/yafowil/widget/select2/resources/bootstrap5/widget.min.js @@ -1 +1 @@ -var yafowil_select2=function(t,e){"use strict";class i{static initialize(t){e(".select2",t).each((function(t){let o=e(this);if(void 0!==window.yafowil_array&&window.yafowil_array.inside_template(o))return;let l=o.data();new i(o,l)}))}constructor(t,e){this.elem=t,this.options=this.init_options(e);try{this.elem.select2(this.options)}catch(t){throw`Failed to initialize select2: ${t}`}t.data("yafowil-select2",this),this.elem.val()&&this.elem.trigger("change")}init_options(t){for(let e in t)t[e]=this.extract_value(t[e]);return t.ajaxurl&&(t.ajax={url:t.ajaxurl,dataType:"json",data:function(t){return{q:t.term}},processResults:function(e){return t.tags&&!e.length&&e.push({id:params.term,text:params.term}),{results:e}}},e.fn.select2.amd.require(["select2/data/select"],(function(i){let o=i;o.prototype.current=function(i){console.log("current");let o=this.$element.val();console.log(o);let l=this.$element.data("vocabulary");if(t.multiple){console.log("multi");let t=[];e(this.$element.val().split(",")).each((function(){var e;t.push({id:this,text:(e=this,l&&l[e]?l[e]:e)})})),i(t)}else console.log("single"),i([{id:"foo",text:o}])};let l=o.prototype.select;o.prototype.select=function(t){console.log(t),console.log("ARHGHHGGH"),l.bind(this)(t)},t.dataAdapter=o}))),t.theme="bootstrap-5",t.selectionCssClass="select2--medium",t.dropdownCssClass="select2--medium",t.width="500px",t}extract_value(t){if("string"==typeof t&&!t.indexOf("javascript:")){if(!(t=t.substring(11,t.length).split("."))[0].length)throw"No function defined";let e=window;for(let i of t){if(void 0===e[i])throw`${i} not found`;e=e[i]}t=e}return t}}function o(t,e){i.initialize(e)}function l(){void 0!==window.yafowil_array&&window.yafowil_array.on_array_event("on_add",o)}return e((function(){void 0!==window.ts?ts.ajax.register(i.initialize,!0):void 0!==window.bdajax?bdajax.register(i.initialize,!0):i.initialize(),l()})),t.Select2Widget=i,t.register_array_subscribers=l,Object.defineProperty(t,"__esModule",{value:!0}),window.yafowil=window.yafowil||{},window.yafowil.select2=t,t}({},jQuery); +var yafowil_select2=function(t,e){"use strict";e.fn.select2.amd.define("select2/data/singleValueAjaxAdapter",["select2/data/ajax","select2/utils"],(function(t,e){function i(t,e){i.__super__.constructor.call(this,t,e)}return e.Extend(i,t),i.prototype.current=function(t){let e=this.$element.val(),i=this.$element.data("vocabulary");var a;t([{id:e,text:(a=e,i&&i[a]?i[a]:a)}])},i.prototype.select=function(e){this.$element.find('option[value="'+e.id+'"]').prop("selected",!0),t.prototype.select.call(this,e)},i})),e.fn.select2.amd.define("select2/data/multiValueAjaxAdapter",["select2/data/ajax","select2/utils"],(function(t,e){function i(t,e){i.__super__.constructor.call(this,t,e)}return e.Extend(i,t),i.prototype.current=function(t){let e=this.$element.val(),i=this.$element.data("vocabulary");let a=[];e.split(",").forEach((t=>{var e;a.push({id:t,text:(e=t,i&&i[e]?i[e]:e)})})),t(a)},i.prototype.select=function(e){t.prototype.select.call(this,e)},i}));const i=e.fn.select2.amd.require("select2/data/singleValueAjaxAdapter"),a=e.fn.select2.amd.require("select2/data/multiValueAjaxAdapter");class n{static initialize(t){e(".select2",t).each((function(t){let i=e(this);if(void 0!==window.yafowil_array&&window.yafowil_array.inside_template(i))return;let a=i.data();new n(i,a)}))}constructor(t,e){this.elem=t,this.options=this.init_options(e);try{this.elem.select2(this.options)}catch(t){throw`Failed to initialize select2: ${t}`}t.data("yafowil-select2",this)}init_options(t){for(let e in t)t[e]=this.extract_value(t[e]);return t.ajaxurl&&(t.ajax={url:t.ajaxurl,dataType:"json",data:function(t){return{q:t.term}},processResults:function(e,i){return t.tags&&!e.length&&e.push({id:i.term,text:i.term}),{results:e.map((t=>({id:t.id,text:t.text||t.id})))}}},t.multiple?t.dataAdapter=a:t.dataAdapter=i),t.theme="bootstrap-5",t.selectionCssClass="select2--medium",t.dropdownCssClass="select2--medium",t.width="500px",t}extract_value(t){if("string"==typeof t&&!t.indexOf("javascript:")){if(!(t=t.substring(11,t.length).split("."))[0].length)throw"No function defined";let e=window;for(let i of t){if(void 0===e[i])throw`${i} not found`;e=e[i]}t=e}return t}}function l(t,e){n.initialize(e)}function s(){void 0!==window.yafowil_array&&window.yafowil_array.on_array_event("on_add",l)}return e((function(){void 0!==window.ts?ts.ajax.register(n.initialize,!0):void 0!==window.bdajax?bdajax.register(n.initialize,!0):n.initialize(),s()})),t.Select2Widget=n,t.register_array_subscribers=s,Object.defineProperty(t,"__esModule",{value:!0}),window.yafowil=window.yafowil||{},window.yafowil.select2=t,t}({},jQuery);