From 1530bb89fe1be45c5042fec3ee317f933f5fb27d Mon Sep 17 00:00:00 2001 From: Pierre Goiffon Date: Wed, 26 Sep 2018 10:39:23 +0200 Subject: [PATCH] =?UTF-8?q?N=C2=B0931=20TagSet=20widget=20and=20its=20POC?= =?UTF-8?q?=20are=20now=20more=20generic=20(to=20be=20used=20in=20all=20At?= =?UTF-8?q?tributeSet=20hierarchy)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- application/cmdbabstract.class.inc.php | 6 +- core/attributedef.class.inc.php | 4 +- dictionaries/en.dictionary.itop.core.php | 2 +- dictionaries/fr.dictionary.itop.core.php | 2 +- ...et-widget.js => jquery.itop-set-widget.js} | 85 ++++++------- test/attributeset_widget_poc.html | 96 ++++++++++++++ test/tagset_widget_poc.html | 117 ------------------ 7 files changed, 146 insertions(+), 166 deletions(-) rename js/{jquery.itop-tagset-widget.js => jquery.itop-set-widget.js} (69%) create mode 100644 test/attributeset_widget_poc.html delete mode 100644 test/tagset_widget_poc.html diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php index eafee92a1..c60542867 100644 --- a/application/cmdbabstract.class.inc.php +++ b/application/cmdbabstract.class.inc.php @@ -2041,15 +2041,15 @@ EOF case 'TagSet': $oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'/js/selectize.min.js'); $oPage->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/selectize.default.css'); - $oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'/js/jquery.itop-tagset-widget.js'); + $oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'/js/jquery.itop-set-widget.js'); - $oPage->add_dict_entry('Core:AttributeTagSet:placeholder'); + $oPage->add_dict_entry('Core:AttributeSet:placeholder'); /** @var \ormTagSet $value */ $sJson = $oAttDef->GetJsonForWidget($value); $sInputId = "attr_{$sFormPrefix}{$sAttCode}"; $sHTMLValue = "
{$sValidationSpan}{$sReloadSpan}"; - $sScript = "$('#$sInputId').tagset_widget();"; + $sScript = "$('#$sInputId').set_widget();"; $oPage->add_ready_script($sScript); break; diff --git a/core/attributedef.class.inc.php b/core/attributedef.class.inc.php index a1600f11f..2155f6cc8 100644 --- a/core/attributedef.class.inc.php +++ b/core/attributedef.class.inc.php @@ -6717,7 +6717,7 @@ class AttributeTagSet extends AttributeDBFieldVoid /** * @param \ormTagSet $oValue * - * @return string JSON to be used in the itop.tagset_widget JQuery widget + * @return string JSON to be used in the itop.set_widget JQuery widget * @throws \CoreException */ public function GetJsonForWidget($oValue) @@ -6750,7 +6750,7 @@ class AttributeTagSet extends AttributeDBFieldVoid $aJson['removed'] = array(); $iMaxTags = $this->GetTagMaxNb(); - $aJson['max_tags_allowed'] = $iMaxTags; + $aJson['max_items_allowed'] = $iMaxTags; return json_encode($aJson); } diff --git a/dictionaries/en.dictionary.itop.core.php b/dictionaries/en.dictionary.itop.core.php index 3b71d6d2f..95c20f68b 100644 --- a/dictionaries/en.dictionary.itop.core.php +++ b/dictionaries/en.dictionary.itop.core.php @@ -36,7 +36,7 @@ Dict::Add('EN US', 'English', 'English', array( 'Core:AttributeTagSet' => 'List of tags', 'Core:AttributeTagSet+' => '', - 'Core:AttributeTagSet:placeholder' => 'click to add', + 'Core:AttributeSet:placeholder' => 'click to add', 'Core:AttributeCaseLog' => 'Log', 'Core:AttributeCaseLog+' => '', diff --git a/dictionaries/fr.dictionary.itop.core.php b/dictionaries/fr.dictionary.itop.core.php index e026ba396..dfd8c0bce 100644 --- a/dictionaries/fr.dictionary.itop.core.php +++ b/dictionaries/fr.dictionary.itop.core.php @@ -432,7 +432,7 @@ Dict::Add('FR FR', 'French', 'Français', array( 'Core:AttributeLinkedSet+' => 'Liste d\'objets d\'une classe donnée et pointant sur l\'objet courant', 'Core:AttributeTagSet' => 'Liste d\'étiquettes', 'Core:AttributeTagSet+' => '', - 'Core:AttributeTagSet:placeholder' => 'cliquer pour ajouter', + 'Core:AttributeSet:placeholder' => 'cliquer pour ajouter', 'Core:AttributeLinkedSetIndirect' => 'Objets liés (1-n)', 'Core:AttributeLinkedSetIndirect+' => 'Liste d\'objets d\'une classe donnée et liés à l\'objet courant via une classe intermédiaire', 'Core:AttributeInteger' => 'Nombre entier', diff --git a/js/jquery.itop-tagset-widget.js b/js/jquery.itop-set-widget.js similarity index 69% rename from js/jquery.itop-tagset-widget.js rename to js/jquery.itop-set-widget.js index e9719644a..6797af6c0 100644 --- a/js/jquery.itop-tagset-widget.js +++ b/js/jquery.itop-set-widget.js @@ -41,6 +41,7 @@ * "label": "don't worry ;)" * } * ], + * "max_items_allowed": 20, * "partial_values": [], * "orig_value": [ * "critical" @@ -55,10 +56,10 @@ * * *

