From 769469e5bfa185fb56cc7f5ab8f93b910f376b25 Mon Sep 17 00:00:00 2001 From: Tomotaka Hosomi <61442-hosomitm@users.noreply.drupalcode.org> Date: Sun, 3 Dec 2023 09:36:46 +0000 Subject: [PATCH] Issue #3401473 by hosomitm, yas: Refactor to native JavaScript from jQuery (openstack_form.js) --- cloud.libraries.yml | 13 ++ .../openstack/css/openstack_form.css | 11 ++ .../openstack/js/openstack_form.js | 173 ++++-------------- .../openstack/openstack.libraries.yml | 6 +- 4 files changed, 68 insertions(+), 135 deletions(-) create mode 100644 modules/cloud_service_providers/openstack/css/openstack_form.css diff --git a/cloud.libraries.yml b/cloud.libraries.yml index c56934bb68..e30eae9c08 100644 --- a/cloud.libraries.yml +++ b/cloud.libraries.yml @@ -60,6 +60,19 @@ select2: theme: https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.5/css/select2.min.css: { type: external, minified: true } +tom-select: + remote: https://github.com/orchidjs/tom-select + version: 2.3.1 + license: + name: Apache License, Version 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0 + gpl-compatible: false + js: + https://cdn.jsdelivr.net/npm/tom-select@2.3.1/dist/js/tom-select.complete.min.js: { type: external, minified: true } + css: + theme: + https://cdn.jsdelivr.net/npm/tom-select@2.3.1/dist/css/tom-select.css: { type: external, minified: true } + datatables: remote: https://github.com/fiduswriter/Simple-DataTables version: 3.1.2 diff --git a/modules/cloud_service_providers/openstack/css/openstack_form.css b/modules/cloud_service_providers/openstack/css/openstack_form.css new file mode 100644 index 0000000000..f0677f4228 --- /dev/null +++ b/modules/cloud_service_providers/openstack/css/openstack_form.css @@ -0,0 +1,11 @@ +.ts-control { + position: absolute; + top: 50%; + left: 0; + transform: translateY(-50%); + border: none; +} + +.plugin-dropdown_input.focus.dropdown-active .ts-control { + border: none; +} diff --git a/modules/cloud_service_providers/openstack/js/openstack_form.js b/modules/cloud_service_providers/openstack/js/openstack_form.js index da5d39f7ee..9469607ac8 100644 --- a/modules/cloud_service_providers/openstack/js/openstack_form.js +++ b/modules/cloud_service_providers/openstack/js/openstack_form.js @@ -1,141 +1,48 @@ -(function ($) { +(function () { 'use strict'; - // Select2 custom results adapter. - $.fn.select2.amd.define('CustomResultsAdapter', [ - 'select2/utils', - 'select2/results' - ], - function (Utils, Results) { - function CustomResultsAdapter($element, options, dataAdapter) { - this.$element = $element; - this.data = dataAdapter; - this.options = options; - - CustomResultsAdapter.__super__.constructor.call(this, $element, options, dataAdapter); - } - - Utils.Extend(CustomResultsAdapter, Results); - - CustomResultsAdapter.prototype.render = function () { - let $results = $( - '<tbody class="select2-results__options" role="tree"></tbody>' - ); - - if (this.options.get('multiple')) { - $results.attr('aria-multiselectable', 'true'); - } - - this.$results = $results; - - return $results; - }; - - CustomResultsAdapter.prototype.option = function (data) { - let option = document.createElement('tr'); - - option.className = 'select2-results__option'; - let attrs = { - 'role': 'treeitem', - 'aria-selected': 'false' - }; - - if (data.disabled) { - delete attrs['aria-selected']; - attrs['aria-disabled'] = 'true'; - } - - if (data.id === null) { - delete attrs['aria-selected']; - } - - if (data._resultId !== null) { - option.id = data._resultId; - } - - if (data.title) { - option.title = data.title; - } - - if (data.children) { - attrs.role = 'group'; - attrs['aria-label'] = data.text; - delete attrs['aria-selected']; - } - - for (let attr in attrs) { - if (attrs.hasOwnProperty(attr)) { - let val = attrs[attr]; - option.setAttribute(attr, val); - } - } - - this.template(data, option); - $.data(option, 'data', data); - return option; - }; - - return CustomResultsAdapter; - }); - - // Select2 custom dropdown adapter. - $.fn.select2.amd.define('CustomDropdownAdapter', [ - 'select2/utils', - 'select2/dropdown', - 'select2/dropdown/attachBody', - 'select2/dropdown/attachContainer', - 'select2/dropdown/search' - ], - function (Utils, Dropdown, AttachBody, AttachContainer, Search) { - function CustomDropdownAdapter($element, options) { - this.$element = $element; - this.options = options; - - CustomDropdownAdapter.__super__.constructor.call(this, $element, options); + // Resets the for attribute of Label rewritten by tom-select to its original value. + const resetLabel = function (label_for) { + const control_id = label_for + '-ts-control'; + const query = "label[for='" + control_id + "']"; + const label = document.querySelector(query); + if (label) { + label.setAttribute('for', label_for); } - - Utils.Extend(CustomDropdownAdapter, Dropdown); - - CustomDropdownAdapter.prototype.render = function () { - let $dropdown = $( - '<div class="select2-dropdown"><table class="select2-results"><thead><tr><th>Name</th><th>vCPUs</th><th>RAM (MB)</th></tr></thead></table></div>' - ); - - $dropdown.attr('dir', this.options.get('dir')); - this.$dropdown = $dropdown; - return $dropdown; - }; - - let adapter = Utils.Decorate(CustomDropdownAdapter, Search); - adapter = Utils.Decorate(adapter, AttachContainer); - adapter = Utils.Decorate(adapter, AttachBody); - return adapter; - }); + } // Flavor. - $('#edit-field-flavor').select2({ - width: '100%', - closeOnSelect: true, - dropdownAdapter: $.fn.select2.amd.require('CustomDropdownAdapter'), - resultsAdapter: $.fn.select2.amd.require('CustomResultsAdapter'), - templateResult: function (state) { - let parts = state.text.split(':').slice(0, 5); - let html = '<td>' + parts.join('</td><td>') + '</td>'; - if (parts.length === 1) { - html = '<td colspan=5>' + parts[0] + '</td>'; - } - let $state = $(html); - return $state; - }, - templateSelection: (state) => { - if (!state.id) { - return state.text; + new TomSelect("#edit-field-flavor", { + create: false, + dropdownParent: 'body', + plugins: [ + 'dropdown_input', + 'no_backspace_delete', + ], + render: { + dropdown: function () { + return '<div><div style="font-weight: bold;">' + + '<span style="width: 50%; display: inline-block;">Name</span>' + + '<span style="width: 25%; display: inline-block;">vCPUs</span>' + + '<span style="width: 25%; display: inline-block;">RAM (MB)</span>' + + '</div></div>'; + }, + option: function (data, escape) { + const splitLabel = escape(data.text).split(':'); + while (splitLabel.length < 3) { + splitLabel.push(''); + } + return '<div>' + + '<span style="width: 50%; display: inline-block;">' + splitLabel[0] + '</span>' + + '<span style="width: 25%; display: inline-block;">' + splitLabel[1] + '</span>' + + '<span style="width: 25%; display: inline-block;">' + splitLabel[2] + '</span>' + + '</div>'; + }, + item: function (data, escape) { + const splitLabel = escape(data.text).split(':'); + return '<div title="' + splitLabel[0] + '">' + splitLabel[0] + '</div>'; } - let $state = $( - '<span>' + state.text.split(':').shift() + '</span>' - ); - return $state; } }); - -})(jQuery); + resetLabel("edit-field-flavor"); +})(); diff --git a/modules/cloud_service_providers/openstack/openstack.libraries.yml b/modules/cloud_service_providers/openstack/openstack.libraries.yml index 3bda5b9719..bd928ab0ff 100644 --- a/modules/cloud_service_providers/openstack/openstack.libraries.yml +++ b/modules/cloud_service_providers/openstack/openstack.libraries.yml @@ -2,9 +2,11 @@ openstack_form: version: 5.x-dev js: js/openstack_form.js: {} + css: + theme: + css/openstack_form.css: {} dependencies: - - core/jquery - - cloud/select2 + - cloud/tom-select openstack_launch_template_radios: version: 6.x-dev -- GitLab