Needs js/selectize.js already loaded !! (https://github.com/selectize/selectize.js)
- * In the future we could use a solution like this : + * In the future we could use WebPack... Or a solution like this : * https://www.safaribooksonline.com/library/view/learning-javascript-design/9781449334840/ch13s09.html */ -$.widget('itop.tagset_widget', +$.widget('itop.set_widget', { // default options options: {isDebug: false}, @@ -71,23 +72,23 @@ $.widget('itop.tagset_widget', STATUS_ADDED: "added", STATUS_REMOVED: "removed", STATUS_NEUTRAL: "unchanged", - MAX_TAGS_ALLOWED: "max_tags_allowed", + MAX_ITEMS_ALLOWED_KEY: "max_items_allowed", possibleValues: null, partialValues: null, originalValue: null, /** will hold all interactions done : code as key and one of STATUS_* constant as value */ - tagSetCodesStatus: null, + setItemsCodesStatus: null, selectizeWidget: null, - maxTagsAllowed: null, + maxItemsAllowed: null, // the constructor _create: function () { var $this = this.element; this._initWidgetData($this.val()); - this._generateTagSetField($this); + this._generateSelectionWidget($this); }, // events bound via _bind are removed automatically @@ -102,44 +103,44 @@ $.widget('itop.tagset_widget', this.possibleValues = dataArray[this.POSSIBLE_VAL_KEY]; this.partialValues = ($.isArray(dataArray[this.PARTIAL_VAL_KEY])) ? dataArray[this.PARTIAL_VAL_KEY] : []; this.originalValue = dataArray[this.ORIG_VAL_KEY]; - this.maxTagsAllowed = dataArray[this.MAX_TAGS_ALLOWED]; - this.tagSetCodesStatus = {}; + this.maxItemsAllowed = dataArray[this.MAX_ITEMS_ALLOWED_KEY]; + this.setItemsCodesStatus = {}; }, - _generateTagSetField: function ($widgetElement) { + _generateSelectionWidget: function ($widgetElement) { var $parentElement = $widgetElement.parent(), - inputId = $widgetElement.attr("id") + "-tagset-values"; + inputId = $widgetElement.attr("id") + "-setwidget-values"; $parentElement.append(""); var $inputWidget = $("#" + inputId); - // create closure to have both tagset widget and Selectize instances available in callbacks + // create closure to have both set widget and Selectize instances available in callbacks // selectize instance could also be retrieve on the source input DOM node (selectize property) // I think this is much clearer this way ! - var tagSetWidget = this; + var setWidget = this; $inputWidget.selectize({ plugins: ['remove_button'], delimiter: ' ', - maxItems: this.maxTagsAllowed, + maxItems: this.maxItemsAllowed, hideSelected: true, valueField: 'code', labelField: 'label', searchField: 'label', options: this.possibleValues, create: false, - placeholder: Dict.S("Core:AttributeTagSet:placeholder"), + placeholder: Dict.S("Core:AttributeSet:placeholder"), onInitialize: function () { var selectizeWidget = this; - tagSetWidget._onInitialize(selectizeWidget); + setWidget._onInitialize(selectizeWidget); }, onItemAdd: function (value, $item) { var selectizeWidget = this; - tagSetWidget._onTagAdd(value, $item, selectizeWidget); + setWidget._onTagAdd(value, $item, selectizeWidget); }, onItemRemove: function (value) { var selectizeWidget = this; - tagSetWidget._onTagRemove(value, selectizeWidget); + setWidget._onTagRemove(value, selectizeWidget); } }); @@ -156,14 +157,14 @@ $.widget('itop.tagset_widget', widgetPublicData[this.PARTIAL_VAL_KEY] = this.partialValues; widgetPublicData[this.ORIG_VAL_KEY] = this.originalValue; - for (var tagSetCode in this.tagSetCodesStatus) { - var tagSetCodeStatus = this.tagSetCodesStatus[tagSetCode]; - switch (tagSetCodeStatus) { + for (var setItemCode in this.setItemsCodesStatus) { + var setItemCodeStatus = this.setItemsCodesStatus[setItemCode]; + switch (setItemCodeStatus) { case this.STATUS_ADDED: - addedValues.push(tagSetCode); + addedValues.push(setItemCode); break; case this.STATUS_REMOVED: - removedValues.push(tagSetCode); + removedValues.push(setItemCode); break; } } @@ -183,59 +184,59 @@ $.widget('itop.tagset_widget', /** * Updating items to have a specific rendering for partial codes.
- * At first I was thinking about using the Selectize render callback, but it is called before onItemAdd/onItemRemove :(
+ * At first I was thinking about using the Selectize render callback, but it is called before onItemAdd/onItemRemove :(
* Indeed as we only need to have partial items on first display, this callback is the right place O:) - * @param inputWidget Selectize object + * @param selectionWidget Selectize object * @private */ - _onInitialize: function (inputWidget) { + _onInitialize: function (selectionWidget) { if (this.options.isDebug) { console.debug("onInit", this); } - var tagSetWidget = this; - inputWidget.items.forEach(function (tagSetCode) { - if (tagSetWidget._isCodeInPartialValues(tagSetCode)) { - inputWidget.getItem(tagSetCode).addClass("partial-code"); + var setWidget = this; + selectionWidget.items.forEach(function (setItemCode) { + if (setWidget._isCodeInPartialValues(setItemCode)) { + selectionWidget.getItem(setItemCode).addClass("partial-code"); } }); }, - _onTagAdd: function (tagSetCode, $item, inputWidget) { + _onTagAdd: function (setItemCode, $item, inputWidget) { if (this.options.isDebug) { console.debug("tagAdd"); } - this.tagSetCodesStatus[tagSetCode] = this.STATUS_ADDED; + this.setItemsCodesStatus[setItemCode] = this.STATUS_ADDED; - if (this._isCodeInPartialValues(tagSetCode)) { - this.partialValues = this.partialValues.filter(item => (item !== tagSetCode)); + if (this._isCodeInPartialValues(setItemCode)) { + this.partialValues = this.partialValues.filter(item => (item !== setItemCode)); } else { - if (this.originalValue.indexOf(tagSetCode) !== -1) { + if (this.originalValue.indexOf(setItemCode) !== -1) { // do not add if was present initially and removed - this.tagSetCodesStatus[tagSetCode] = this.STATUS_NEUTRAL; + this.setItemsCodesStatus[setItemCode] = this.STATUS_NEUTRAL; } } this.refresh(); }, - _onTagRemove: function (tagSetCode, inputWidget) { - this.tagSetCodesStatus[tagSetCode] = this.STATUS_REMOVED; + _onTagRemove: function (setItemCode, inputWidget) { + this.setItemsCodesStatus[setItemCode] = this.STATUS_REMOVED; - if (this._isCodeInPartialValues(tagSetCode)) { + if (this._isCodeInPartialValues(setItemCode)) { // force rendering items again, otherwise partial class will be kept // can'be in the onItemAdd callback as it is called after the render callback... inputWidget.clearCache("item"); } - if (this.originalValue.indexOf(tagSetCode) === -1) { + if (this.originalValue.indexOf(setItemCode) === -1) { // do not remove if wasn't present initially - this.tagSetCodesStatus[tagSetCode] = this.STATUS_NEUTRAL; + this.setItemsCodesStatus[setItemCode] = this.STATUS_NEUTRAL; } this.refresh(); }, - _isCodeInPartialValues: function (tagSetCode) { - return (this.partialValues.indexOf(tagSetCode) >= 0); + _isCodeInPartialValues: function (setItemCode) { + return (this.partialValues.indexOf(setItemCode) >= 0); } }); \ No newline at end of file diff --git a/test/attributeset_widget_poc.html b/test/attributeset_widget_poc.html new file mode 100644 index 000000000..63c0b3e00 --- /dev/null +++ b/test/attributeset_widget_poc.html @@ -0,0 +1,96 @@ + + + + + + +AttributeSet fields widget test + + + + + + + + + + + + + + + + +

+
+
+
+
+
+ + +
+
+
+
+
+
+ + + + + + \ No newline at end of file diff --git a/test/tagset_widget_poc.html b/test/tagset_widget_poc.html deleted file mode 100644 index 509cb500e..000000000 --- a/test/tagset_widget_poc.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - TagSet fields widget test - - - - - - - - - - - - - - - - -
- - -
- - - - - - \ No newline at end of file