From 650ac4f6d45d925233dcc3c3fb92b3bb71bb8147 Mon Sep 17 00:00:00 2001 From: Lena Daxenbichler Date: Thu, 19 Sep 2024 09:58:33 +0200 Subject: [PATCH 01/17] add bs5 resources and config --- src/yafowil/widget/array/__init__.py | 44 +++++++++++ .../array/resources/bootstrap5/widget.css | 77 +++++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 src/yafowil/widget/array/resources/bootstrap5/widget.css diff --git a/src/yafowil/widget/array/__init__.py b/src/yafowil/widget/array/__init__.py index f7b05f8..4e61c2a 100644 --- a/src/yafowil/widget/array/__init__.py +++ b/src/yafowil/widget/array/__init__.py @@ -85,6 +85,34 @@ }] +############################################################################## +# Bootstrap 5 +############################################################################## + +# webresource ################################################################ + +bootstrap5_resources = wr.ResourceGroup( + name='yafowil.widget.array', + directory=resources_dir, + path='yafowil-array' +) +bootstrap5_resources.add(array_js) +bootstrap5_resources.add(wr.StyleResource( + name='yafowil-array-css', + directory=os.path.join(resources_dir, 'bootstrap5'), + path='yafowil-array/bootstrap5', + resource='widget.css' +)) + +# B/C resources ############################################################## + +bootstrap5_css = [{ + 'group': 'yafowil.widget.array.common', + 'resource': 'bootstrap5/widget.css', + 'order': 20, +}] + + ############################################################################## # Plone5 ############################################################################## @@ -147,6 +175,22 @@ def register(): bootstrap_resources ) + # Bootstrap 5 + factory.register_theme( + ['bootstrap5'], + widget_name, + resources_dir, + js=js, + css=bootstrap5_css + ) + + factory.register_resources( + ['bootstrap5'], + widget_name, + bootstrap5_resources + ) + + # Plone 5 factory.register_theme( 'plone5', diff --git a/src/yafowil/widget/array/resources/bootstrap5/widget.css b/src/yafowil/widget/array/resources/bootstrap5/widget.css new file mode 100644 index 0000000..0e30322 --- /dev/null +++ b/src/yafowil/widget/array/resources/bootstrap5/widget.css @@ -0,0 +1,77 @@ +/* yafowil.widget.array - bootstrap theme styles +.arraytemplate { + display: none; + } + + .icon-plus-sign, + .icon-minus-sign, + .icon-circle-arrow-up, + .icon-circle-arrow-down { + display: inline-block; + font-family: "Glyphicons Halflings"; + font-style: normal; + font-weight: 400; + line-height: 1; + margin-left: 2px; + position: relative; + top: 1px; + } + + .icon-plus-sign:before { + content: "\e081"; + } + + .icon-minus-sign:before { + content: "\e082"; + } + + .icon-circle-arrow-up:before { + content: "\e133"; + } + + .icon-circle-arrow-down:before { + content: "\e134"; + } + + .array table { + border-radius: 4px; + margin-bottom: 0; + } + .array table table { + border-right: #ddd 1px solid; + margin-top: 10px; + } + .array table table th { + padding-left: 0; + } + .array table td.widget { + padding: 0 0 10px 0; + } + .array table td.widget .form-group { + margin: 0; + } + .array table th { + vertical-align: middle; + } + .array table th.head_actions, + .array table td.actions { + width: 5.5em; + } + .array .array_actions { + display: inline-block; + margin-top: 0.6em; + padding-right: 0.45em; + width: 5.5em; + } + .array .array_actions a { + float: right; + background: none; + } + .array .array_actions a.array_row_up_disabled, .array .array_actions a.array_row_down_disabled { + opacity: 0.4; + filter: alpha(opacity=40); + } + .array .array_actions span { + color: var(--yafowil-accent-color, #0d6efd); + } + */ From 65f8891eb4be6ed75472477417acd043200f8a92 Mon Sep 17 00:00:00 2001 From: Lena Daxenbichler Date: Thu, 19 Sep 2024 12:23:57 +0200 Subject: [PATCH 02/17] update to bs5 --- js/rollup_bs5.conf.js | 47 ++++ js/src/bundle_bs5.js | 15 + js/src/widget_bs5.js | 257 ++++++++++++++++++ scripts/rollup_bs5.sh | 5 + scripts/styles.sh | 3 +- scss/widget_bootstrap5.scss | 78 ++++++ src/yafowil/widget/array/__init__.py | 12 +- .../array/resources/bootstrap5/widget.css | 134 ++++----- .../array/resources/bootstrap5/widget.js | 256 +++++++++++++++++ .../array/resources/bootstrap5/widget.min.js | 1 + src/yafowil/widget/array/widget.py | 13 +- 11 files changed, 738 insertions(+), 83 deletions(-) create mode 100644 js/rollup_bs5.conf.js create mode 100644 js/src/bundle_bs5.js create mode 100644 js/src/widget_bs5.js create mode 100755 scripts/rollup_bs5.sh create mode 100644 scss/widget_bootstrap5.scss create mode 100644 src/yafowil/widget/array/resources/bootstrap5/widget.js create mode 100644 src/yafowil/widget/array/resources/bootstrap5/widget.min.js diff --git a/js/rollup_bs5.conf.js b/js/rollup_bs5.conf.js new file mode 100644 index 0000000..8022908 --- /dev/null +++ b/js/rollup_bs5.conf.js @@ -0,0 +1,47 @@ +import cleanup from 'rollup-plugin-cleanup'; +import {terser} from 'rollup-plugin-terser'; + +const out_dir = 'src/yafowil/widget/array/resources/bootstrap5'; + +const outro = ` +window.yafowil = window.yafowil || {}; +window.yafowil.array = exports; +`; + +export default args => { + let conf = { + input: 'js/src/bundle_bs5.js', + plugins: [ + cleanup() + ], + output: [{ + name: 'yafowil_array', + file: `${out_dir}/widget.js`, + format: 'iife', + outro: outro, + globals: { + jquery: 'jQuery' + }, + interop: 'default' + }], + external: [ + 'jquery' + ] + }; + if (args.configDebug !== true) { + conf.output.push({ + name: 'yafowil_array', + file: `${out_dir}/widget.min.js`, + format: 'iife', + plugins: [ + terser() + ], + outro: outro, + globals: { + jquery: 'jQuery' + }, + interop: 'default' + }); + } + return conf; +}; diff --git a/js/src/bundle_bs5.js b/js/src/bundle_bs5.js new file mode 100644 index 0000000..7274669 --- /dev/null +++ b/js/src/bundle_bs5.js @@ -0,0 +1,15 @@ +import $ from 'jquery'; + +import {ArrayWidget} from './widget_bs5.js'; + +export * from './widget_bs5.js'; + +$(function() { + if (window.ts !== undefined) { + ts.ajax.register(ArrayWidget.initialize, true); + } else if (window.bdajax !== undefined) { + bdajax.register(ArrayWidget.initialize, true); + } else { + ArrayWidget.initialize(); + } +}); diff --git a/js/src/widget_bs5.js b/js/src/widget_bs5.js new file mode 100644 index 0000000..637b7ee --- /dev/null +++ b/js/src/widget_bs5.js @@ -0,0 +1,257 @@ +import $ from 'jquery'; + +// B/C. Deprecated. Use ``on_array_event`` +export let hooks = { + before_add: {}, + add: {}, + remove: {}, + before_up: {}, + up: {}, + before_down: {}, + down: {}, + index: {} +}; + +// global array subscribers, gets called from every array instance +let _array_subscribers = { + on_before_add: [], + on_add: [], + on_remove: [], + on_before_up: [], + on_up: [], + on_before_down: [], + on_down: [], + on_index: [] +} + +export function on_array_event(event, subscriber) { + _array_subscribers[event].push(subscriber) +} + +export function inside_template(elem) { + return elem.parents('.arraytemplate').length > 0 +} + +export class ArrayWidget { + + static initialize(context) { + $('div.array', context).each(function() { + let wrapper = $(this); + if (wrapper.attr('id').indexOf('-TEMPLATE') === -1) { + new ArrayWidget(wrapper); + } + }); + } + + constructor(wrapper) { + wrapper.data('yafowil-array', this); + this.wrapper = wrapper; + let table = $('> table', wrapper), + head_actions = $('> thead .array_actions', table), + add_handle = this.add_first_handle.bind(this); + this.table = table; + $('a.array_row_add', head_actions).off().on('click', add_handle); + this.bind_actions(); + } + + bind_actions() { + let actions_sel = '> tbody > tr > td.actions .array_actions', + row_actions = $(actions_sel, this.table), + add_handle = this.add_handle.bind(this), + remove_handle = this.remove_handle.bind(this), + up_handle = this.up_handle.bind(this), + down_handle = this.down_handle.bind(this); + this.mark_disabled(row_actions); + $('a.array_row_add', row_actions).off().on('click', add_handle); + $('a.array_row_remove', row_actions).off().on('click', remove_handle); + $('a.array_row_up', row_actions).off().on('click', up_handle); + $('a.array_row_down', row_actions).off().on('click', down_handle); + } + + mark_disabled(row_actions) { + $('a.array_row_up', row_actions) + .removeClass('array_row_up_disabled') + .first() + .addClass('array_row_up_disabled'); + $('a.array_row_down', row_actions) + .removeClass('array_row_down_disabled') + .last() + .addClass('array_row_down_disabled'); + } + + create_row() { + let css = this.wrapper.attr('class'); + let row = ''; + row += ''; + row += ''; + row += ''; + if (css.indexOf('array-static') === -1) { + row += ''; + row += '
'; + if (css.indexOf('array-add') > -1) { + row += ''; + row += ' '; + row += ''; + } + if (css.indexOf('array-remove') > -1) { + row += ''; + row += ' '; + row += ''; + } + if (css.indexOf('array-sort') > -1) { + row += ''; + row += ' '; + row += ''; + row += ''; + row += ' '; + row += ''; + } + row += '
'; + row += ''; + } + row += ''; + row = $(row); + let template = $('> .arraytemplate', this.wrapper).clone(); + $('.widget', row).append(template.children()); + return row; + } + + get_row(action) { + return $(action).parent().parent().parent(); + } + + get base_id() { + let id = this.wrapper.attr('id'); + return id.substring(6, id.length); + } + + trigger(event, ...args) { + let event_hooks = hooks[event.substring(3, event.length)]; + if (Object.entries(event_hooks).length) { + console.log( + 'Array hooks are deprecated. Use ``on_array_event`` instead.' + ); + for (let hook_name in event_hooks) { + console.log(` - ${hook_name}`); + event_hooks[hook_name].apply(null, args); + } + } + args.splice(0, 0, this); + for (let subscriber of _array_subscribers[event]) { + subscriber.apply(null, args); + } + } + + reset_indices(context) { + let index = 0, + base_id = this.base_id, + that = this, + row; + context.children().each(function() { + row = $(this); + that.set_row_index(row, base_id, index); + that.trigger('on_index', row, index); + index++; + }); + this.bind_actions(); + } + + set_row_index(node, base_id, index) { + let base_name = base_id.replace(/\-/g, '.'), + set_index = this.set_attr_index.bind(this), + that = this, + child; + node.children().each(function() { + child = $(this); + set_index(child, 'id', base_id, index, '-'); + set_index(child, 'for', base_id, index, '-'); + set_index(child, 'name', base_name, index, '.'); + that.set_row_index(child, base_id, index); + }); + } + + set_attr_index(node, attr, base, index, delim) { + let value = node.attr(attr); + if (value && value.indexOf(base) > -1) { + node.attr( + attr, + this.set_value_index(value, base, index, delim) + ); + } + } + + set_value_index(value, base, index, delim) { + let idx_0 = value.indexOf(base) + base.length + 1, + idx_1 = value.indexOf(delim, idx_0), + pre = value.substring(0, idx_0), + post = ''; + if (idx_1 > -1) { + post = value.substring(idx_1, value.length); + } + return pre + index + post; + } + + init_row(container, row) { + this.reset_indices(container); + ArrayWidget.initialize(row); + this.trigger('on_add', row); + } + + add_first_handle(evt) { + evt.preventDefault(); + let new_row = this.create_row(), + container = $('> tbody', this.table); + this.trigger('on_before_add', new_row, container); + container.prepend(new_row); + this.init_row(container, new_row); + } + + add_handle(evt) { + evt.preventDefault(); + let row = this.get_row(evt.currentTarget), + new_row = this.create_row(), + container = row.parent(); + this.trigger('on_before_add', new_row, container); + row.after(new_row); + this.init_row(container, new_row); + } + + remove_handle(evt) { + evt.preventDefault(); + let row = this.get_row(evt.currentTarget); + this.trigger('on_remove', row); + let container = row.parent(); + row.remove(); + this.reset_indices(container); + } + + up_handle(evt) { + evt.preventDefault(); + let row = this.get_row(evt.currentTarget); + this.trigger('on_before_up', row); + row.insertBefore(row.prev()); + this.reset_indices(row.parent()); + + row.addClass('row-moved'); + setTimeout(function() { + row.removeClass('row-moved'); + }, 1000); + + this.trigger('on_up', row); + } + + down_handle(evt) { + evt.preventDefault(); + let row = this.get_row(evt.currentTarget); + this.trigger('on_before_down', row); + row.insertAfter(row.next()); + this.reset_indices(row.parent()); + + row.addClass('row-moved'); + setTimeout(function() { + row.removeClass('row-moved'); + }, 1000); + + this.trigger('on_down', row); + } +} diff --git a/scripts/rollup_bs5.sh b/scripts/rollup_bs5.sh new file mode 100755 index 0000000..3e00d03 --- /dev/null +++ b/scripts/rollup_bs5.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# +# Create JS bundles. + +node_modules/rollup/dist/bin/rollup --config js/rollup_bs5.conf.js "$@" diff --git a/scripts/styles.sh b/scripts/styles.sh index 495c3e9..f890b96 100755 --- a/scripts/styles.sh +++ b/scripts/styles.sh @@ -6,4 +6,5 @@ TARGET_DIR="./src/yafowil/widget/array/resources" $SASS_BIN $SASS_DIR/widget_default.scss --no-source-map $TARGET_DIR/default/widget.css $SASS_BIN $SASS_DIR/widget_bootstrap.scss --no-source-map $TARGET_DIR/bootstrap/widget.css -$SASS_BIN $SASS_DIR/widget_plone5.scss --no-source-map $TARGET_DIR/plone5/widget.css \ No newline at end of file +$SASS_BIN $SASS_DIR/widget_plone5.scss --no-source-map $TARGET_DIR/plone5/widget.css +$SASS_BIN $SASS_DIR/widget_bootstrap5.scss --no-source-map $TARGET_DIR/bootstrap5/widget.css diff --git a/scss/widget_bootstrap5.scss b/scss/widget_bootstrap5.scss new file mode 100644 index 0000000..14ac880 --- /dev/null +++ b/scss/widget_bootstrap5.scss @@ -0,0 +1,78 @@ +/* yafowil.widget.array - bootstrap theme styles */ + +.arraytemplate { + display:none; +} + +.array { + table { + margin-bottom: 0; + + td.widget { + padding: 6px 0px 10px 10px; + + .form-group { + margin: 0; + } + } + + tr:last-of-type > td { + border: 0; + } + + th { + vertical-align: middle; + } + + thead { + height: 30px; + background-color: #0080ff1a; + + tr th { + padding-left: 10px; + border: 0; + } + } + + th.head_actions, + td.actions { + width: 5.5em; + } + + .field ~ .field { + margin-top: 10px; + } + } + + .array_actions { + display: inline-block; + width: 5.5em; + + a { + float:right; + background: none; + &.array_row_up_disabled, + &.array_row_down_disabled { + opacity:0.4; + filter:alpha(opacity=40); + } + } + span { + color: var(--yafowil-accent-color, #0d6efd); + } + } +} + +@keyframes boxShadowAnimation { + 0% { + } + 30% { + background: #0080ff1a; + } + 100% { + } +} + +.row-moved { + animation: boxShadowAnimation 1000ms; +} diff --git a/src/yafowil/widget/array/__init__.py b/src/yafowil/widget/array/__init__.py index 4e61c2a..c683c79 100644 --- a/src/yafowil/widget/array/__init__.py +++ b/src/yafowil/widget/array/__init__.py @@ -90,13 +90,18 @@ ############################################################################## # webresource ################################################################ - +bootstrap5_js = wr.ScriptResource( + name='yafowil-array-js', + depends='jquery-js', + resource='bootstrap5/widget.js', + compressed='bootstrap5/widget.min.js' +) bootstrap5_resources = wr.ResourceGroup( name='yafowil.widget.array', directory=resources_dir, path='yafowil-array' ) -bootstrap5_resources.add(array_js) +bootstrap5_resources.add(bootstrap5_js) bootstrap5_resources.add(wr.StyleResource( name='yafowil-array-css', directory=os.path.join(resources_dir, 'bootstrap5'), @@ -113,6 +118,7 @@ }] + ############################################################################## # Plone5 ############################################################################## @@ -180,7 +186,7 @@ def register(): ['bootstrap5'], widget_name, resources_dir, - js=js, + js=bootstrap5_js, css=bootstrap5_css ) diff --git a/src/yafowil/widget/array/resources/bootstrap5/widget.css b/src/yafowil/widget/array/resources/bootstrap5/widget.css index 0e30322..581902b 100644 --- a/src/yafowil/widget/array/resources/bootstrap5/widget.css +++ b/src/yafowil/widget/array/resources/bootstrap5/widget.css @@ -1,77 +1,59 @@ -/* yafowil.widget.array - bootstrap theme styles +/* yafowil.widget.array - bootstrap theme styles */ .arraytemplate { - display: none; - } - - .icon-plus-sign, - .icon-minus-sign, - .icon-circle-arrow-up, - .icon-circle-arrow-down { - display: inline-block; - font-family: "Glyphicons Halflings"; - font-style: normal; - font-weight: 400; - line-height: 1; - margin-left: 2px; - position: relative; - top: 1px; - } - - .icon-plus-sign:before { - content: "\e081"; - } - - .icon-minus-sign:before { - content: "\e082"; - } - - .icon-circle-arrow-up:before { - content: "\e133"; - } - - .icon-circle-arrow-down:before { - content: "\e134"; - } - - .array table { - border-radius: 4px; - margin-bottom: 0; - } - .array table table { - border-right: #ddd 1px solid; - margin-top: 10px; - } - .array table table th { - padding-left: 0; - } - .array table td.widget { - padding: 0 0 10px 0; - } - .array table td.widget .form-group { - margin: 0; - } - .array table th { - vertical-align: middle; - } - .array table th.head_actions, - .array table td.actions { - width: 5.5em; - } - .array .array_actions { - display: inline-block; - margin-top: 0.6em; - padding-right: 0.45em; - width: 5.5em; - } - .array .array_actions a { - float: right; - background: none; - } - .array .array_actions a.array_row_up_disabled, .array .array_actions a.array_row_down_disabled { - opacity: 0.4; - filter: alpha(opacity=40); - } - .array .array_actions span { - color: var(--yafowil-accent-color, #0d6efd); - } - */ + display: none; +} + +.array table { + margin-bottom: 0; +} +.array table td.widget { + padding: 6px 0px 10px 10px; +} +.array table td.widget .form-group { + margin: 0; +} +.array table tr:last-of-type > td { + border: 0; +} +.array table th { + vertical-align: middle; +} +.array table thead { + height: 30px; + background-color: rgba(0, 128, 255, 0.1019607843); +} +.array table thead tr th { + padding-left: 10px; + border: 0; +} +.array table th.head_actions, +.array table td.actions { + width: 5.5em; +} +.array table .field ~ .field { + margin-top: 10px; +} +.array .array_actions { + display: inline-block; + width: 5.5em; +} +.array .array_actions a { + float: right; + background: none; +} +.array .array_actions a.array_row_up_disabled, .array .array_actions a.array_row_down_disabled { + opacity: 0.4; + filter: alpha(opacity=40); +} +.array .array_actions span { + color: var(--yafowil-accent-color, #0d6efd); +} + +@keyframes boxShadowAnimation { + 30% { + background: rgba(0, 128, 255, 0.1019607843); + } +} +.row-moved { + animation: boxShadowAnimation 1000ms; +} diff --git a/src/yafowil/widget/array/resources/bootstrap5/widget.js b/src/yafowil/widget/array/resources/bootstrap5/widget.js new file mode 100644 index 0000000..0712f4e --- /dev/null +++ b/src/yafowil/widget/array/resources/bootstrap5/widget.js @@ -0,0 +1,256 @@ +var yafowil_array = (function (exports, $) { + 'use strict'; + + let hooks = { + before_add: {}, + add: {}, + remove: {}, + before_up: {}, + up: {}, + before_down: {}, + down: {}, + index: {} + }; + let _array_subscribers = { + on_before_add: [], + on_add: [], + on_remove: [], + on_before_up: [], + on_up: [], + on_before_down: [], + on_down: [], + on_index: [] + }; + function on_array_event(event, subscriber) { + _array_subscribers[event].push(subscriber); + } + function inside_template(elem) { + return elem.parents('.arraytemplate').length > 0 + } + class ArrayWidget { + static initialize(context) { + $('div.array', context).each(function() { + let wrapper = $(this); + if (wrapper.attr('id').indexOf('-TEMPLATE') === -1) { + new ArrayWidget(wrapper); + } + }); + } + constructor(wrapper) { + wrapper.data('yafowil-array', this); + this.wrapper = wrapper; + let table = $('> table', wrapper), + head_actions = $('> thead .array_actions', table), + add_handle = this.add_first_handle.bind(this); + this.table = table; + $('a.array_row_add', head_actions).off().on('click', add_handle); + this.bind_actions(); + } + bind_actions() { + let actions_sel = '> tbody > tr > td.actions .array_actions', + row_actions = $(actions_sel, this.table), + add_handle = this.add_handle.bind(this), + remove_handle = this.remove_handle.bind(this), + up_handle = this.up_handle.bind(this), + down_handle = this.down_handle.bind(this); + this.mark_disabled(row_actions); + $('a.array_row_add', row_actions).off().on('click', add_handle); + $('a.array_row_remove', row_actions).off().on('click', remove_handle); + $('a.array_row_up', row_actions).off().on('click', up_handle); + $('a.array_row_down', row_actions).off().on('click', down_handle); + } + mark_disabled(row_actions) { + $('a.array_row_up', row_actions) + .removeClass('array_row_up_disabled') + .first() + .addClass('array_row_up_disabled'); + $('a.array_row_down', row_actions) + .removeClass('array_row_down_disabled') + .last() + .addClass('array_row_down_disabled'); + } + create_row() { + let css = this.wrapper.attr('class'); + let row = ''; + row += ''; + row += ''; + row += ''; + if (css.indexOf('array-static') === -1) { + row += ''; + row += '
'; + if (css.indexOf('array-add') > -1) { + row += ''; + row += ' '; + row += ''; + } + if (css.indexOf('array-remove') > -1) { + row += ''; + row += ' '; + row += ''; + } + if (css.indexOf('array-sort') > -1) { + row += ''; + row += ' '; + row += ''; + row += ''; + row += ' '; + row += ''; + } + row += '
'; + row += ''; + } + row += ''; + row = $(row); + let template = $('> .arraytemplate', this.wrapper).clone(); + $('.widget', row).append(template.children()); + return row; + } + get_row(action) { + return $(action).parent().parent().parent(); + } + get base_id() { + let id = this.wrapper.attr('id'); + return id.substring(6, id.length); + } + trigger(event, ...args) { + let event_hooks = hooks[event.substring(3, event.length)]; + if (Object.entries(event_hooks).length) { + console.log( + 'Array hooks are deprecated. Use ``on_array_event`` instead.' + ); + for (let hook_name in event_hooks) { + console.log(` - ${hook_name}`); + event_hooks[hook_name].apply(null, args); + } + } + args.splice(0, 0, this); + for (let subscriber of _array_subscribers[event]) { + subscriber.apply(null, args); + } + } + reset_indices(context) { + let index = 0, + base_id = this.base_id, + that = this, + row; + context.children().each(function() { + row = $(this); + that.set_row_index(row, base_id, index); + that.trigger('on_index', row, index); + index++; + }); + this.bind_actions(); + } + set_row_index(node, base_id, index) { + let base_name = base_id.replace(/\-/g, '.'), + set_index = this.set_attr_index.bind(this), + that = this, + child; + node.children().each(function() { + child = $(this); + set_index(child, 'id', base_id, index, '-'); + set_index(child, 'for', base_id, index, '-'); + set_index(child, 'name', base_name, index, '.'); + that.set_row_index(child, base_id, index); + }); + } + set_attr_index(node, attr, base, index, delim) { + let value = node.attr(attr); + if (value && value.indexOf(base) > -1) { + node.attr( + attr, + this.set_value_index(value, base, index, delim) + ); + } + } + set_value_index(value, base, index, delim) { + let idx_0 = value.indexOf(base) + base.length + 1, + idx_1 = value.indexOf(delim, idx_0), + pre = value.substring(0, idx_0), + post = ''; + if (idx_1 > -1) { + post = value.substring(idx_1, value.length); + } + return pre + index + post; + } + init_row(container, row) { + this.reset_indices(container); + ArrayWidget.initialize(row); + this.trigger('on_add', row); + } + add_first_handle(evt) { + evt.preventDefault(); + let new_row = this.create_row(), + container = $('> tbody', this.table); + this.trigger('on_before_add', new_row, container); + container.prepend(new_row); + this.init_row(container, new_row); + } + add_handle(evt) { + evt.preventDefault(); + let row = this.get_row(evt.currentTarget), + new_row = this.create_row(), + container = row.parent(); + this.trigger('on_before_add', new_row, container); + row.after(new_row); + this.init_row(container, new_row); + } + remove_handle(evt) { + evt.preventDefault(); + let row = this.get_row(evt.currentTarget); + this.trigger('on_remove', row); + let container = row.parent(); + row.remove(); + this.reset_indices(container); + } + up_handle(evt) { + evt.preventDefault(); + let row = this.get_row(evt.currentTarget); + this.trigger('on_before_up', row); + row.insertBefore(row.prev()); + this.reset_indices(row.parent()); + row.addClass('row-moved'); + setTimeout(function() { + row.removeClass('row-moved'); + }, 1000); + this.trigger('on_up', row); + } + down_handle(evt) { + evt.preventDefault(); + let row = this.get_row(evt.currentTarget); + this.trigger('on_before_down', row); + row.insertAfter(row.next()); + this.reset_indices(row.parent()); + row.addClass('row-moved'); + setTimeout(function() { + row.removeClass('row-moved'); + }, 1000); + this.trigger('on_down', row); + } + } + + $(function() { + if (window.ts !== undefined) { + ts.ajax.register(ArrayWidget.initialize, true); + } else if (window.bdajax !== undefined) { + bdajax.register(ArrayWidget.initialize, true); + } else { + ArrayWidget.initialize(); + } + }); + + exports.ArrayWidget = ArrayWidget; + exports.hooks = hooks; + exports.inside_template = inside_template; + exports.on_array_event = on_array_event; + + Object.defineProperty(exports, '__esModule', { value: true }); + + + window.yafowil = window.yafowil || {}; + window.yafowil.array = exports; + + + return exports; + +})({}, jQuery); diff --git a/src/yafowil/widget/array/resources/bootstrap5/widget.min.js b/src/yafowil/widget/array/resources/bootstrap5/widget.min.js new file mode 100644 index 0000000..0c4e6f7 --- /dev/null +++ b/src/yafowil/widget/array/resources/bootstrap5/widget.min.js @@ -0,0 +1 @@ +var yafowil_array=function(e,r){"use strict";let t={before_add:{},add:{},remove:{},before_up:{},up:{},before_down:{},down:{},index:{}},a={on_before_add:[],on_add:[],on_remove:[],on_before_up:[],on_up:[],on_before_down:[],on_down:[],on_index:[]};class i{static initialize(e){r("div.array",e).each((function(){let e=r(this);-1===e.attr("id").indexOf("-TEMPLATE")&&new i(e)}))}constructor(e){e.data("yafowil-array",this),this.wrapper=e;let t=r("> table",e),a=r("> thead .array_actions",t),i=this.add_first_handle.bind(this);this.table=t,r("a.array_row_add",a).off().on("click",i),this.bind_actions()}bind_actions(){let e=r("> tbody > tr > td.actions .array_actions",this.table),t=this.add_handle.bind(this),a=this.remove_handle.bind(this),i=this.up_handle.bind(this),n=this.down_handle.bind(this);this.mark_disabled(e),r("a.array_row_add",e).off().on("click",t),r("a.array_row_remove",e).off().on("click",a),r("a.array_row_up",e).off().on("click",i),r("a.array_row_down",e).off().on("click",n)}mark_disabled(e){r("a.array_row_up",e).removeClass("array_row_up_disabled").first().addClass("array_row_up_disabled"),r("a.array_row_down",e).removeClass("array_row_down_disabled").last().addClass("array_row_down_disabled")}create_row(){let e=this.wrapper.attr("class"),t="";t+="",t+='',t+="",-1===e.indexOf("array-static")&&(t+='',t+='
',e.indexOf("array-add")>-1&&(t+='',t+=' ',t+=""),e.indexOf("array-remove")>-1&&(t+='',t+=' ',t+=""),e.indexOf("array-sort")>-1&&(t+='',t+=' ',t+="",t+='',t+=' ',t+=""),t+="
",t+=""),t+="",t=r(t);let a=r("> .arraytemplate",this.wrapper).clone();return r(".widget",t).append(a.children()),t}get_row(e){return r(e).parent().parent().parent()}get base_id(){let e=this.wrapper.attr("id");return e.substring(6,e.length)}trigger(e,...r){let i=t[e.substring(3,e.length)];if(Object.entries(i).length){console.log("Array hooks are deprecated. Use ``on_array_event`` instead.");for(let e in i)console.log(` - ${e}`),i[e].apply(null,r)}r.splice(0,0,this);for(let t of a[e])t.apply(null,r)}reset_indices(e){let t,a=0,i=this.base_id,n=this;e.children().each((function(){t=r(this),n.set_row_index(t,i,a),n.trigger("on_index",t,a),a++})),this.bind_actions()}set_row_index(e,t,a){let i,n=t.replace(/\-/g,"."),s=this.set_attr_index.bind(this),o=this;e.children().each((function(){i=r(this),s(i,"id",t,a,"-"),s(i,"for",t,a,"-"),s(i,"name",n,a,"."),o.set_row_index(i,t,a)}))}set_attr_index(e,r,t,a,i){let n=e.attr(r);n&&n.indexOf(t)>-1&&e.attr(r,this.set_value_index(n,t,a,i))}set_value_index(e,r,t,a){let i=e.indexOf(r)+r.length+1,n=e.indexOf(a,i),s=e.substring(0,i),o="";return n>-1&&(o=e.substring(n,e.length)),s+t+o}init_row(e,r){this.reset_indices(e),i.initialize(r),this.trigger("on_add",r)}add_first_handle(e){e.preventDefault();let t=this.create_row(),a=r("> tbody",this.table);this.trigger("on_before_add",t,a),a.prepend(t),this.init_row(a,t)}add_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget),t=this.create_row(),a=r.parent();this.trigger("on_before_add",t,a),r.after(t),this.init_row(a,t)}remove_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget);this.trigger("on_remove",r);let t=r.parent();r.remove(),this.reset_indices(t)}up_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget);this.trigger("on_before_up",r),r.insertBefore(r.prev()),this.reset_indices(r.parent()),r.addClass("row-moved"),setTimeout((function(){r.removeClass("row-moved")}),1e3),this.trigger("on_up",r)}down_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget);this.trigger("on_before_down",r),r.insertAfter(r.next()),this.reset_indices(r.parent()),r.addClass("row-moved"),setTimeout((function(){r.removeClass("row-moved")}),1e3),this.trigger("on_down",r)}}return r((function(){void 0!==window.ts?ts.ajax.register(i.initialize,!0):void 0!==window.bdajax?bdajax.register(i.initialize,!0):i.initialize()})),e.ArrayWidget=i,e.hooks=t,e.inside_template=function(e){return e.parents(".arraytemplate").length>0},e.on_array_event=function(e,r){a[e].push(r)},Object.defineProperty(e,"__esModule",{value:!0}),window.yafowil=window.yafowil||{},window.yafowil.array=e,e}({},jQuery); diff --git a/src/yafowil/widget/array/widget.py b/src/yafowil/widget/array/widget.py index 14709f3..6db7281 100644 --- a/src/yafowil/widget/array/widget.py +++ b/src/yafowil/widget/array/widget.py @@ -10,7 +10,7 @@ from yafowil.utils import cssclasses from yafowil.utils import cssid from yafowil.utils import managedprops - +from yafowil.base import factory @managedprops(*css_managed_props) def array_display_proxy_renderer(widget, data): @@ -44,15 +44,22 @@ def array_display_proxy_renderer(widget, data): 'up': 'icon-circle-arrow-up', 'down': 'icon-circle-arrow-down', } +BS_ICON = { + 'add': 'bi-plus-circle-fill', + 'remove': 'bi-dash-circle-fill', + 'up': 'bi-arrow-up-circle-fill', + 'down': 'bi-arrow-down-circle-fill', +} def actions_renderer(widget, data): tag = data.tag actions = list() + icons = BS_ICON if factory.theme == 'bootstrap5' else ICON_CSS for key in ['add', 'remove', 'up', 'down']: if widget.attrs.get(key): class_ = 'array_row_%s' % key - icon = tag('span', ' ', class_=ICON_CSS[key]) + icon = tag('span', ' ', class_=icons[key]) action = tag('a', icon, href='#', class_=class_) actions.append(action) kw = dict(class_='array_actions') @@ -299,7 +306,7 @@ def array_display_renderer(widget, data): `_. """ -factory.defaults['array.class'] = 'array' +factory.defaults['array.class'] = 'array card' factory.defaults['array.required'] = False From d4d61221af6244b1527ea880e5fbcadf1977d4a1 Mon Sep 17 00:00:00 2001 From: Lena Daxenbichler Date: Thu, 19 Sep 2024 13:37:42 +0200 Subject: [PATCH 03/17] some edge case fixes --- package.json | 12 ++++++------ scss/widget_bootstrap5.scss | 5 +++++ .../widget/array/resources/bootstrap5/widget.css | 4 ++++ src/yafowil/widget/array/widget.py | 2 +- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index cad658f..454db7e 100644 --- a/package.json +++ b/package.json @@ -4,15 +4,15 @@ "karma-test:coverage": "node js/karma-coverage.js" }, "devDependencies": { - "karma": "^6.4.1", - "karma-chrome-launcher": "^3.1.1", - "karma-coverage": "^2.2.0", + "karma": "^6.4.4", + "karma-chrome-launcher": "^3.2.0", + "karma-coverage": "^2.2.1", "karma-module-resolver-preprocessor": "^1.1.3", - "karma-qunit": "^4.1.2", - "qunit": "^2.19.4", + "karma-qunit": "^4.2.1", + "qunit": "^2.22.0", "rollup": "^2.79.1", "rollup-plugin-cleanup": "^3.2.1", "rollup-plugin-terser": "^7.0.2", - "sass": "^1.58.3" + "sass": "^1.79.1" } } diff --git a/scss/widget_bootstrap5.scss b/scss/widget_bootstrap5.scss index 14ac880..395e092 100644 --- a/scss/widget_bootstrap5.scss +++ b/scss/widget_bootstrap5.scss @@ -22,6 +22,11 @@ th { vertical-align: middle; + background: none; + } + + td { + background: none; } thead { diff --git a/src/yafowil/widget/array/resources/bootstrap5/widget.css b/src/yafowil/widget/array/resources/bootstrap5/widget.css index 581902b..639abb3 100644 --- a/src/yafowil/widget/array/resources/bootstrap5/widget.css +++ b/src/yafowil/widget/array/resources/bootstrap5/widget.css @@ -17,6 +17,10 @@ } .array table th { vertical-align: middle; + background: none; +} +.array table td { + background: none; } .array table thead { height: 30px; diff --git a/src/yafowil/widget/array/widget.py b/src/yafowil/widget/array/widget.py index 6db7281..b3a19d6 100644 --- a/src/yafowil/widget/array/widget.py +++ b/src/yafowil/widget/array/widget.py @@ -78,7 +78,7 @@ def actions_renderer(widget, data): def array_builder(widget, factory): table = widget['table'] = factory('table', props={ 'structural': True, - 'class': widget.attrs['table_class'], + 'class': 'table table-sm ' + widget.attrs['table_class'], }) head = table['head'] = factory('thead', props={ 'structural': True, From bb94d403f9211c5f369d4448d8ae8eb8bae888c5 Mon Sep 17 00:00:00 2001 From: Lena Daxenbichler Date: Fri, 20 Sep 2024 09:16:14 +0200 Subject: [PATCH 04/17] no more bad practice --- src/yafowil/widget/array/widget.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/yafowil/widget/array/widget.py b/src/yafowil/widget/array/widget.py index b3a19d6..6db7281 100644 --- a/src/yafowil/widget/array/widget.py +++ b/src/yafowil/widget/array/widget.py @@ -78,7 +78,7 @@ def actions_renderer(widget, data): def array_builder(widget, factory): table = widget['table'] = factory('table', props={ 'structural': True, - 'class': 'table table-sm ' + widget.attrs['table_class'], + 'class': widget.attrs['table_class'], }) head = table['head'] = factory('thead', props={ 'structural': True, From be960b1e8a201e0b3f88460b56ef434eed914166 Mon Sep 17 00:00:00 2001 From: Lena Daxenbichler Date: Fri, 20 Sep 2024 09:47:23 +0200 Subject: [PATCH 05/17] add margins between array actions --- scss/widget_bootstrap5.scss | 14 ++++++++------ .../widget/array/resources/bootstrap5/widget.css | 5 +++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/scss/widget_bootstrap5.scss b/scss/widget_bootstrap5.scss index 395e092..b4d5827 100644 --- a/scss/widget_bootstrap5.scss +++ b/scss/widget_bootstrap5.scss @@ -53,14 +53,16 @@ display: inline-block; width: 5.5em; - a { + > a { float:right; background: none; - &.array_row_up_disabled, - &.array_row_down_disabled { - opacity:0.4; - filter:alpha(opacity=40); - } + margin-left: 2px; + + &.array_row_up_disabled, + &.array_row_down_disabled { + opacity:0.4; + filter:alpha(opacity=40); + } } span { color: var(--yafowil-accent-color, #0d6efd); diff --git a/src/yafowil/widget/array/resources/bootstrap5/widget.css b/src/yafowil/widget/array/resources/bootstrap5/widget.css index 639abb3..50c488d 100644 --- a/src/yafowil/widget/array/resources/bootstrap5/widget.css +++ b/src/yafowil/widget/array/resources/bootstrap5/widget.css @@ -41,11 +41,12 @@ display: inline-block; width: 5.5em; } -.array .array_actions a { +.array .array_actions > a { float: right; background: none; + margin-left: 2px; } -.array .array_actions a.array_row_up_disabled, .array .array_actions a.array_row_down_disabled { +.array .array_actions > a.array_row_up_disabled, .array .array_actions > a.array_row_down_disabled { opacity: 0.4; filter: alpha(opacity=40); } From 3e5f600db1a8851464e25a95b6f60bccb957425d Mon Sep 17 00:00:00 2001 From: Lena Daxenbichler Date: Mon, 23 Sep 2024 10:43:27 +0200 Subject: [PATCH 06/17] combine js logic in array.js --- js/rollup.conf.js | 49 +++- js/rollup_bs5.conf.js | 47 ---- js/src/{widget.js => array.js} | 57 +--- js/src/{ => bootstrap5}/bundle.js | 0 js/src/bootstrap5/widget.js | 73 +++++ js/src/{bundle_bs5.js => default/bundle.js} | 4 +- js/src/default/widget.js | 57 ++++ js/src/widget_bs5.js | 257 ------------------ scripts/rollup_bs5.sh | 5 - src/yafowil/widget/array/__init__.py | 7 +- .../array/resources/bootstrap5/widget.js | 113 ++++---- .../array/resources/bootstrap5/widget.min.js | 2 +- .../array/resources/{ => default}/widget.js | 97 ++++--- .../array/resources/default/widget.min.js | 1 + .../widget/array/resources/widget.min.js | 1 - 15 files changed, 310 insertions(+), 460 deletions(-) delete mode 100644 js/rollup_bs5.conf.js rename js/src/{widget.js => array.js} (82%) rename js/src/{ => bootstrap5}/bundle.js (100%) create mode 100644 js/src/bootstrap5/widget.js rename js/src/{bundle_bs5.js => default/bundle.js} (78%) create mode 100644 js/src/default/widget.js delete mode 100644 js/src/widget_bs5.js delete mode 100755 scripts/rollup_bs5.sh rename src/yafowil/widget/array/resources/{ => default}/widget.js (90%) create mode 100644 src/yafowil/widget/array/resources/default/widget.min.js delete mode 100644 src/yafowil/widget/array/resources/widget.min.js diff --git a/js/rollup.conf.js b/js/rollup.conf.js index 799a5d0..f30268d 100644 --- a/js/rollup.conf.js +++ b/js/rollup.conf.js @@ -1,7 +1,8 @@ import cleanup from 'rollup-plugin-cleanup'; import {terser} from 'rollup-plugin-terser'; -const out_dir = 'src/yafowil/widget/array/resources'; +const out_dir = 'src/yafowil/widget/array/resources/default'; +const out_dir_bs5 = 'src/yafowil/widget/array/resources/bootstrap5'; const outro = ` window.yafowil = window.yafowil || {}; @@ -9,8 +10,9 @@ window.yafowil.array = exports; `; export default args => { - let conf = { - input: 'js/src/bundle.js', + // default + let conf1 = { + input: 'js/src/default/bundle.js', plugins: [ cleanup() ], @@ -29,7 +31,7 @@ export default args => { ] }; if (args.configDebug !== true) { - conf.output.push({ + conf1.output.push({ name: 'yafowil_array', file: `${out_dir}/widget.min.js`, format: 'iife', @@ -43,5 +45,42 @@ export default args => { interop: 'default' }); } - return conf; + + // Bootstrap5 + let conf2 = { + input: 'js/src/bootstrap5/bundle.js', + plugins: [ + cleanup() + ], + output: [{ + name: 'yafowil_array', + file: `${out_dir_bs5}/widget.js`, + format: 'iife', + outro: outro, + globals: { + jquery: 'jQuery' + }, + interop: 'default' + }], + external: [ + 'jquery' + ] + }; + if (args.configDebug !== true) { + conf2.output.push({ + name: 'yafowil_array', + file: `${out_dir_bs5}/widget.min.js`, + format: 'iife', + plugins: [ + terser() + ], + outro: outro, + globals: { + jquery: 'jQuery' + }, + interop: 'default' + }); + } + + return [conf1, conf2]; }; diff --git a/js/rollup_bs5.conf.js b/js/rollup_bs5.conf.js deleted file mode 100644 index 8022908..0000000 --- a/js/rollup_bs5.conf.js +++ /dev/null @@ -1,47 +0,0 @@ -import cleanup from 'rollup-plugin-cleanup'; -import {terser} from 'rollup-plugin-terser'; - -const out_dir = 'src/yafowil/widget/array/resources/bootstrap5'; - -const outro = ` -window.yafowil = window.yafowil || {}; -window.yafowil.array = exports; -`; - -export default args => { - let conf = { - input: 'js/src/bundle_bs5.js', - plugins: [ - cleanup() - ], - output: [{ - name: 'yafowil_array', - file: `${out_dir}/widget.js`, - format: 'iife', - outro: outro, - globals: { - jquery: 'jQuery' - }, - interop: 'default' - }], - external: [ - 'jquery' - ] - }; - if (args.configDebug !== true) { - conf.output.push({ - name: 'yafowil_array', - file: `${out_dir}/widget.min.js`, - format: 'iife', - plugins: [ - terser() - ], - outro: outro, - globals: { - jquery: 'jQuery' - }, - interop: 'default' - }); - } - return conf; -}; diff --git a/js/src/widget.js b/js/src/array.js similarity index 82% rename from js/src/widget.js rename to js/src/array.js index eac7fdc..f90cf55 100644 --- a/js/src/widget.js +++ b/js/src/array.js @@ -1,47 +1,6 @@ import $ from 'jquery'; -// B/C. Deprecated. Use ``on_array_event`` -export let hooks = { - before_add: {}, - add: {}, - remove: {}, - before_up: {}, - up: {}, - before_down: {}, - down: {}, - index: {} -}; - -// global array subscribers, gets called from every array instance -let _array_subscribers = { - on_before_add: [], - on_add: [], - on_remove: [], - on_before_up: [], - on_up: [], - on_before_down: [], - on_down: [], - on_index: [] -} - -export function on_array_event(event, subscriber) { - _array_subscribers[event].push(subscriber) -} - -export function inside_template(elem) { - return elem.parents('.arraytemplate').length > 0 -} - -export class ArrayWidget { - - static initialize(context) { - $('div.array', context).each(function() { - let wrapper = $(this); - if (wrapper.attr('id').indexOf('-TEMPLATE') === -1) { - new ArrayWidget(wrapper); - } - }); - } +export class ArrayBase { constructor(wrapper) { wrapper.data('yafowil-array', this); @@ -90,20 +49,20 @@ export class ArrayWidget { row += '
'; if (css.indexOf('array-add') > -1) { row += ''; - row += ' '; + row += ` `; row += ''; } if (css.indexOf('array-remove') > -1) { row += ''; - row += ' '; + row += ` `; row += ''; } if (css.indexOf('array-sort') > -1) { row += ''; - row += ' '; + row += ` `; row += ''; row += ''; - row += ' '; + row += ` `; row += ''; } row += '
'; @@ -126,7 +85,7 @@ export class ArrayWidget { } trigger(event, ...args) { - let event_hooks = hooks[event.substring(3, event.length)]; + let event_hooks = this.hooks[event.substring(3, event.length)]; if (Object.entries(event_hooks).length) { console.log( 'Array hooks are deprecated. Use ``on_array_event`` instead.' @@ -137,7 +96,7 @@ export class ArrayWidget { } } args.splice(0, 0, this); - for (let subscriber of _array_subscribers[event]) { + for (let subscriber of this._array_subscribers[event]) { subscriber.apply(null, args); } } @@ -193,7 +152,7 @@ export class ArrayWidget { init_row(container, row) { this.reset_indices(container); - ArrayWidget.initialize(row); + this.array_widget.initialize(row); this.trigger('on_add', row); } diff --git a/js/src/bundle.js b/js/src/bootstrap5/bundle.js similarity index 100% rename from js/src/bundle.js rename to js/src/bootstrap5/bundle.js diff --git a/js/src/bootstrap5/widget.js b/js/src/bootstrap5/widget.js new file mode 100644 index 0000000..5c91e10 --- /dev/null +++ b/js/src/bootstrap5/widget.js @@ -0,0 +1,73 @@ +import $ from 'jquery'; +import {ArrayBase} from '../array.js'; + +// B/C. Deprecated. Use ``on_array_event`` +export let hooks = { + before_add: {}, + add: {}, + remove: {}, + before_up: {}, + up: {}, + before_down: {}, + down: {}, + index: {} +}; + +// global array subscribers, gets called from every array instance +let _array_subscribers = { + on_before_add: [], + on_add: [], + on_remove: [], + on_before_up: [], + on_up: [], + on_before_down: [], + on_down: [], + on_index: [] +} + +export function on_array_event(event, subscriber) { + _array_subscribers[event].push(subscriber) +} + +export function inside_template(elem) { + return elem.parents('.arraytemplate').length > 0 +} + +export class ArrayWidget extends ArrayBase { + + static initialize(context) { + $('div.array', context).each(function() { + let wrapper = $(this); + if (wrapper.attr('id').indexOf('-TEMPLATE') === -1) { + new ArrayWidget(wrapper); + } + }); + } + + constructor(wrapper) { + super(wrapper); + this.hooks = hooks; + this._array_subscribers = _array_subscribers; + this.array_widget = ArrayWidget; + this.icon_add = 'bi-plus-circle-fill'; + this.icon_remove = 'bi-dash-circle-fill'; + this.icon_up = 'bi-arrow-up-circle-fill'; + this.icon_down = 'bi-arrow-down-circle-fill'; + } + + up_handle(evt) { + super.up_handle(evt); + row.addClass('row-moved'); + setTimeout(function() { + row.removeClass('row-moved'); + }, 1000); + } + + down_handle(evt) { + super.down_handle(evt); + row.addClass('row-moved'); + setTimeout(function() { + row.removeClass('row-moved'); + }, 1000); + } +} diff --git a/js/src/bundle_bs5.js b/js/src/default/bundle.js similarity index 78% rename from js/src/bundle_bs5.js rename to js/src/default/bundle.js index 7274669..464f2c9 100644 --- a/js/src/bundle_bs5.js +++ b/js/src/default/bundle.js @@ -1,8 +1,8 @@ import $ from 'jquery'; -import {ArrayWidget} from './widget_bs5.js'; +import {ArrayWidget} from './widget.js'; -export * from './widget_bs5.js'; +export * from './widget.js'; $(function() { if (window.ts !== undefined) { diff --git a/js/src/default/widget.js b/js/src/default/widget.js new file mode 100644 index 0000000..ac9c949 --- /dev/null +++ b/js/src/default/widget.js @@ -0,0 +1,57 @@ +import $ from 'jquery'; +import {ArrayBase} from '../array.js'; + +// B/C. Deprecated. Use ``on_array_event`` +export let hooks = { + before_add: {}, + add: {}, + remove: {}, + before_up: {}, + up: {}, + before_down: {}, + down: {}, + index: {} +}; + +// global array subscribers, gets called from every array instance +let _array_subscribers = { + on_before_add: [], + on_add: [], + on_remove: [], + on_before_up: [], + on_up: [], + on_before_down: [], + on_down: [], + on_index: [] +} + +export function on_array_event(event, subscriber) { + _array_subscribers[event].push(subscriber) +} + +export function inside_template(elem) { + return elem.parents('.arraytemplate').length > 0 +} + +export class ArrayWidget extends ArrayBase { + + static initialize(context) { + $('div.array', context).each(function() { + let wrapper = $(this); + if (wrapper.attr('id').indexOf('-TEMPLATE') === -1) { + new ArrayWidget(wrapper); + } + }); + } + + constructor(wrapper) { + super(wrapper); + this.hooks = hooks; + this._array_subscribers = _array_subscribers; + this.array_widget = ArrayWidget; + this.icon_add = 'icon-plus-sign'; + this.icon_remove = 'icon-minus-sign'; + this.icon_up = 'icon-circle-arrow-up'; + this.icon_down = 'icon-circle-arrow-down'; + } +} diff --git a/js/src/widget_bs5.js b/js/src/widget_bs5.js deleted file mode 100644 index 637b7ee..0000000 --- a/js/src/widget_bs5.js +++ /dev/null @@ -1,257 +0,0 @@ -import $ from 'jquery'; - -// B/C. Deprecated. Use ``on_array_event`` -export let hooks = { - before_add: {}, - add: {}, - remove: {}, - before_up: {}, - up: {}, - before_down: {}, - down: {}, - index: {} -}; - -// global array subscribers, gets called from every array instance -let _array_subscribers = { - on_before_add: [], - on_add: [], - on_remove: [], - on_before_up: [], - on_up: [], - on_before_down: [], - on_down: [], - on_index: [] -} - -export function on_array_event(event, subscriber) { - _array_subscribers[event].push(subscriber) -} - -export function inside_template(elem) { - return elem.parents('.arraytemplate').length > 0 -} - -export class ArrayWidget { - - static initialize(context) { - $('div.array', context).each(function() { - let wrapper = $(this); - if (wrapper.attr('id').indexOf('-TEMPLATE') === -1) { - new ArrayWidget(wrapper); - } - }); - } - - constructor(wrapper) { - wrapper.data('yafowil-array', this); - this.wrapper = wrapper; - let table = $('> table', wrapper), - head_actions = $('> thead .array_actions', table), - add_handle = this.add_first_handle.bind(this); - this.table = table; - $('a.array_row_add', head_actions).off().on('click', add_handle); - this.bind_actions(); - } - - bind_actions() { - let actions_sel = '> tbody > tr > td.actions .array_actions', - row_actions = $(actions_sel, this.table), - add_handle = this.add_handle.bind(this), - remove_handle = this.remove_handle.bind(this), - up_handle = this.up_handle.bind(this), - down_handle = this.down_handle.bind(this); - this.mark_disabled(row_actions); - $('a.array_row_add', row_actions).off().on('click', add_handle); - $('a.array_row_remove', row_actions).off().on('click', remove_handle); - $('a.array_row_up', row_actions).off().on('click', up_handle); - $('a.array_row_down', row_actions).off().on('click', down_handle); - } - - mark_disabled(row_actions) { - $('a.array_row_up', row_actions) - .removeClass('array_row_up_disabled') - .first() - .addClass('array_row_up_disabled'); - $('a.array_row_down', row_actions) - .removeClass('array_row_down_disabled') - .last() - .addClass('array_row_down_disabled'); - } - - create_row() { - let css = this.wrapper.attr('class'); - let row = ''; - row += ''; - row += ''; - row += ''; - if (css.indexOf('array-static') === -1) { - row += ''; - row += '
'; - if (css.indexOf('array-add') > -1) { - row += ''; - row += ' '; - row += ''; - } - if (css.indexOf('array-remove') > -1) { - row += ''; - row += ' '; - row += ''; - } - if (css.indexOf('array-sort') > -1) { - row += ''; - row += ' '; - row += ''; - row += ''; - row += ' '; - row += ''; - } - row += '
'; - row += ''; - } - row += ''; - row = $(row); - let template = $('> .arraytemplate', this.wrapper).clone(); - $('.widget', row).append(template.children()); - return row; - } - - get_row(action) { - return $(action).parent().parent().parent(); - } - - get base_id() { - let id = this.wrapper.attr('id'); - return id.substring(6, id.length); - } - - trigger(event, ...args) { - let event_hooks = hooks[event.substring(3, event.length)]; - if (Object.entries(event_hooks).length) { - console.log( - 'Array hooks are deprecated. Use ``on_array_event`` instead.' - ); - for (let hook_name in event_hooks) { - console.log(` - ${hook_name}`); - event_hooks[hook_name].apply(null, args); - } - } - args.splice(0, 0, this); - for (let subscriber of _array_subscribers[event]) { - subscriber.apply(null, args); - } - } - - reset_indices(context) { - let index = 0, - base_id = this.base_id, - that = this, - row; - context.children().each(function() { - row = $(this); - that.set_row_index(row, base_id, index); - that.trigger('on_index', row, index); - index++; - }); - this.bind_actions(); - } - - set_row_index(node, base_id, index) { - let base_name = base_id.replace(/\-/g, '.'), - set_index = this.set_attr_index.bind(this), - that = this, - child; - node.children().each(function() { - child = $(this); - set_index(child, 'id', base_id, index, '-'); - set_index(child, 'for', base_id, index, '-'); - set_index(child, 'name', base_name, index, '.'); - that.set_row_index(child, base_id, index); - }); - } - - set_attr_index(node, attr, base, index, delim) { - let value = node.attr(attr); - if (value && value.indexOf(base) > -1) { - node.attr( - attr, - this.set_value_index(value, base, index, delim) - ); - } - } - - set_value_index(value, base, index, delim) { - let idx_0 = value.indexOf(base) + base.length + 1, - idx_1 = value.indexOf(delim, idx_0), - pre = value.substring(0, idx_0), - post = ''; - if (idx_1 > -1) { - post = value.substring(idx_1, value.length); - } - return pre + index + post; - } - - init_row(container, row) { - this.reset_indices(container); - ArrayWidget.initialize(row); - this.trigger('on_add', row); - } - - add_first_handle(evt) { - evt.preventDefault(); - let new_row = this.create_row(), - container = $('> tbody', this.table); - this.trigger('on_before_add', new_row, container); - container.prepend(new_row); - this.init_row(container, new_row); - } - - add_handle(evt) { - evt.preventDefault(); - let row = this.get_row(evt.currentTarget), - new_row = this.create_row(), - container = row.parent(); - this.trigger('on_before_add', new_row, container); - row.after(new_row); - this.init_row(container, new_row); - } - - remove_handle(evt) { - evt.preventDefault(); - let row = this.get_row(evt.currentTarget); - this.trigger('on_remove', row); - let container = row.parent(); - row.remove(); - this.reset_indices(container); - } - - up_handle(evt) { - evt.preventDefault(); - let row = this.get_row(evt.currentTarget); - this.trigger('on_before_up', row); - row.insertBefore(row.prev()); - this.reset_indices(row.parent()); - - row.addClass('row-moved'); - setTimeout(function() { - row.removeClass('row-moved'); - }, 1000); - - this.trigger('on_up', row); - } - - down_handle(evt) { - evt.preventDefault(); - let row = this.get_row(evt.currentTarget); - this.trigger('on_before_down', row); - row.insertAfter(row.next()); - this.reset_indices(row.parent()); - - row.addClass('row-moved'); - setTimeout(function() { - row.removeClass('row-moved'); - }, 1000); - - this.trigger('on_down', row); - } -} diff --git a/scripts/rollup_bs5.sh b/scripts/rollup_bs5.sh deleted file mode 100755 index 3e00d03..0000000 --- a/scripts/rollup_bs5.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -# -# Create JS bundles. - -node_modules/rollup/dist/bin/rollup --config js/rollup_bs5.conf.js "$@" diff --git a/src/yafowil/widget/array/__init__.py b/src/yafowil/widget/array/__init__.py index c683c79..d2d9e65 100644 --- a/src/yafowil/widget/array/__init__.py +++ b/src/yafowil/widget/array/__init__.py @@ -16,15 +16,15 @@ array_js = wr.ScriptResource( name='yafowil-array-js', depends='jquery-js', - resource='widget.js', - compressed='widget.min.js' + resource='default/widget.js', + compressed='default/widget.min.js' ) # B/C resources ############################################################## js = [{ 'group': 'yafowil.widget.array.common', - 'resource': 'widget.js', + 'resource': 'default/widget.js', 'order': 20, }] @@ -196,7 +196,6 @@ def register(): bootstrap5_resources ) - # Plone 5 factory.register_theme( 'plone5', diff --git a/src/yafowil/widget/array/resources/bootstrap5/widget.js b/src/yafowil/widget/array/resources/bootstrap5/widget.js index 0712f4e..0394490 100644 --- a/src/yafowil/widget/array/resources/bootstrap5/widget.js +++ b/src/yafowil/widget/array/resources/bootstrap5/widget.js @@ -1,41 +1,7 @@ var yafowil_array = (function (exports, $) { 'use strict'; - let hooks = { - before_add: {}, - add: {}, - remove: {}, - before_up: {}, - up: {}, - before_down: {}, - down: {}, - index: {} - }; - let _array_subscribers = { - on_before_add: [], - on_add: [], - on_remove: [], - on_before_up: [], - on_up: [], - on_before_down: [], - on_down: [], - on_index: [] - }; - function on_array_event(event, subscriber) { - _array_subscribers[event].push(subscriber); - } - function inside_template(elem) { - return elem.parents('.arraytemplate').length > 0 - } - class ArrayWidget { - static initialize(context) { - $('div.array', context).each(function() { - let wrapper = $(this); - if (wrapper.attr('id').indexOf('-TEMPLATE') === -1) { - new ArrayWidget(wrapper); - } - }); - } + class ArrayBase { constructor(wrapper) { wrapper.data('yafowil-array', this); this.wrapper = wrapper; @@ -80,20 +46,20 @@ var yafowil_array = (function (exports, $) { row += '
'; if (css.indexOf('array-add') > -1) { row += ''; - row += ' '; + row += ` `; row += ''; } if (css.indexOf('array-remove') > -1) { row += ''; - row += ' '; + row += ` `; row += ''; } if (css.indexOf('array-sort') > -1) { row += ''; - row += ' '; + row += ` `; row += ''; row += ''; - row += ' '; + row += ` `; row += ''; } row += '
'; @@ -113,7 +79,7 @@ var yafowil_array = (function (exports, $) { return id.substring(6, id.length); } trigger(event, ...args) { - let event_hooks = hooks[event.substring(3, event.length)]; + let event_hooks = this.hooks[event.substring(3, event.length)]; if (Object.entries(event_hooks).length) { console.log( 'Array hooks are deprecated. Use ``on_array_event`` instead.' @@ -124,7 +90,7 @@ var yafowil_array = (function (exports, $) { } } args.splice(0, 0, this); - for (let subscriber of _array_subscribers[event]) { + for (let subscriber of this._array_subscribers[event]) { subscriber.apply(null, args); } } @@ -175,7 +141,7 @@ var yafowil_array = (function (exports, $) { } init_row(container, row) { this.reset_indices(container); - ArrayWidget.initialize(row); + this.array_widget.initialize(row); this.trigger('on_add', row); } add_first_handle(evt) { @@ -209,10 +175,6 @@ var yafowil_array = (function (exports, $) { this.trigger('on_before_up', row); row.insertBefore(row.prev()); this.reset_indices(row.parent()); - row.addClass('row-moved'); - setTimeout(function() { - row.removeClass('row-moved'); - }, 1000); this.trigger('on_up', row); } down_handle(evt) { @@ -221,11 +183,68 @@ var yafowil_array = (function (exports, $) { this.trigger('on_before_down', row); row.insertAfter(row.next()); this.reset_indices(row.parent()); + this.trigger('on_down', row); + } + } + + let hooks = { + before_add: {}, + add: {}, + remove: {}, + before_up: {}, + up: {}, + before_down: {}, + down: {}, + index: {} + }; + let _array_subscribers = { + on_before_add: [], + on_add: [], + on_remove: [], + on_before_up: [], + on_up: [], + on_before_down: [], + on_down: [], + on_index: [] + }; + function on_array_event(event, subscriber) { + _array_subscribers[event].push(subscriber); + } + function inside_template(elem) { + return elem.parents('.arraytemplate').length > 0 + } + class ArrayWidget extends ArrayBase { + static initialize(context) { + $('div.array', context).each(function() { + let wrapper = $(this); + if (wrapper.attr('id').indexOf('-TEMPLATE') === -1) { + new ArrayWidget(wrapper); + } + }); + } + constructor(wrapper) { + super(wrapper); + this.hooks = hooks; + this._array_subscribers = _array_subscribers; + this.array_widget = ArrayWidget; + this.icon_add = 'bi-plus-circle-fill'; + this.icon_remove = 'bi-dash-circle-fill'; + this.icon_up = 'bi-arrow-up-circle-fill'; + this.icon_down = 'bi-arrow-down-circle-fill'; + } + up_handle(evt) { + super.up_handle(evt); + row.addClass('row-moved'); + setTimeout(function() { + row.removeClass('row-moved'); + }, 1000); + } + down_handle(evt) { + super.down_handle(evt); row.addClass('row-moved'); setTimeout(function() { row.removeClass('row-moved'); }, 1000); - this.trigger('on_down', row); } } diff --git a/src/yafowil/widget/array/resources/bootstrap5/widget.min.js b/src/yafowil/widget/array/resources/bootstrap5/widget.min.js index 0c4e6f7..efe6931 100644 --- a/src/yafowil/widget/array/resources/bootstrap5/widget.min.js +++ b/src/yafowil/widget/array/resources/bootstrap5/widget.min.js @@ -1 +1 @@ -var yafowil_array=function(e,r){"use strict";let t={before_add:{},add:{},remove:{},before_up:{},up:{},before_down:{},down:{},index:{}},a={on_before_add:[],on_add:[],on_remove:[],on_before_up:[],on_up:[],on_before_down:[],on_down:[],on_index:[]};class i{static initialize(e){r("div.array",e).each((function(){let e=r(this);-1===e.attr("id").indexOf("-TEMPLATE")&&new i(e)}))}constructor(e){e.data("yafowil-array",this),this.wrapper=e;let t=r("> table",e),a=r("> thead .array_actions",t),i=this.add_first_handle.bind(this);this.table=t,r("a.array_row_add",a).off().on("click",i),this.bind_actions()}bind_actions(){let e=r("> tbody > tr > td.actions .array_actions",this.table),t=this.add_handle.bind(this),a=this.remove_handle.bind(this),i=this.up_handle.bind(this),n=this.down_handle.bind(this);this.mark_disabled(e),r("a.array_row_add",e).off().on("click",t),r("a.array_row_remove",e).off().on("click",a),r("a.array_row_up",e).off().on("click",i),r("a.array_row_down",e).off().on("click",n)}mark_disabled(e){r("a.array_row_up",e).removeClass("array_row_up_disabled").first().addClass("array_row_up_disabled"),r("a.array_row_down",e).removeClass("array_row_down_disabled").last().addClass("array_row_down_disabled")}create_row(){let e=this.wrapper.attr("class"),t="";t+="",t+='',t+="",-1===e.indexOf("array-static")&&(t+='',t+='
',e.indexOf("array-add")>-1&&(t+='',t+=' ',t+=""),e.indexOf("array-remove")>-1&&(t+='',t+=' ',t+=""),e.indexOf("array-sort")>-1&&(t+='',t+=' ',t+="",t+='',t+=' ',t+=""),t+="
",t+=""),t+="",t=r(t);let a=r("> .arraytemplate",this.wrapper).clone();return r(".widget",t).append(a.children()),t}get_row(e){return r(e).parent().parent().parent()}get base_id(){let e=this.wrapper.attr("id");return e.substring(6,e.length)}trigger(e,...r){let i=t[e.substring(3,e.length)];if(Object.entries(i).length){console.log("Array hooks are deprecated. Use ``on_array_event`` instead.");for(let e in i)console.log(` - ${e}`),i[e].apply(null,r)}r.splice(0,0,this);for(let t of a[e])t.apply(null,r)}reset_indices(e){let t,a=0,i=this.base_id,n=this;e.children().each((function(){t=r(this),n.set_row_index(t,i,a),n.trigger("on_index",t,a),a++})),this.bind_actions()}set_row_index(e,t,a){let i,n=t.replace(/\-/g,"."),s=this.set_attr_index.bind(this),o=this;e.children().each((function(){i=r(this),s(i,"id",t,a,"-"),s(i,"for",t,a,"-"),s(i,"name",n,a,"."),o.set_row_index(i,t,a)}))}set_attr_index(e,r,t,a,i){let n=e.attr(r);n&&n.indexOf(t)>-1&&e.attr(r,this.set_value_index(n,t,a,i))}set_value_index(e,r,t,a){let i=e.indexOf(r)+r.length+1,n=e.indexOf(a,i),s=e.substring(0,i),o="";return n>-1&&(o=e.substring(n,e.length)),s+t+o}init_row(e,r){this.reset_indices(e),i.initialize(r),this.trigger("on_add",r)}add_first_handle(e){e.preventDefault();let t=this.create_row(),a=r("> tbody",this.table);this.trigger("on_before_add",t,a),a.prepend(t),this.init_row(a,t)}add_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget),t=this.create_row(),a=r.parent();this.trigger("on_before_add",t,a),r.after(t),this.init_row(a,t)}remove_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget);this.trigger("on_remove",r);let t=r.parent();r.remove(),this.reset_indices(t)}up_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget);this.trigger("on_before_up",r),r.insertBefore(r.prev()),this.reset_indices(r.parent()),r.addClass("row-moved"),setTimeout((function(){r.removeClass("row-moved")}),1e3),this.trigger("on_up",r)}down_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget);this.trigger("on_before_down",r),r.insertAfter(r.next()),this.reset_indices(r.parent()),r.addClass("row-moved"),setTimeout((function(){r.removeClass("row-moved")}),1e3),this.trigger("on_down",r)}}return r((function(){void 0!==window.ts?ts.ajax.register(i.initialize,!0):void 0!==window.bdajax?bdajax.register(i.initialize,!0):i.initialize()})),e.ArrayWidget=i,e.hooks=t,e.inside_template=function(e){return e.parents(".arraytemplate").length>0},e.on_array_event=function(e,r){a[e].push(r)},Object.defineProperty(e,"__esModule",{value:!0}),window.yafowil=window.yafowil||{},window.yafowil.array=e,e}({},jQuery); +var yafowil_array=function(e,r){"use strict";class t{constructor(e){e.data("yafowil-array",this),this.wrapper=e;let t=r("> table",e),a=r("> thead .array_actions",t),i=this.add_first_handle.bind(this);this.table=t,r("a.array_row_add",a).off().on("click",i),this.bind_actions()}bind_actions(){let e=r("> tbody > tr > td.actions .array_actions",this.table),t=this.add_handle.bind(this),a=this.remove_handle.bind(this),i=this.up_handle.bind(this),s=this.down_handle.bind(this);this.mark_disabled(e),r("a.array_row_add",e).off().on("click",t),r("a.array_row_remove",e).off().on("click",a),r("a.array_row_up",e).off().on("click",i),r("a.array_row_down",e).off().on("click",s)}mark_disabled(e){r("a.array_row_up",e).removeClass("array_row_up_disabled").first().addClass("array_row_up_disabled"),r("a.array_row_down",e).removeClass("array_row_down_disabled").last().addClass("array_row_down_disabled")}create_row(){let e=this.wrapper.attr("class"),t="";t+="",t+='',t+="",-1===e.indexOf("array-static")&&(t+='',t+='
',e.indexOf("array-add")>-1&&(t+='',t+=` `,t+=""),e.indexOf("array-remove")>-1&&(t+='',t+=` `,t+=""),e.indexOf("array-sort")>-1&&(t+='',t+=` `,t+="",t+='',t+=` `,t+=""),t+="
",t+=""),t+="",t=r(t);let a=r("> .arraytemplate",this.wrapper).clone();return r(".widget",t).append(a.children()),t}get_row(e){return r(e).parent().parent().parent()}get base_id(){let e=this.wrapper.attr("id");return e.substring(6,e.length)}trigger(e,...r){let t=this.hooks[e.substring(3,e.length)];if(Object.entries(t).length){console.log("Array hooks are deprecated. Use ``on_array_event`` instead.");for(let e in t)console.log(` - ${e}`),t[e].apply(null,r)}r.splice(0,0,this);for(let t of this._array_subscribers[e])t.apply(null,r)}reset_indices(e){let t,a=0,i=this.base_id,s=this;e.children().each((function(){t=r(this),s.set_row_index(t,i,a),s.trigger("on_index",t,a),a++})),this.bind_actions()}set_row_index(e,t,a){let i,s=t.replace(/\-/g,"."),n=this.set_attr_index.bind(this),o=this;e.children().each((function(){i=r(this),n(i,"id",t,a,"-"),n(i,"for",t,a,"-"),n(i,"name",s,a,"."),o.set_row_index(i,t,a)}))}set_attr_index(e,r,t,a,i){let s=e.attr(r);s&&s.indexOf(t)>-1&&e.attr(r,this.set_value_index(s,t,a,i))}set_value_index(e,r,t,a){let i=e.indexOf(r)+r.length+1,s=e.indexOf(a,i),n=e.substring(0,i),o="";return s>-1&&(o=e.substring(s,e.length)),n+t+o}init_row(e,r){this.reset_indices(e),this.array_widget.initialize(r),this.trigger("on_add",r)}add_first_handle(e){e.preventDefault();let t=this.create_row(),a=r("> tbody",this.table);this.trigger("on_before_add",t,a),a.prepend(t),this.init_row(a,t)}add_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget),t=this.create_row(),a=r.parent();this.trigger("on_before_add",t,a),r.after(t),this.init_row(a,t)}remove_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget);this.trigger("on_remove",r);let t=r.parent();r.remove(),this.reset_indices(t)}up_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget);this.trigger("on_before_up",r),r.insertBefore(r.prev()),this.reset_indices(r.parent()),this.trigger("on_up",r)}down_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget);this.trigger("on_before_down",r),r.insertAfter(r.next()),this.reset_indices(r.parent()),this.trigger("on_down",r)}}let a={before_add:{},add:{},remove:{},before_up:{},up:{},before_down:{},down:{},index:{}},i={on_before_add:[],on_add:[],on_remove:[],on_before_up:[],on_up:[],on_before_down:[],on_down:[],on_index:[]};class s extends t{static initialize(e){r("div.array",e).each((function(){let e=r(this);-1===e.attr("id").indexOf("-TEMPLATE")&&new s(e)}))}constructor(e){super(e),this.hooks=a,this._array_subscribers=i,this.array_widget=s,this.icon_add="bi-plus-circle-fill",this.icon_remove="bi-dash-circle-fill",this.icon_up="bi-arrow-up-circle-fill",this.icon_down="bi-arrow-down-circle-fill"}up_handle(e){super.up_handle(e),row.addClass("row-moved"),setTimeout((function(){row.removeClass("row-moved")}),1e3)}down_handle(e){super.down_handle(e),row.addClass("row-moved"),setTimeout((function(){row.removeClass("row-moved")}),1e3)}}return r((function(){void 0!==window.ts?ts.ajax.register(s.initialize,!0):void 0!==window.bdajax?bdajax.register(s.initialize,!0):s.initialize()})),e.ArrayWidget=s,e.hooks=a,e.inside_template=function(e){return e.parents(".arraytemplate").length>0},e.on_array_event=function(e,r){i[e].push(r)},Object.defineProperty(e,"__esModule",{value:!0}),window.yafowil=window.yafowil||{},window.yafowil.array=e,e}({},jQuery); diff --git a/src/yafowil/widget/array/resources/widget.js b/src/yafowil/widget/array/resources/default/widget.js similarity index 90% rename from src/yafowil/widget/array/resources/widget.js rename to src/yafowil/widget/array/resources/default/widget.js index e573651..92f0ace 100644 --- a/src/yafowil/widget/array/resources/widget.js +++ b/src/yafowil/widget/array/resources/default/widget.js @@ -1,41 +1,7 @@ var yafowil_array = (function (exports, $) { 'use strict'; - let hooks = { - before_add: {}, - add: {}, - remove: {}, - before_up: {}, - up: {}, - before_down: {}, - down: {}, - index: {} - }; - let _array_subscribers = { - on_before_add: [], - on_add: [], - on_remove: [], - on_before_up: [], - on_up: [], - on_before_down: [], - on_down: [], - on_index: [] - }; - function on_array_event(event, subscriber) { - _array_subscribers[event].push(subscriber); - } - function inside_template(elem) { - return elem.parents('.arraytemplate').length > 0 - } - class ArrayWidget { - static initialize(context) { - $('div.array', context).each(function() { - let wrapper = $(this); - if (wrapper.attr('id').indexOf('-TEMPLATE') === -1) { - new ArrayWidget(wrapper); - } - }); - } + class ArrayBase { constructor(wrapper) { wrapper.data('yafowil-array', this); this.wrapper = wrapper; @@ -80,20 +46,20 @@ var yafowil_array = (function (exports, $) { row += '
'; if (css.indexOf('array-add') > -1) { row += ''; - row += ' '; + row += ` `; row += ''; } if (css.indexOf('array-remove') > -1) { row += ''; - row += ' '; + row += ` `; row += ''; } if (css.indexOf('array-sort') > -1) { row += ''; - row += ' '; + row += ` `; row += ''; row += ''; - row += ' '; + row += ` `; row += ''; } row += '
'; @@ -113,7 +79,7 @@ var yafowil_array = (function (exports, $) { return id.substring(6, id.length); } trigger(event, ...args) { - let event_hooks = hooks[event.substring(3, event.length)]; + let event_hooks = this.hooks[event.substring(3, event.length)]; if (Object.entries(event_hooks).length) { console.log( 'Array hooks are deprecated. Use ``on_array_event`` instead.' @@ -124,7 +90,7 @@ var yafowil_array = (function (exports, $) { } } args.splice(0, 0, this); - for (let subscriber of _array_subscribers[event]) { + for (let subscriber of this._array_subscribers[event]) { subscriber.apply(null, args); } } @@ -175,7 +141,7 @@ var yafowil_array = (function (exports, $) { } init_row(container, row) { this.reset_indices(container); - ArrayWidget.initialize(row); + this.array_widget.initialize(row); this.trigger('on_add', row); } add_first_handle(evt) { @@ -221,6 +187,53 @@ var yafowil_array = (function (exports, $) { } } + let hooks = { + before_add: {}, + add: {}, + remove: {}, + before_up: {}, + up: {}, + before_down: {}, + down: {}, + index: {} + }; + let _array_subscribers = { + on_before_add: [], + on_add: [], + on_remove: [], + on_before_up: [], + on_up: [], + on_before_down: [], + on_down: [], + on_index: [] + }; + function on_array_event(event, subscriber) { + _array_subscribers[event].push(subscriber); + } + function inside_template(elem) { + return elem.parents('.arraytemplate').length > 0 + } + class ArrayWidget extends ArrayBase { + static initialize(context) { + $('div.array', context).each(function() { + let wrapper = $(this); + if (wrapper.attr('id').indexOf('-TEMPLATE') === -1) { + new ArrayWidget(wrapper); + } + }); + } + constructor(wrapper) { + super(wrapper); + this.hooks = hooks; + this._array_subscribers = _array_subscribers; + this.array_widget = ArrayWidget; + this.icon_add = 'icon-plus-sign'; + this.icon_remove = 'icon-minus-sign'; + this.icon_up = 'icon-circle-arrow-up'; + this.icon_down = 'icon-circle-arrow-down'; + } + } + $(function() { if (window.ts !== undefined) { ts.ajax.register(ArrayWidget.initialize, true); diff --git a/src/yafowil/widget/array/resources/default/widget.min.js b/src/yafowil/widget/array/resources/default/widget.min.js new file mode 100644 index 0000000..77f4281 --- /dev/null +++ b/src/yafowil/widget/array/resources/default/widget.min.js @@ -0,0 +1 @@ +var yafowil_array=function(e,r){"use strict";class t{constructor(e){e.data("yafowil-array",this),this.wrapper=e;let t=r("> table",e),a=r("> thead .array_actions",t),i=this.add_first_handle.bind(this);this.table=t,r("a.array_row_add",a).off().on("click",i),this.bind_actions()}bind_actions(){let e=r("> tbody > tr > td.actions .array_actions",this.table),t=this.add_handle.bind(this),a=this.remove_handle.bind(this),i=this.up_handle.bind(this),n=this.down_handle.bind(this);this.mark_disabled(e),r("a.array_row_add",e).off().on("click",t),r("a.array_row_remove",e).off().on("click",a),r("a.array_row_up",e).off().on("click",i),r("a.array_row_down",e).off().on("click",n)}mark_disabled(e){r("a.array_row_up",e).removeClass("array_row_up_disabled").first().addClass("array_row_up_disabled"),r("a.array_row_down",e).removeClass("array_row_down_disabled").last().addClass("array_row_down_disabled")}create_row(){let e=this.wrapper.attr("class"),t="";t+="",t+='',t+="",-1===e.indexOf("array-static")&&(t+='',t+='
',e.indexOf("array-add")>-1&&(t+='',t+=` `,t+=""),e.indexOf("array-remove")>-1&&(t+='',t+=` `,t+=""),e.indexOf("array-sort")>-1&&(t+='',t+=` `,t+="",t+='',t+=` `,t+=""),t+="
",t+=""),t+="",t=r(t);let a=r("> .arraytemplate",this.wrapper).clone();return r(".widget",t).append(a.children()),t}get_row(e){return r(e).parent().parent().parent()}get base_id(){let e=this.wrapper.attr("id");return e.substring(6,e.length)}trigger(e,...r){let t=this.hooks[e.substring(3,e.length)];if(Object.entries(t).length){console.log("Array hooks are deprecated. Use ``on_array_event`` instead.");for(let e in t)console.log(` - ${e}`),t[e].apply(null,r)}r.splice(0,0,this);for(let t of this._array_subscribers[e])t.apply(null,r)}reset_indices(e){let t,a=0,i=this.base_id,n=this;e.children().each((function(){t=r(this),n.set_row_index(t,i,a),n.trigger("on_index",t,a),a++})),this.bind_actions()}set_row_index(e,t,a){let i,n=t.replace(/\-/g,"."),s=this.set_attr_index.bind(this),o=this;e.children().each((function(){i=r(this),s(i,"id",t,a,"-"),s(i,"for",t,a,"-"),s(i,"name",n,a,"."),o.set_row_index(i,t,a)}))}set_attr_index(e,r,t,a,i){let n=e.attr(r);n&&n.indexOf(t)>-1&&e.attr(r,this.set_value_index(n,t,a,i))}set_value_index(e,r,t,a){let i=e.indexOf(r)+r.length+1,n=e.indexOf(a,i),s=e.substring(0,i),o="";return n>-1&&(o=e.substring(n,e.length)),s+t+o}init_row(e,r){this.reset_indices(e),this.array_widget.initialize(r),this.trigger("on_add",r)}add_first_handle(e){e.preventDefault();let t=this.create_row(),a=r("> tbody",this.table);this.trigger("on_before_add",t,a),a.prepend(t),this.init_row(a,t)}add_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget),t=this.create_row(),a=r.parent();this.trigger("on_before_add",t,a),r.after(t),this.init_row(a,t)}remove_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget);this.trigger("on_remove",r);let t=r.parent();r.remove(),this.reset_indices(t)}up_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget);this.trigger("on_before_up",r),r.insertBefore(r.prev()),this.reset_indices(r.parent()),this.trigger("on_up",r)}down_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget);this.trigger("on_before_down",r),r.insertAfter(r.next()),this.reset_indices(r.parent()),this.trigger("on_down",r)}}let a={before_add:{},add:{},remove:{},before_up:{},up:{},before_down:{},down:{},index:{}},i={on_before_add:[],on_add:[],on_remove:[],on_before_up:[],on_up:[],on_before_down:[],on_down:[],on_index:[]};class n extends t{static initialize(e){r("div.array",e).each((function(){let e=r(this);-1===e.attr("id").indexOf("-TEMPLATE")&&new n(e)}))}constructor(e){super(e),this.hooks=a,this._array_subscribers=i,this.array_widget=n,this.icon_add="icon-plus-sign",this.icon_remove="icon-minus-sign",this.icon_up="icon-circle-arrow-up",this.icon_down="icon-circle-arrow-down"}}return r((function(){void 0!==window.ts?ts.ajax.register(n.initialize,!0):void 0!==window.bdajax?bdajax.register(n.initialize,!0):n.initialize()})),e.ArrayWidget=n,e.hooks=a,e.inside_template=function(e){return e.parents(".arraytemplate").length>0},e.on_array_event=function(e,r){i[e].push(r)},Object.defineProperty(e,"__esModule",{value:!0}),window.yafowil=window.yafowil||{},window.yafowil.array=e,e}({},jQuery); diff --git a/src/yafowil/widget/array/resources/widget.min.js b/src/yafowil/widget/array/resources/widget.min.js deleted file mode 100644 index 8cb4e97..0000000 --- a/src/yafowil/widget/array/resources/widget.min.js +++ /dev/null @@ -1 +0,0 @@ -var yafowil_array=function(e,r){"use strict";let t={before_add:{},add:{},remove:{},before_up:{},up:{},before_down:{},down:{},index:{}},a={on_before_add:[],on_add:[],on_remove:[],on_before_up:[],on_up:[],on_before_down:[],on_down:[],on_index:[]};class i{static initialize(e){r("div.array",e).each((function(){let e=r(this);-1===e.attr("id").indexOf("-TEMPLATE")&&new i(e)}))}constructor(e){e.data("yafowil-array",this),this.wrapper=e;let t=r("> table",e),a=r("> thead .array_actions",t),i=this.add_first_handle.bind(this);this.table=t,r("a.array_row_add",a).off().on("click",i),this.bind_actions()}bind_actions(){let e=r("> tbody > tr > td.actions .array_actions",this.table),t=this.add_handle.bind(this),a=this.remove_handle.bind(this),i=this.up_handle.bind(this),n=this.down_handle.bind(this);this.mark_disabled(e),r("a.array_row_add",e).off().on("click",t),r("a.array_row_remove",e).off().on("click",a),r("a.array_row_up",e).off().on("click",i),r("a.array_row_down",e).off().on("click",n)}mark_disabled(e){r("a.array_row_up",e).removeClass("array_row_up_disabled").first().addClass("array_row_up_disabled"),r("a.array_row_down",e).removeClass("array_row_down_disabled").last().addClass("array_row_down_disabled")}create_row(){let e=this.wrapper.attr("class"),t="";t+="",t+='',t+="",-1===e.indexOf("array-static")&&(t+='',t+='
',e.indexOf("array-add")>-1&&(t+='',t+=' ',t+=""),e.indexOf("array-remove")>-1&&(t+='',t+=' ',t+=""),e.indexOf("array-sort")>-1&&(t+='',t+=' ',t+="",t+='',t+=' ',t+=""),t+="
",t+=""),t+="",t=r(t);let a=r("> .arraytemplate",this.wrapper).clone();return r(".widget",t).append(a.children()),t}get_row(e){return r(e).parent().parent().parent()}get base_id(){let e=this.wrapper.attr("id");return e.substring(6,e.length)}trigger(e,...r){let i=t[e.substring(3,e.length)];if(Object.entries(i).length){console.log("Array hooks are deprecated. Use ``on_array_event`` instead.");for(let e in i)console.log(` - ${e}`),i[e].apply(null,r)}r.splice(0,0,this);for(let t of a[e])t.apply(null,r)}reset_indices(e){let t,a=0,i=this.base_id,n=this;e.children().each((function(){t=r(this),n.set_row_index(t,i,a),n.trigger("on_index",t,a),a++})),this.bind_actions()}set_row_index(e,t,a){let i,n=t.replace(/\-/g,"."),s=this.set_attr_index.bind(this),o=this;e.children().each((function(){i=r(this),s(i,"id",t,a,"-"),s(i,"for",t,a,"-"),s(i,"name",n,a,"."),o.set_row_index(i,t,a)}))}set_attr_index(e,r,t,a,i){let n=e.attr(r);n&&n.indexOf(t)>-1&&e.attr(r,this.set_value_index(n,t,a,i))}set_value_index(e,r,t,a){let i=e.indexOf(r)+r.length+1,n=e.indexOf(a,i),s=e.substring(0,i),o="";return n>-1&&(o=e.substring(n,e.length)),s+t+o}init_row(e,r){this.reset_indices(e),i.initialize(r),this.trigger("on_add",r)}add_first_handle(e){e.preventDefault();let t=this.create_row(),a=r("> tbody",this.table);this.trigger("on_before_add",t,a),a.prepend(t),this.init_row(a,t)}add_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget),t=this.create_row(),a=r.parent();this.trigger("on_before_add",t,a),r.after(t),this.init_row(a,t)}remove_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget);this.trigger("on_remove",r);let t=r.parent();r.remove(),this.reset_indices(t)}up_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget);this.trigger("on_before_up",r),r.insertBefore(r.prev()),this.reset_indices(r.parent()),this.trigger("on_up",r)}down_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget);this.trigger("on_before_down",r),r.insertAfter(r.next()),this.reset_indices(r.parent()),this.trigger("on_down",r)}}return r((function(){void 0!==window.ts?ts.ajax.register(i.initialize,!0):void 0!==window.bdajax?bdajax.register(i.initialize,!0):i.initialize()})),e.ArrayWidget=i,e.hooks=t,e.inside_template=function(e){return e.parents(".arraytemplate").length>0},e.on_array_event=function(e,r){a[e].push(r)},Object.defineProperty(e,"__esModule",{value:!0}),window.yafowil=window.yafowil||{},window.yafowil.array=e,e}({},jQuery); From 4fa63671a1b283c3e868485f8b55a6695d8d067f Mon Sep 17 00:00:00 2001 From: Lena Daxenbichler Date: Mon, 23 Sep 2024 10:48:55 +0200 Subject: [PATCH 07/17] add missing line --- js/src/bootstrap5/widget.js | 2 ++ src/yafowil/widget/array/resources/bootstrap5/widget.js | 2 ++ src/yafowil/widget/array/resources/bootstrap5/widget.min.js | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/js/src/bootstrap5/widget.js b/js/src/bootstrap5/widget.js index 5c91e10..02cd312 100644 --- a/js/src/bootstrap5/widget.js +++ b/js/src/bootstrap5/widget.js @@ -57,6 +57,7 @@ export class ArrayWidget extends ArrayBase { up_handle(evt) { super.up_handle(evt); + let row = this.get_row(evt.currentTarget); row.addClass('row-moved'); setTimeout(function() { row.removeClass('row-moved'); @@ -65,6 +66,7 @@ export class ArrayWidget extends ArrayBase { down_handle(evt) { super.down_handle(evt); + let row = this.get_row(evt.currentTarget); row.addClass('row-moved'); setTimeout(function() { row.removeClass('row-moved'); diff --git a/src/yafowil/widget/array/resources/bootstrap5/widget.js b/src/yafowil/widget/array/resources/bootstrap5/widget.js index 0394490..84b68b1 100644 --- a/src/yafowil/widget/array/resources/bootstrap5/widget.js +++ b/src/yafowil/widget/array/resources/bootstrap5/widget.js @@ -234,6 +234,7 @@ var yafowil_array = (function (exports, $) { } up_handle(evt) { super.up_handle(evt); + let row = this.get_row(evt.currentTarget); row.addClass('row-moved'); setTimeout(function() { row.removeClass('row-moved'); @@ -241,6 +242,7 @@ var yafowil_array = (function (exports, $) { } down_handle(evt) { super.down_handle(evt); + let row = this.get_row(evt.currentTarget); row.addClass('row-moved'); setTimeout(function() { row.removeClass('row-moved'); diff --git a/src/yafowil/widget/array/resources/bootstrap5/widget.min.js b/src/yafowil/widget/array/resources/bootstrap5/widget.min.js index efe6931..9ce7e3d 100644 --- a/src/yafowil/widget/array/resources/bootstrap5/widget.min.js +++ b/src/yafowil/widget/array/resources/bootstrap5/widget.min.js @@ -1 +1 @@ -var yafowil_array=function(e,r){"use strict";class t{constructor(e){e.data("yafowil-array",this),this.wrapper=e;let t=r("> table",e),a=r("> thead .array_actions",t),i=this.add_first_handle.bind(this);this.table=t,r("a.array_row_add",a).off().on("click",i),this.bind_actions()}bind_actions(){let e=r("> tbody > tr > td.actions .array_actions",this.table),t=this.add_handle.bind(this),a=this.remove_handle.bind(this),i=this.up_handle.bind(this),s=this.down_handle.bind(this);this.mark_disabled(e),r("a.array_row_add",e).off().on("click",t),r("a.array_row_remove",e).off().on("click",a),r("a.array_row_up",e).off().on("click",i),r("a.array_row_down",e).off().on("click",s)}mark_disabled(e){r("a.array_row_up",e).removeClass("array_row_up_disabled").first().addClass("array_row_up_disabled"),r("a.array_row_down",e).removeClass("array_row_down_disabled").last().addClass("array_row_down_disabled")}create_row(){let e=this.wrapper.attr("class"),t="";t+="",t+='',t+="",-1===e.indexOf("array-static")&&(t+='',t+='
',e.indexOf("array-add")>-1&&(t+='',t+=` `,t+=""),e.indexOf("array-remove")>-1&&(t+='',t+=` `,t+=""),e.indexOf("array-sort")>-1&&(t+='',t+=` `,t+="",t+='',t+=` `,t+=""),t+="
",t+=""),t+="",t=r(t);let a=r("> .arraytemplate",this.wrapper).clone();return r(".widget",t).append(a.children()),t}get_row(e){return r(e).parent().parent().parent()}get base_id(){let e=this.wrapper.attr("id");return e.substring(6,e.length)}trigger(e,...r){let t=this.hooks[e.substring(3,e.length)];if(Object.entries(t).length){console.log("Array hooks are deprecated. Use ``on_array_event`` instead.");for(let e in t)console.log(` - ${e}`),t[e].apply(null,r)}r.splice(0,0,this);for(let t of this._array_subscribers[e])t.apply(null,r)}reset_indices(e){let t,a=0,i=this.base_id,s=this;e.children().each((function(){t=r(this),s.set_row_index(t,i,a),s.trigger("on_index",t,a),a++})),this.bind_actions()}set_row_index(e,t,a){let i,s=t.replace(/\-/g,"."),n=this.set_attr_index.bind(this),o=this;e.children().each((function(){i=r(this),n(i,"id",t,a,"-"),n(i,"for",t,a,"-"),n(i,"name",s,a,"."),o.set_row_index(i,t,a)}))}set_attr_index(e,r,t,a,i){let s=e.attr(r);s&&s.indexOf(t)>-1&&e.attr(r,this.set_value_index(s,t,a,i))}set_value_index(e,r,t,a){let i=e.indexOf(r)+r.length+1,s=e.indexOf(a,i),n=e.substring(0,i),o="";return s>-1&&(o=e.substring(s,e.length)),n+t+o}init_row(e,r){this.reset_indices(e),this.array_widget.initialize(r),this.trigger("on_add",r)}add_first_handle(e){e.preventDefault();let t=this.create_row(),a=r("> tbody",this.table);this.trigger("on_before_add",t,a),a.prepend(t),this.init_row(a,t)}add_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget),t=this.create_row(),a=r.parent();this.trigger("on_before_add",t,a),r.after(t),this.init_row(a,t)}remove_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget);this.trigger("on_remove",r);let t=r.parent();r.remove(),this.reset_indices(t)}up_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget);this.trigger("on_before_up",r),r.insertBefore(r.prev()),this.reset_indices(r.parent()),this.trigger("on_up",r)}down_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget);this.trigger("on_before_down",r),r.insertAfter(r.next()),this.reset_indices(r.parent()),this.trigger("on_down",r)}}let a={before_add:{},add:{},remove:{},before_up:{},up:{},before_down:{},down:{},index:{}},i={on_before_add:[],on_add:[],on_remove:[],on_before_up:[],on_up:[],on_before_down:[],on_down:[],on_index:[]};class s extends t{static initialize(e){r("div.array",e).each((function(){let e=r(this);-1===e.attr("id").indexOf("-TEMPLATE")&&new s(e)}))}constructor(e){super(e),this.hooks=a,this._array_subscribers=i,this.array_widget=s,this.icon_add="bi-plus-circle-fill",this.icon_remove="bi-dash-circle-fill",this.icon_up="bi-arrow-up-circle-fill",this.icon_down="bi-arrow-down-circle-fill"}up_handle(e){super.up_handle(e),row.addClass("row-moved"),setTimeout((function(){row.removeClass("row-moved")}),1e3)}down_handle(e){super.down_handle(e),row.addClass("row-moved"),setTimeout((function(){row.removeClass("row-moved")}),1e3)}}return r((function(){void 0!==window.ts?ts.ajax.register(s.initialize,!0):void 0!==window.bdajax?bdajax.register(s.initialize,!0):s.initialize()})),e.ArrayWidget=s,e.hooks=a,e.inside_template=function(e){return e.parents(".arraytemplate").length>0},e.on_array_event=function(e,r){i[e].push(r)},Object.defineProperty(e,"__esModule",{value:!0}),window.yafowil=window.yafowil||{},window.yafowil.array=e,e}({},jQuery); +var yafowil_array=function(e,r){"use strict";class t{constructor(e){e.data("yafowil-array",this),this.wrapper=e;let t=r("> table",e),a=r("> thead .array_actions",t),i=this.add_first_handle.bind(this);this.table=t,r("a.array_row_add",a).off().on("click",i),this.bind_actions()}bind_actions(){let e=r("> tbody > tr > td.actions .array_actions",this.table),t=this.add_handle.bind(this),a=this.remove_handle.bind(this),i=this.up_handle.bind(this),s=this.down_handle.bind(this);this.mark_disabled(e),r("a.array_row_add",e).off().on("click",t),r("a.array_row_remove",e).off().on("click",a),r("a.array_row_up",e).off().on("click",i),r("a.array_row_down",e).off().on("click",s)}mark_disabled(e){r("a.array_row_up",e).removeClass("array_row_up_disabled").first().addClass("array_row_up_disabled"),r("a.array_row_down",e).removeClass("array_row_down_disabled").last().addClass("array_row_down_disabled")}create_row(){let e=this.wrapper.attr("class"),t="";t+="",t+='',t+="",-1===e.indexOf("array-static")&&(t+='',t+='
',e.indexOf("array-add")>-1&&(t+='',t+=` `,t+=""),e.indexOf("array-remove")>-1&&(t+='',t+=` `,t+=""),e.indexOf("array-sort")>-1&&(t+='',t+=` `,t+="",t+='',t+=` `,t+=""),t+="
",t+=""),t+="",t=r(t);let a=r("> .arraytemplate",this.wrapper).clone();return r(".widget",t).append(a.children()),t}get_row(e){return r(e).parent().parent().parent()}get base_id(){let e=this.wrapper.attr("id");return e.substring(6,e.length)}trigger(e,...r){let t=this.hooks[e.substring(3,e.length)];if(Object.entries(t).length){console.log("Array hooks are deprecated. Use ``on_array_event`` instead.");for(let e in t)console.log(` - ${e}`),t[e].apply(null,r)}r.splice(0,0,this);for(let t of this._array_subscribers[e])t.apply(null,r)}reset_indices(e){let t,a=0,i=this.base_id,s=this;e.children().each((function(){t=r(this),s.set_row_index(t,i,a),s.trigger("on_index",t,a),a++})),this.bind_actions()}set_row_index(e,t,a){let i,s=t.replace(/\-/g,"."),n=this.set_attr_index.bind(this),o=this;e.children().each((function(){i=r(this),n(i,"id",t,a,"-"),n(i,"for",t,a,"-"),n(i,"name",s,a,"."),o.set_row_index(i,t,a)}))}set_attr_index(e,r,t,a,i){let s=e.attr(r);s&&s.indexOf(t)>-1&&e.attr(r,this.set_value_index(s,t,a,i))}set_value_index(e,r,t,a){let i=e.indexOf(r)+r.length+1,s=e.indexOf(a,i),n=e.substring(0,i),o="";return s>-1&&(o=e.substring(s,e.length)),n+t+o}init_row(e,r){this.reset_indices(e),this.array_widget.initialize(r),this.trigger("on_add",r)}add_first_handle(e){e.preventDefault();let t=this.create_row(),a=r("> tbody",this.table);this.trigger("on_before_add",t,a),a.prepend(t),this.init_row(a,t)}add_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget),t=this.create_row(),a=r.parent();this.trigger("on_before_add",t,a),r.after(t),this.init_row(a,t)}remove_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget);this.trigger("on_remove",r);let t=r.parent();r.remove(),this.reset_indices(t)}up_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget);this.trigger("on_before_up",r),r.insertBefore(r.prev()),this.reset_indices(r.parent()),this.trigger("on_up",r)}down_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget);this.trigger("on_before_down",r),r.insertAfter(r.next()),this.reset_indices(r.parent()),this.trigger("on_down",r)}}let a={before_add:{},add:{},remove:{},before_up:{},up:{},before_down:{},down:{},index:{}},i={on_before_add:[],on_add:[],on_remove:[],on_before_up:[],on_up:[],on_before_down:[],on_down:[],on_index:[]};class s extends t{static initialize(e){r("div.array",e).each((function(){let e=r(this);-1===e.attr("id").indexOf("-TEMPLATE")&&new s(e)}))}constructor(e){super(e),this.hooks=a,this._array_subscribers=i,this.array_widget=s,this.icon_add="bi-plus-circle-fill",this.icon_remove="bi-dash-circle-fill",this.icon_up="bi-arrow-up-circle-fill",this.icon_down="bi-arrow-down-circle-fill"}up_handle(e){super.up_handle(e);let r=this.get_row(e.currentTarget);r.addClass("row-moved"),setTimeout((function(){r.removeClass("row-moved")}),1e3)}down_handle(e){super.down_handle(e);let r=this.get_row(e.currentTarget);r.addClass("row-moved"),setTimeout((function(){r.removeClass("row-moved")}),1e3)}}return r((function(){void 0!==window.ts?ts.ajax.register(s.initialize,!0):void 0!==window.bdajax?bdajax.register(s.initialize,!0):s.initialize()})),e.ArrayWidget=s,e.hooks=a,e.inside_template=function(e){return e.parents(".arraytemplate").length>0},e.on_array_event=function(e,r){i[e].push(r)},Object.defineProperty(e,"__esModule",{value:!0}),window.yafowil=window.yafowil||{},window.yafowil.array=e,e}({},jQuery); From 4e1dc0b2c25573ec05303a3e476c4f992c9d7fe7 Mon Sep 17 00:00:00 2001 From: Lena Daxenbichler Date: Fri, 25 Oct 2024 12:57:48 +0200 Subject: [PATCH 08/17] fix github actions. fix py tests. update scss structure. --- .github/workflows/test_js.yaml | 32 ++-- .github/workflows/test_py.yaml | 16 +- js/rollup.conf.js | 130 +++++++++------ js/tests/test_array.js | 2 +- .../widget.scss} | 0 .../widget.scss} | 0 .../widget.scss} | 0 .../widget.scss} | 0 .../array/resources/bootstrap5/widget.css | 65 +------- src/yafowil/widget/array/tests/test_widget.py | 152 +++++++++--------- 10 files changed, 176 insertions(+), 221 deletions(-) rename scss/{widget_bootstrap.scss => bootstrap/widget.scss} (100%) rename scss/{widget_bootstrap5.scss => bootstrap5/widget.scss} (100%) rename scss/{widget_default.scss => default/widget.scss} (100%) rename scss/{widget_plone5.scss => plone5/widget.scss} (100%) diff --git a/.github/workflows/test_js.yaml b/.github/workflows/test_js.yaml index 38cdd84..009ed7f 100644 --- a/.github/workflows/test_js.yaml +++ b/.github/workflows/test_js.yaml @@ -1,34 +1,20 @@ name: JS Test array -on: - push: - paths: - - '**.js' +on: [push] jobs: test: - name: TEST ARRAY + name: Test runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - - name: Install - run: | - npm --save-dev install \ - qunit \ - karma \ - karma-qunit \ - karma-coverage \ - karma-chrome-launcher \ - karma-module-resolver-preprocessor - npm --no-save install https://github.com/jquery/jquery#main + - name: Install + run: | + corepack enable + make nodejs - - name: Run tests - run: | - node_modules/karma/bin/karma start js/karma.conf.js - - - name: Run coverage - run: | - npm run karma-test:coverage + - name: Run tests + run: make wtr diff --git a/.github/workflows/test_py.yaml b/.github/workflows/test_py.yaml index 19c2c6b..caa084c 100644 --- a/.github/workflows/test_py.yaml +++ b/.github/workflows/test_py.yaml @@ -1,9 +1,6 @@ name: PY Test array -on: - push: - paths: - - '**.py' +on: [push] jobs: test: @@ -24,6 +21,9 @@ jobs: - "3.8" - "3.9" - "3.10" + - "3.11" + - "3.12" + - "3.13" steps: - uses: actions/checkout@v2 @@ -37,16 +37,16 @@ jobs: run: | pip install wheel pip install coverage - pip install lxml - pip install zope.testrunner pip install https://github.com/conestack/webresource/archive/master.zip pip install https://github.com/conestack/yafowil/archive/master.zip pip install -e .[test] + - name: Run tests run: | python --version - python -m yafowil.widget.array.tests + python -m pytest src/yafowil/widget/array/tests + - name: Run coverage run: | - coverage run --source=src/yafowil/widget/array --omit=src/yafowil/widget/array/example.py -m yafowil.widget.array.tests + coverage run --source=src/yafowil/widget/array --omit=src/yafowil/widget/array/example.py -m pytest src/yafowil/widget/array/tests coverage report --fail-under=99 \ No newline at end of file diff --git a/js/rollup.conf.js b/js/rollup.conf.js index 2e02424..ca156f0 100644 --- a/js/rollup.conf.js +++ b/js/rollup.conf.js @@ -2,8 +2,7 @@ import cleanup from 'rollup-plugin-cleanup'; import postcss from 'rollup-plugin-postcss'; import terser from '@rollup/plugin-terser'; -const out_dir = 'src/yafowil/widget/array/resources/default'; -const out_dir_bs5 = 'src/yafowil/widget/array/resources/bootstrap5'; +const out_dir = 'src/yafowil/widget/array/resources'; const outro = ` window.yafowil = window.yafowil || {}; @@ -11,51 +10,19 @@ window.yafowil.array = exports; `; export default args => { - // default - let conf1 = { - input: 'js/src/default/bundle.js', - plugins: [ - cleanup() - ], - output: [{ - name: 'yafowil_array', - file: `${out_dir}/widget.js`, - format: 'iife', - outro: outro, - globals: { - jquery: 'jQuery' - }, - interop: 'default' - }], - external: [ - 'jquery' - ] - }; - if (args.configDebug !== true) { - conf1.output.push({ - name: 'yafowil_array', - file: `${out_dir}/widget.min.js`, - format: 'iife', - plugins: [ - terser() - ], - outro: outro, - globals: { - jquery: 'jQuery' - }, - interop: 'default' - }); - } - // Bootstrap5 - let conf2 = { - input: 'js/src/bootstrap5/bundle.js', + //////////////////////////////////////////////////////////////////////////// + // DEFAULT + //////////////////////////////////////////////////////////////////////////// + + let bundle_default = { + input: 'js/src/default/bundle.js', plugins: [ cleanup() ], output: [{ name: 'yafowil_array', - file: `${out_dir_bs5}/widget.js`, + file: `${out_dir}/default/widget.js`, format: 'iife', outro: outro, globals: { @@ -68,9 +35,9 @@ export default args => { ] }; if (args.configDebug !== true) { - conf2.output.push({ + bundle_default.output.push({ name: 'yafowil_array', - file: `${out_dir_bs5}/widget.min.js`, + file: `${out_dir}/default/widget.min.js`, format: 'iife', plugins: [ terser() @@ -82,10 +49,8 @@ export default args => { interop: 'default' }); } - - return [conf1, conf2]; let scss_default = { - input: ['scss/widget_default.scss'], + input: ['scss/default/widget.scss'], output: [ { file: `${out_dir}/default/widget.css`, @@ -103,8 +68,13 @@ export default args => { }), ], }; + + //////////////////////////////////////////////////////////////////////////// + // BOOTSTRAP + //////////////////////////////////////////////////////////////////////////// + let scss_bootstrap = { - input: ['scss/widget_bootstrap.scss'], + input: ['scss/bootstrap/widget.scss'], output: [ { file: `${out_dir}/bootstrap/widget.css`, @@ -122,8 +92,13 @@ export default args => { }), ], }; + + //////////////////////////////////////////////////////////////////////////// + // PLONE5 + //////////////////////////////////////////////////////////////////////////// + let scss_plone5 = { - input: ['scss/widget_plone5.scss'], + input: ['scss/plone5/widget.scss'], output: [ { file: `${out_dir}/plone5/widget.css`, @@ -141,5 +116,62 @@ export default args => { }), ], }; - return [conf, scss_default, scss_bootstrap, scss_plone5]; + + //////////////////////////////////////////////////////////////////////////// + // BOOTSTRAP5 + //////////////////////////////////////////////////////////////////////////// + + let bundle_bs5 = { + input: 'js/src/bootstrap5/bundle.js', + plugins: [ + cleanup() + ], + output: [{ + name: 'yafowil_array', + file: `${out_dir}/bootstrap5/widget.js`, + format: 'iife', + outro: outro, + globals: { + jquery: 'jQuery' + }, + interop: 'default' + }], + external: [ + 'jquery' + ] + }; + if (args.configDebug !== true) { + bundle_bs5.output.push({ + name: 'yafowil_array', + file: `${out_dir}/bootstrap5/widget.min.js`, + format: 'iife', + plugins: [ + terser() + ], + outro: outro, + globals: { + jquery: 'jQuery' + }, + interop: 'default' + }); + } + let scss_bs5 = { + input: ['scss/bootstrap5/widget.scss'], + output: [{ + file: `${out_dir}/bootstrap5/widget.css`, + format: 'es', + plugins: [terser()], + }], + plugins: [ + postcss({ + extract: true, + minimize: true, + use: [ + ['sass', { outputStyle: 'compressed' }], + ], + }), + ], + }; + + return [bundle_default, scss_default, scss_bootstrap, scss_plone5, bundle_bs5, scss_bs5]; }; diff --git a/js/tests/test_array.js b/js/tests/test_array.js index 40aac9b..369715c 100644 --- a/js/tests/test_array.js +++ b/js/tests/test_array.js @@ -1,4 +1,4 @@ -import { ArrayWidget } from "../src/widget"; +import { ArrayWidget } from "../src/default/widget.js"; import $ from 'jquery'; QUnit.test('Initialize', assert => { diff --git a/scss/widget_bootstrap.scss b/scss/bootstrap/widget.scss similarity index 100% rename from scss/widget_bootstrap.scss rename to scss/bootstrap/widget.scss diff --git a/scss/widget_bootstrap5.scss b/scss/bootstrap5/widget.scss similarity index 100% rename from scss/widget_bootstrap5.scss rename to scss/bootstrap5/widget.scss diff --git a/scss/widget_default.scss b/scss/default/widget.scss similarity index 100% rename from scss/widget_default.scss rename to scss/default/widget.scss diff --git a/scss/widget_plone5.scss b/scss/plone5/widget.scss similarity index 100% rename from scss/widget_plone5.scss rename to scss/plone5/widget.scss diff --git a/src/yafowil/widget/array/resources/bootstrap5/widget.css b/src/yafowil/widget/array/resources/bootstrap5/widget.css index 50c488d..1e53d5d 100644 --- a/src/yafowil/widget/array/resources/bootstrap5/widget.css +++ b/src/yafowil/widget/array/resources/bootstrap5/widget.css @@ -1,64 +1 @@ -/* yafowil.widget.array - bootstrap theme styles */ -.arraytemplate { - display: none; -} - -.array table { - margin-bottom: 0; -} -.array table td.widget { - padding: 6px 0px 10px 10px; -} -.array table td.widget .form-group { - margin: 0; -} -.array table tr:last-of-type > td { - border: 0; -} -.array table th { - vertical-align: middle; - background: none; -} -.array table td { - background: none; -} -.array table thead { - height: 30px; - background-color: rgba(0, 128, 255, 0.1019607843); -} -.array table thead tr th { - padding-left: 10px; - border: 0; -} -.array table th.head_actions, -.array table td.actions { - width: 5.5em; -} -.array table .field ~ .field { - margin-top: 10px; -} -.array .array_actions { - display: inline-block; - width: 5.5em; -} -.array .array_actions > a { - float: right; - background: none; - margin-left: 2px; -} -.array .array_actions > a.array_row_up_disabled, .array .array_actions > a.array_row_down_disabled { - opacity: 0.4; - filter: alpha(opacity=40); -} -.array .array_actions span { - color: var(--yafowil-accent-color, #0d6efd); -} - -@keyframes boxShadowAnimation { - 30% { - background: rgba(0, 128, 255, 0.1019607843); - } -} -.row-moved { - animation: boxShadowAnimation 1000ms; -} +.arraytemplate{display:none}.array table{margin-bottom:0}.array table td.widget{padding:6px 0 10px 10px}.array table td.widget .form-group{margin:0}.array table tr:last-of-type>td{border:0}.array table th{background:none;vertical-align:middle}.array table td{background:none}.array table thead{background-color:rgba(0,128,255,.102);height:30px}.array table thead tr th{border:0;padding-left:10px}.array table td.actions,.array table th.head_actions{width:5.5em}.array table .field~.field{margin-top:10px}.array .array_actions{display:inline-block;width:5.5em}.array .array_actions>a{background:none;float:right;margin-left:2px}.array .array_actions>a.array_row_down_disabled,.array .array_actions>a.array_row_up_disabled{filter:alpha(opacity=40);opacity:.4}.array .array_actions span{color:var(--yafowil-accent-color,#0d6efd)}@keyframes boxShadowAnimation{30%{background:rgba(0,128,255,.102)}}.row-moved{animation:boxShadowAnimation 1s} \ No newline at end of file diff --git a/src/yafowil/widget/array/tests/test_widget.py b/src/yafowil/widget/array/tests/test_widget.py index 92b0799..a6b6865 100644 --- a/src/yafowil/widget/array/tests/test_widget.py +++ b/src/yafowil/widget/array/tests/test_widget.py @@ -67,7 +67,7 @@ def test_empty_array(self): self.checkOutput("""
-
@@ -126,7 +126,7 @@ def test_empty_array_with_add_action_disabled(self): self.checkOutput(""" -
+
@@ -249,19 +249,19 @@ def test_empty_static_array(self): ]) self.checkOutput(""" - -
-
- - - - - - -
My Array
-
-
+
+
+ + + + + + + +
My Array
+
+
""", fxml(form())) def test_empty_array_with_compound_as_template(self): @@ -313,7 +313,7 @@ def test_empty_array_with_compound_as_template(self): self.checkOutput("""
-
... @@ -372,13 +372,13 @@ def test_empty_array_with_array_as_template(self): self.checkOutput(""" -
...
-
... @@ -440,7 +440,7 @@ def test_array_with_preset_values_disable_add_action(self): self.checkOutput(""" -
+
@@ -502,7 +502,7 @@ def test_array_with_preset_values_disable_sort_actions(self): self.checkOutput(""" -
+
@@ -566,7 +566,7 @@ def test_array_with_preset_values_disable_all_actions(self): self.checkOutput(""" -
+
@@ -627,38 +627,38 @@ def test_static_array_with_preset_values(self): ]) self.checkOutput(""" - -
-
- - - - - - - - - - - - - -
My Array
-
- - -
-
-
- - -
-
-
- +
+
+ + + + + + + + + + + + + + +
My Array
+
+ + +
+
+
+ + +
+
+
+
""", fxml(form())) def test_array_with_preset_value_as_list(self): @@ -677,7 +677,7 @@ def test_array_with_preset_value_as_list(self): self.checkOutput("""
-
@@ -771,7 +771,7 @@ def test_array_with_preset_value_as_dict(self): self.checkOutput(""" -
@@ -831,7 +831,7 @@ def test_array_with_compounds_default_values(self): self.checkOutput(""" -
@@ -908,7 +908,7 @@ def test_array_with_array_default_values_set(self): self.checkOutput(""" -
@@ -917,7 +917,7 @@ def test_array_with_array_default_values_set(self):
-
@@ -972,7 +972,7 @@ def test_array_with_array_default_values_set(self):
-
...
@@ -984,7 +984,7 @@ def test_array_with_array_default_values_set(self):
-
@@ -1109,7 +1109,7 @@ def test_array_with_array_with_compound_default_values_set(self): self.checkOutput(""" -
@@ -1121,7 +1121,7 @@ def test_array_with_array_with_compound_default_values_set(self):
-
@@ -1183,7 +1183,7 @@ def test_array_with_array_with_compound_default_values_set(self):
-
@@ -1481,7 +1481,7 @@ def test_array_required_extraction(self):
Array is required
-
+
...
@@ -1531,7 +1531,7 @@ def test_array_field_required_extraction(self): self.checkOutput(""" -
... @@ -1864,7 +1864,7 @@ def test_array_hidden_proxy_for_display_mode_children(self): self.checkOutput(""" -
... @@ -1909,7 +1909,7 @@ def test_callable_array_label(self): self.checkOutput(""" -
@@ -1984,7 +1984,7 @@ def test_3_dimensional_array(self): self.checkOutput(""" -
@@ -1996,7 +1996,7 @@ def test_3_dimensional_array(self):
-
@@ -2008,7 +2008,7 @@ def test_3_dimensional_array(self):
-
@@ -2054,7 +2054,7 @@ def test_3_dimensional_array(self):
-
+
@@ -2089,7 +2089,7 @@ def test_3_dimensional_array(self):
-
@@ -2101,7 +2101,7 @@ def test_3_dimensional_array(self):
-
@@ -2141,7 +2141,7 @@ def test_resources(self): self.assertTrue(scripts[0].directory.endswith(np('/array/resources'))) self.assertEqual(scripts[0].path, 'yafowil-array') - self.assertEqual(scripts[0].file_name, 'widget.min.js') + self.assertEqual(scripts[0].file_name, 'default/widget.min.js') self.assertTrue(os.path.exists(scripts[0].file_path)) styles = resources.styles @@ -2165,7 +2165,7 @@ def test_resources(self): self.assertTrue(scripts[0].directory.endswith(np('/array/resources'))) self.assertEqual(scripts[0].path, 'yafowil-array') - self.assertEqual(scripts[0].file_name, 'widget.min.js') + self.assertEqual(scripts[0].file_name, 'default/widget.min.js') self.assertTrue(os.path.exists(scripts[0].file_path)) styles = resources.styles @@ -2189,7 +2189,7 @@ def test_resources(self): self.assertTrue(scripts[0].directory.endswith(np('/array/resources'))) self.assertEqual(scripts[0].path, 'yafowil-array') - self.assertEqual(scripts[0].file_name, 'widget.min.js') + self.assertEqual(scripts[0].file_name, 'default/widget.min.js') self.assertTrue(os.path.exists(scripts[0].file_path)) styles = resources.styles From 1fd70570faddc618cc6ac71813c5cdae6d027d14 Mon Sep 17 00:00:00 2001 From: Lena Daxenbichler Date: Fri, 25 Oct 2024 13:02:13 +0200 Subject: [PATCH 09/17] set minimum python version for gh actions to 3.8 --- .github/workflows/test_py.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/test_py.yaml b/.github/workflows/test_py.yaml index caa084c..76a3fab 100644 --- a/.github/workflows/test_py.yaml +++ b/.github/workflows/test_py.yaml @@ -16,8 +16,6 @@ jobs: - macos-latest python: - - "2.7" - - "3.7" - "3.8" - "3.9" - "3.10" From 0455329890cd1ffb1f3bce13a9764982dfa90dfb Mon Sep 17 00:00:00 2001 From: Lena Daxenbichler Date: Mon, 4 Nov 2024 11:55:53 +0100 Subject: [PATCH 10/17] cleanup --- js/rollup.conf.js | 15 +++++--- src/yafowil/widget/array/__init__.py | 35 ++++++++++--------- .../bootstrap/{widget.css => widget.min.css} | 0 .../bootstrap5/{widget.css => widget.min.css} | 0 .../default/{widget.css => widget.min.css} | 0 .../plone5/{widget.css => widget.min.css} | 0 src/yafowil/widget/array/tests/test_widget.py | 18 +++++----- 7 files changed, 38 insertions(+), 30 deletions(-) rename src/yafowil/widget/array/resources/bootstrap/{widget.css => widget.min.css} (100%) rename src/yafowil/widget/array/resources/bootstrap5/{widget.css => widget.min.css} (100%) rename src/yafowil/widget/array/resources/default/{widget.css => widget.min.css} (100%) rename src/yafowil/widget/array/resources/plone5/{widget.css => widget.min.css} (100%) diff --git a/js/rollup.conf.js b/js/rollup.conf.js index ca156f0..dd2fea1 100644 --- a/js/rollup.conf.js +++ b/js/rollup.conf.js @@ -10,6 +10,7 @@ window.yafowil.array = exports; `; export default args => { + let conf = []; //////////////////////////////////////////////////////////////////////////// // DEFAULT @@ -53,7 +54,7 @@ export default args => { input: ['scss/default/widget.scss'], output: [ { - file: `${out_dir}/default/widget.css`, + file: `${out_dir}/default/widget.min.css`, format: 'es', plugins: [terser()], }, @@ -68,6 +69,7 @@ export default args => { }), ], }; + conf.push(bundle_default, scss_default); //////////////////////////////////////////////////////////////////////////// // BOOTSTRAP @@ -77,7 +79,7 @@ export default args => { input: ['scss/bootstrap/widget.scss'], output: [ { - file: `${out_dir}/bootstrap/widget.css`, + file: `${out_dir}/bootstrap/widget.min.css`, format: 'es', plugins: [terser()], }, @@ -92,6 +94,7 @@ export default args => { }), ], }; + conf.push(scss_bootstrap); //////////////////////////////////////////////////////////////////////////// // PLONE5 @@ -101,7 +104,7 @@ export default args => { input: ['scss/plone5/widget.scss'], output: [ { - file: `${out_dir}/plone5/widget.css`, + file: `${out_dir}/plone5/widget.min.css`, format: 'es', plugins: [terser()], }, @@ -116,6 +119,7 @@ export default args => { }), ], }; + conf.push(scss_plone5); //////////////////////////////////////////////////////////////////////////// // BOOTSTRAP5 @@ -158,7 +162,7 @@ export default args => { let scss_bs5 = { input: ['scss/bootstrap5/widget.scss'], output: [{ - file: `${out_dir}/bootstrap5/widget.css`, + file: `${out_dir}/bootstrap5/widget.min.css`, format: 'es', plugins: [terser()], }], @@ -172,6 +176,7 @@ export default args => { }), ], }; + conf.push(bundle_bs5, scss_bs5); - return [bundle_default, scss_default, scss_bootstrap, scss_plone5, bundle_bs5, scss_bs5]; + return conf; }; diff --git a/src/yafowil/widget/array/__init__.py b/src/yafowil/widget/array/__init__.py index d2d9e65..d259e6f 100644 --- a/src/yafowil/widget/array/__init__.py +++ b/src/yafowil/widget/array/__init__.py @@ -15,9 +15,10 @@ array_js = wr.ScriptResource( name='yafowil-array-js', + directory=os.path.join(resources_dir, 'default'), depends='jquery-js', - resource='default/widget.js', - compressed='default/widget.min.js' + resource='widget.js', + compressed='widget.min.js' ) # B/C resources ############################################################## @@ -45,14 +46,14 @@ name='yafowil-array-css', directory=os.path.join(resources_dir, 'default'), path='yafowil-array/default', - resource='widget.css' + resource='widget.min.css' )) # B/C resources ############################################################## default_css = [{ 'group': 'yafowil.widget.array.common', - 'resource': 'default/widget.css', + 'resource': 'default/widget.min.css', 'order': 20, }] @@ -73,14 +74,14 @@ name='yafowil-array-css', directory=os.path.join(resources_dir, 'bootstrap'), path='yafowil-array/bootstrap', - resource='widget.css' + resource='widget.min.css' )) # B/C resources ############################################################## bootstrap_css = [{ 'group': 'yafowil.widget.array.common', - 'resource': 'bootstrap/widget.css', + 'resource': 'bootstrap/widget.min.css', 'order': 20, }] @@ -90,30 +91,32 @@ ############################################################################## # webresource ################################################################ -bootstrap5_js = wr.ScriptResource( - name='yafowil-array-js', - depends='jquery-js', - resource='bootstrap5/widget.js', - compressed='bootstrap5/widget.min.js' -) bootstrap5_resources = wr.ResourceGroup( name='yafowil.widget.array', directory=resources_dir, path='yafowil-array' ) +bootstrap5_js = wr.ScriptResource( + name='yafowil-array-js', + directory=os.path.join(resources_dir, 'bootstrap5'), + path='yafowil-array/bootstrap5', + depends='jquery-js', + resource='widget.js', + compressed='widget.min.js' +) bootstrap5_resources.add(bootstrap5_js) bootstrap5_resources.add(wr.StyleResource( name='yafowil-array-css', directory=os.path.join(resources_dir, 'bootstrap5'), path='yafowil-array/bootstrap5', - resource='widget.css' + resource='widget.min.css' )) # B/C resources ############################################################## bootstrap5_css = [{ 'group': 'yafowil.widget.array.common', - 'resource': 'bootstrap5/widget.css', + 'resource': 'bootstrap5/widget.min.css', 'order': 20, }] @@ -135,14 +138,14 @@ name='yafowil-array-css', directory=os.path.join(resources_dir, 'plone5'), path='yafowil-array/plone5', - resource='widget.css' + resource='widget.min.css' )) # B/C resources ############################################################## plone5_css = [{ 'group': 'yafowil.widget.array.common', - 'resource': 'plone5/widget.css', + 'resource': 'plone5/widget.min.css', 'order': 20, }] diff --git a/src/yafowil/widget/array/resources/bootstrap/widget.css b/src/yafowil/widget/array/resources/bootstrap/widget.min.css similarity index 100% rename from src/yafowil/widget/array/resources/bootstrap/widget.css rename to src/yafowil/widget/array/resources/bootstrap/widget.min.css diff --git a/src/yafowil/widget/array/resources/bootstrap5/widget.css b/src/yafowil/widget/array/resources/bootstrap5/widget.min.css similarity index 100% rename from src/yafowil/widget/array/resources/bootstrap5/widget.css rename to src/yafowil/widget/array/resources/bootstrap5/widget.min.css diff --git a/src/yafowil/widget/array/resources/default/widget.css b/src/yafowil/widget/array/resources/default/widget.min.css similarity index 100% rename from src/yafowil/widget/array/resources/default/widget.css rename to src/yafowil/widget/array/resources/default/widget.min.css diff --git a/src/yafowil/widget/array/resources/plone5/widget.css b/src/yafowil/widget/array/resources/plone5/widget.min.css similarity index 100% rename from src/yafowil/widget/array/resources/plone5/widget.css rename to src/yafowil/widget/array/resources/plone5/widget.min.css diff --git a/src/yafowil/widget/array/tests/test_widget.py b/src/yafowil/widget/array/tests/test_widget.py index a6b6865..c71bf69 100644 --- a/src/yafowil/widget/array/tests/test_widget.py +++ b/src/yafowil/widget/array/tests/test_widget.py @@ -2139,9 +2139,9 @@ def test_resources(self): scripts = resources.scripts self.assertEqual(len(scripts), 1) - self.assertTrue(scripts[0].directory.endswith(np('/array/resources'))) + self.assertTrue(scripts[0].directory.endswith(np('/array/resources/default'))) self.assertEqual(scripts[0].path, 'yafowil-array') - self.assertEqual(scripts[0].file_name, 'default/widget.min.js') + self.assertEqual(scripts[0].file_name, 'widget.min.js') self.assertTrue(os.path.exists(scripts[0].file_path)) styles = resources.styles @@ -2151,7 +2151,7 @@ def test_resources(self): styles[0].directory.endswith(np('/array/resources/default')) ) self.assertEqual(styles[0].path, 'yafowil-array/default') - self.assertEqual(styles[0].file_name, 'widget.css') + self.assertEqual(styles[0].file_name, 'widget.min.css') self.assertTrue(os.path.exists(styles[0].file_path)) factory.theme = 'bootstrap3' @@ -2163,9 +2163,9 @@ def test_resources(self): scripts = resources.scripts self.assertEqual(len(scripts), 1) - self.assertTrue(scripts[0].directory.endswith(np('/array/resources'))) + self.assertTrue(scripts[0].directory.endswith(np('/array/resources/default'))) self.assertEqual(scripts[0].path, 'yafowil-array') - self.assertEqual(scripts[0].file_name, 'default/widget.min.js') + self.assertEqual(scripts[0].file_name, 'widget.min.js') self.assertTrue(os.path.exists(scripts[0].file_path)) styles = resources.styles @@ -2175,7 +2175,7 @@ def test_resources(self): styles[0].directory.endswith(np('/array/resources/bootstrap')) ) self.assertEqual(styles[0].path, 'yafowil-array/bootstrap') - self.assertEqual(styles[0].file_name, 'widget.css') + self.assertEqual(styles[0].file_name, 'widget.min.css') self.assertTrue(os.path.exists(styles[0].file_path)) factory.theme = 'plone5' @@ -2187,9 +2187,9 @@ def test_resources(self): scripts = resources.scripts self.assertEqual(len(scripts), 1) - self.assertTrue(scripts[0].directory.endswith(np('/array/resources'))) + self.assertTrue(scripts[0].directory.endswith(np('/array/resources/default'))) self.assertEqual(scripts[0].path, 'yafowil-array') - self.assertEqual(scripts[0].file_name, 'default/widget.min.js') + self.assertEqual(scripts[0].file_name, 'widget.min.js') self.assertTrue(os.path.exists(scripts[0].file_path)) styles = resources.styles @@ -2199,5 +2199,5 @@ def test_resources(self): styles[0].directory.endswith(np('/array/resources/plone5')) ) self.assertEqual(styles[0].path, 'yafowil-array/plone5') - self.assertEqual(styles[0].file_name, 'widget.css') + self.assertEqual(styles[0].file_name, 'widget.min.css') self.assertTrue(os.path.exists(styles[0].file_path)) From c86515ce2ceaad8efb4b52a096edb6766448143f Mon Sep 17 00:00:00 2001 From: Lena Daxenbichler Date: Mon, 4 Nov 2024 12:55:36 +0100 Subject: [PATCH 11/17] more cleanup --- src/yafowil/widget/array/__init__.py | 1 + src/yafowil/widget/array/tests/test_widget.py | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/yafowil/widget/array/__init__.py b/src/yafowil/widget/array/__init__.py index d259e6f..d64e43f 100644 --- a/src/yafowil/widget/array/__init__.py +++ b/src/yafowil/widget/array/__init__.py @@ -16,6 +16,7 @@ array_js = wr.ScriptResource( name='yafowil-array-js', directory=os.path.join(resources_dir, 'default'), + path='yafowil-array/default', depends='jquery-js', resource='widget.js', compressed='widget.min.js' diff --git a/src/yafowil/widget/array/tests/test_widget.py b/src/yafowil/widget/array/tests/test_widget.py index c71bf69..9a0a6ba 100644 --- a/src/yafowil/widget/array/tests/test_widget.py +++ b/src/yafowil/widget/array/tests/test_widget.py @@ -2140,7 +2140,7 @@ def test_resources(self): self.assertEqual(len(scripts), 1) self.assertTrue(scripts[0].directory.endswith(np('/array/resources/default'))) - self.assertEqual(scripts[0].path, 'yafowil-array') + self.assertEqual(scripts[0].path, 'yafowil-array/default') self.assertEqual(scripts[0].file_name, 'widget.min.js') self.assertTrue(os.path.exists(scripts[0].file_path)) @@ -2164,7 +2164,7 @@ def test_resources(self): self.assertEqual(len(scripts), 1) self.assertTrue(scripts[0].directory.endswith(np('/array/resources/default'))) - self.assertEqual(scripts[0].path, 'yafowil-array') + self.assertEqual(scripts[0].path, 'yafowil-array/default') self.assertEqual(scripts[0].file_name, 'widget.min.js') self.assertTrue(os.path.exists(scripts[0].file_path)) @@ -2188,7 +2188,7 @@ def test_resources(self): self.assertEqual(len(scripts), 1) self.assertTrue(scripts[0].directory.endswith(np('/array/resources/default'))) - self.assertEqual(scripts[0].path, 'yafowil-array') + self.assertEqual(scripts[0].path, 'yafowil-array/default') self.assertEqual(scripts[0].file_name, 'widget.min.js') self.assertTrue(os.path.exists(scripts[0].file_path)) From 9465805908ee92546502c152074149f6609eb35d Mon Sep 17 00:00:00 2001 From: Lena Daxenbichler Date: Tue, 5 Nov 2024 09:31:43 +0100 Subject: [PATCH 12/17] Add glowing effect when adding a row. --- js/src/bootstrap5/widget.js | 13 +++++++++++-- .../widget/array/resources/bootstrap5/widget.js | 12 ++++++++++-- .../widget/array/resources/bootstrap5/widget.min.js | 2 +- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/js/src/bootstrap5/widget.js b/js/src/bootstrap5/widget.js index 02cd312..750120d 100644 --- a/js/src/bootstrap5/widget.js +++ b/js/src/bootstrap5/widget.js @@ -57,7 +57,7 @@ export class ArrayWidget extends ArrayBase { up_handle(evt) { super.up_handle(evt); - let row = this.get_row(evt.currentTarget); + const row = this.get_row(evt.currentTarget); row.addClass('row-moved'); setTimeout(function() { row.removeClass('row-moved'); @@ -66,10 +66,19 @@ export class ArrayWidget extends ArrayBase { down_handle(evt) { super.down_handle(evt); - let row = this.get_row(evt.currentTarget); + const row = this.get_row(evt.currentTarget); row.addClass('row-moved'); setTimeout(function() { row.removeClass('row-moved'); }, 1000); } + + create_row() { + const row = super.create_row(); + row.addClass('row-moved'); + setTimeout(function() { + row.removeClass('row-moved'); + }, 1000); + return row; + } } diff --git a/src/yafowil/widget/array/resources/bootstrap5/widget.js b/src/yafowil/widget/array/resources/bootstrap5/widget.js index 84b68b1..12ed490 100644 --- a/src/yafowil/widget/array/resources/bootstrap5/widget.js +++ b/src/yafowil/widget/array/resources/bootstrap5/widget.js @@ -234,7 +234,7 @@ var yafowil_array = (function (exports, $) { } up_handle(evt) { super.up_handle(evt); - let row = this.get_row(evt.currentTarget); + const row = this.get_row(evt.currentTarget); row.addClass('row-moved'); setTimeout(function() { row.removeClass('row-moved'); @@ -242,12 +242,20 @@ var yafowil_array = (function (exports, $) { } down_handle(evt) { super.down_handle(evt); - let row = this.get_row(evt.currentTarget); + const row = this.get_row(evt.currentTarget); row.addClass('row-moved'); setTimeout(function() { row.removeClass('row-moved'); }, 1000); } + create_row() { + const row = super.create_row(); + row.addClass('row-moved'); + setTimeout(function() { + row.removeClass('row-moved'); + }, 1000); + return row; + } } $(function() { diff --git a/src/yafowil/widget/array/resources/bootstrap5/widget.min.js b/src/yafowil/widget/array/resources/bootstrap5/widget.min.js index 9ce7e3d..5723316 100644 --- a/src/yafowil/widget/array/resources/bootstrap5/widget.min.js +++ b/src/yafowil/widget/array/resources/bootstrap5/widget.min.js @@ -1 +1 @@ -var yafowil_array=function(e,r){"use strict";class t{constructor(e){e.data("yafowil-array",this),this.wrapper=e;let t=r("> table",e),a=r("> thead .array_actions",t),i=this.add_first_handle.bind(this);this.table=t,r("a.array_row_add",a).off().on("click",i),this.bind_actions()}bind_actions(){let e=r("> tbody > tr > td.actions .array_actions",this.table),t=this.add_handle.bind(this),a=this.remove_handle.bind(this),i=this.up_handle.bind(this),s=this.down_handle.bind(this);this.mark_disabled(e),r("a.array_row_add",e).off().on("click",t),r("a.array_row_remove",e).off().on("click",a),r("a.array_row_up",e).off().on("click",i),r("a.array_row_down",e).off().on("click",s)}mark_disabled(e){r("a.array_row_up",e).removeClass("array_row_up_disabled").first().addClass("array_row_up_disabled"),r("a.array_row_down",e).removeClass("array_row_down_disabled").last().addClass("array_row_down_disabled")}create_row(){let e=this.wrapper.attr("class"),t="";t+="",t+='",-1===e.indexOf("array-static")&&(t+='"),t+="",t=r(t);let a=r("> .arraytemplate",this.wrapper).clone();return r(".widget",t).append(a.children()),t}get_row(e){return r(e).parent().parent().parent()}get base_id(){let e=this.wrapper.attr("id");return e.substring(6,e.length)}trigger(e,...r){let t=this.hooks[e.substring(3,e.length)];if(Object.entries(t).length){console.log("Array hooks are deprecated. Use ``on_array_event`` instead.");for(let e in t)console.log(` - ${e}`),t[e].apply(null,r)}r.splice(0,0,this);for(let t of this._array_subscribers[e])t.apply(null,r)}reset_indices(e){let t,a=0,i=this.base_id,s=this;e.children().each((function(){t=r(this),s.set_row_index(t,i,a),s.trigger("on_index",t,a),a++})),this.bind_actions()}set_row_index(e,t,a){let i,s=t.replace(/\-/g,"."),n=this.set_attr_index.bind(this),o=this;e.children().each((function(){i=r(this),n(i,"id",t,a,"-"),n(i,"for",t,a,"-"),n(i,"name",s,a,"."),o.set_row_index(i,t,a)}))}set_attr_index(e,r,t,a,i){let s=e.attr(r);s&&s.indexOf(t)>-1&&e.attr(r,this.set_value_index(s,t,a,i))}set_value_index(e,r,t,a){let i=e.indexOf(r)+r.length+1,s=e.indexOf(a,i),n=e.substring(0,i),o="";return s>-1&&(o=e.substring(s,e.length)),n+t+o}init_row(e,r){this.reset_indices(e),this.array_widget.initialize(r),this.trigger("on_add",r)}add_first_handle(e){e.preventDefault();let t=this.create_row(),a=r("> tbody",this.table);this.trigger("on_before_add",t,a),a.prepend(t),this.init_row(a,t)}add_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget),t=this.create_row(),a=r.parent();this.trigger("on_before_add",t,a),r.after(t),this.init_row(a,t)}remove_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget);this.trigger("on_remove",r);let t=r.parent();r.remove(),this.reset_indices(t)}up_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget);this.trigger("on_before_up",r),r.insertBefore(r.prev()),this.reset_indices(r.parent()),this.trigger("on_up",r)}down_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget);this.trigger("on_before_down",r),r.insertAfter(r.next()),this.reset_indices(r.parent()),this.trigger("on_down",r)}}let a={before_add:{},add:{},remove:{},before_up:{},up:{},before_down:{},down:{},index:{}},i={on_before_add:[],on_add:[],on_remove:[],on_before_up:[],on_up:[],on_before_down:[],on_down:[],on_index:[]};class s extends t{static initialize(e){r("div.array",e).each((function(){let e=r(this);-1===e.attr("id").indexOf("-TEMPLATE")&&new s(e)}))}constructor(e){super(e),this.hooks=a,this._array_subscribers=i,this.array_widget=s,this.icon_add="bi-plus-circle-fill",this.icon_remove="bi-dash-circle-fill",this.icon_up="bi-arrow-up-circle-fill",this.icon_down="bi-arrow-down-circle-fill"}up_handle(e){super.up_handle(e);let r=this.get_row(e.currentTarget);r.addClass("row-moved"),setTimeout((function(){r.removeClass("row-moved")}),1e3)}down_handle(e){super.down_handle(e);let r=this.get_row(e.currentTarget);r.addClass("row-moved"),setTimeout((function(){r.removeClass("row-moved")}),1e3)}}return r((function(){void 0!==window.ts?ts.ajax.register(s.initialize,!0):void 0!==window.bdajax?bdajax.register(s.initialize,!0):s.initialize()})),e.ArrayWidget=s,e.hooks=a,e.inside_template=function(e){return e.parents(".arraytemplate").length>0},e.on_array_event=function(e,r){i[e].push(r)},Object.defineProperty(e,"__esModule",{value:!0}),window.yafowil=window.yafowil||{},window.yafowil.array=e,e}({},jQuery); +var yafowil_array=function(e,r){"use strict";class t{constructor(e){e.data("yafowil-array",this),this.wrapper=e;let t=r("> table",e),a=r("> thead .array_actions",t),i=this.add_first_handle.bind(this);this.table=t,r("a.array_row_add",a).off().on("click",i),this.bind_actions()}bind_actions(){let e=r("> tbody > tr > td.actions .array_actions",this.table),t=this.add_handle.bind(this),a=this.remove_handle.bind(this),i=this.up_handle.bind(this),s=this.down_handle.bind(this);this.mark_disabled(e),r("a.array_row_add",e).off().on("click",t),r("a.array_row_remove",e).off().on("click",a),r("a.array_row_up",e).off().on("click",i),r("a.array_row_down",e).off().on("click",s)}mark_disabled(e){r("a.array_row_up",e).removeClass("array_row_up_disabled").first().addClass("array_row_up_disabled"),r("a.array_row_down",e).removeClass("array_row_down_disabled").last().addClass("array_row_down_disabled")}create_row(){let e=this.wrapper.attr("class"),t="";t+="",t+='",-1===e.indexOf("array-static")&&(t+='"),t+="",t=r(t);let a=r("> .arraytemplate",this.wrapper).clone();return r(".widget",t).append(a.children()),t}get_row(e){return r(e).parent().parent().parent()}get base_id(){let e=this.wrapper.attr("id");return e.substring(6,e.length)}trigger(e,...r){let t=this.hooks[e.substring(3,e.length)];if(Object.entries(t).length){console.log("Array hooks are deprecated. Use ``on_array_event`` instead.");for(let e in t)console.log(` - ${e}`),t[e].apply(null,r)}r.splice(0,0,this);for(let t of this._array_subscribers[e])t.apply(null,r)}reset_indices(e){let t,a=0,i=this.base_id,s=this;e.children().each((function(){t=r(this),s.set_row_index(t,i,a),s.trigger("on_index",t,a),a++})),this.bind_actions()}set_row_index(e,t,a){let i,s=t.replace(/\-/g,"."),n=this.set_attr_index.bind(this),o=this;e.children().each((function(){i=r(this),n(i,"id",t,a,"-"),n(i,"for",t,a,"-"),n(i,"name",s,a,"."),o.set_row_index(i,t,a)}))}set_attr_index(e,r,t,a,i){let s=e.attr(r);s&&s.indexOf(t)>-1&&e.attr(r,this.set_value_index(s,t,a,i))}set_value_index(e,r,t,a){let i=e.indexOf(r)+r.length+1,s=e.indexOf(a,i),n=e.substring(0,i),o="";return s>-1&&(o=e.substring(s,e.length)),n+t+o}init_row(e,r){this.reset_indices(e),this.array_widget.initialize(r),this.trigger("on_add",r)}add_first_handle(e){e.preventDefault();let t=this.create_row(),a=r("> tbody",this.table);this.trigger("on_before_add",t,a),a.prepend(t),this.init_row(a,t)}add_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget),t=this.create_row(),a=r.parent();this.trigger("on_before_add",t,a),r.after(t),this.init_row(a,t)}remove_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget);this.trigger("on_remove",r);let t=r.parent();r.remove(),this.reset_indices(t)}up_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget);this.trigger("on_before_up",r),r.insertBefore(r.prev()),this.reset_indices(r.parent()),this.trigger("on_up",r)}down_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget);this.trigger("on_before_down",r),r.insertAfter(r.next()),this.reset_indices(r.parent()),this.trigger("on_down",r)}}let a={before_add:{},add:{},remove:{},before_up:{},up:{},before_down:{},down:{},index:{}},i={on_before_add:[],on_add:[],on_remove:[],on_before_up:[],on_up:[],on_before_down:[],on_down:[],on_index:[]};class s extends t{static initialize(e){r("div.array",e).each((function(){let e=r(this);-1===e.attr("id").indexOf("-TEMPLATE")&&new s(e)}))}constructor(e){super(e),this.hooks=a,this._array_subscribers=i,this.array_widget=s,this.icon_add="bi-plus-circle-fill",this.icon_remove="bi-dash-circle-fill",this.icon_up="bi-arrow-up-circle-fill",this.icon_down="bi-arrow-down-circle-fill"}up_handle(e){super.up_handle(e);const r=this.get_row(e.currentTarget);r.addClass("row-moved"),setTimeout((function(){r.removeClass("row-moved")}),1e3)}down_handle(e){super.down_handle(e);const r=this.get_row(e.currentTarget);r.addClass("row-moved"),setTimeout((function(){r.removeClass("row-moved")}),1e3)}create_row(){const e=super.create_row();return e.addClass("row-moved"),setTimeout((function(){e.removeClass("row-moved")}),1e3),e}}return r((function(){void 0!==window.ts?ts.ajax.register(s.initialize,!0):void 0!==window.bdajax?bdajax.register(s.initialize,!0):s.initialize()})),e.ArrayWidget=s,e.hooks=a,e.inside_template=function(e){return e.parents(".arraytemplate").length>0},e.on_array_event=function(e,r){i[e].push(r)},Object.defineProperty(e,"__esModule",{value:!0}),window.yafowil=window.yafowil||{},window.yafowil.array=e,e}({},jQuery); From 6f797e387b0b64cea72aec8f1ef7dee084455e32 Mon Sep 17 00:00:00 2001 From: Lena Daxenbichler Date: Tue, 5 Nov 2024 12:53:19 +0100 Subject: [PATCH 13/17] documentation --- js/src/bootstrap5/widget.js | 49 ++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/js/src/bootstrap5/widget.js b/js/src/bootstrap5/widget.js index 750120d..8f9017d 100644 --- a/js/src/bootstrap5/widget.js +++ b/js/src/bootstrap5/widget.js @@ -1,7 +1,9 @@ import $ from 'jquery'; -import {ArrayBase} from '../array.js'; +import { ArrayBase } from '../array.js'; -// B/C. Deprecated. Use ``on_array_event`` +/** + * Legacy hooks object for backward compatibility, providing deprecated event hooks. + */ export let hooks = { before_add: {}, add: {}, @@ -13,7 +15,9 @@ export let hooks = { index: {} }; -// global array subscribers, gets called from every array instance +/** + * Global subscribers for array events, called by each array instance. + */ let _array_subscribers = { on_before_add: [], on_add: [], @@ -23,18 +27,27 @@ let _array_subscribers = { on_before_down: [], on_down: [], on_index: [] -} +}; +/** + * Registers a subscriber to a specified array event. + */ export function on_array_event(event, subscriber) { - _array_subscribers[event].push(subscriber) + _array_subscribers[event].push(subscriber); } +/** + * Checks if the specified element is within an array template. + */ export function inside_template(elem) { - return elem.parents('.arraytemplate').length > 0 + return elem.parents('.arraytemplate').length > 0; } export class ArrayWidget extends ArrayBase { + /** + * @param {HTMLElement} context - DOM context for widget initialization. + */ static initialize(context) { $('div.array', context).each(function() { let wrapper = $(this); @@ -44,6 +57,9 @@ export class ArrayWidget extends ArrayBase { }); } + /** + * @param {jQuery} wrapper - The jQuery-wrapped element to initialize. + */ constructor(wrapper) { super(wrapper); this.hooks = hooks; @@ -55,28 +71,43 @@ export class ArrayWidget extends ArrayBase { this.icon_down = 'bi-arrow-down-circle-fill'; } + /** + * Handles the event for moving a row up and applies a visual effect. + * + * @param {Event} evt + */ up_handle(evt) { super.up_handle(evt); const row = this.get_row(evt.currentTarget); row.addClass('row-moved'); - setTimeout(function() { + setTimeout(() => { row.removeClass('row-moved'); }, 1000); } + /** + * Handles the event for moving a row down and applies a visual effect. + * + * @param {Event} evt + */ down_handle(evt) { super.down_handle(evt); const row = this.get_row(evt.currentTarget); row.addClass('row-moved'); - setTimeout(function() { + setTimeout(() => { row.removeClass('row-moved'); }, 1000); } + /** + * Creates a new row with a visual effect. + * + * @returns {jQuery} - The created row element. + */ create_row() { const row = super.create_row(); row.addClass('row-moved'); - setTimeout(function() { + setTimeout(() => { row.removeClass('row-moved'); }, 1000); return row; From ba091b3389395059948596d6cbde87bcc9b6dc1c Mon Sep 17 00:00:00 2001 From: Lena Daxenbichler Date: Thu, 7 Nov 2024 09:15:52 +0100 Subject: [PATCH 14/17] some formatting --- js/src/{ => base}/array.js | 0 js/src/bootstrap5/widget.js | 35 +++++++++++-------- js/src/default/widget.js | 2 +- .../array/resources/bootstrap5/widget.js | 19 +++++----- .../array/resources/bootstrap5/widget.min.js | 2 +- 5 files changed, 30 insertions(+), 28 deletions(-) rename js/src/{ => base}/array.js (100%) diff --git a/js/src/array.js b/js/src/base/array.js similarity index 100% rename from js/src/array.js rename to js/src/base/array.js diff --git a/js/src/bootstrap5/widget.js b/js/src/bootstrap5/widget.js index 8f9017d..1c19be9 100644 --- a/js/src/bootstrap5/widget.js +++ b/js/src/bootstrap5/widget.js @@ -1,8 +1,8 @@ import $ from 'jquery'; -import { ArrayBase } from '../array.js'; +import { ArrayBase } from '../base/array.js'; /** - * Legacy hooks object for backward compatibility, providing deprecated event hooks. + * Legacy hooks for backward compatibility, providing deprecated event hooks. */ export let hooks = { before_add: {}, @@ -46,7 +46,9 @@ export function inside_template(elem) { export class ArrayWidget extends ArrayBase { /** - * @param {HTMLElement} context - DOM context for widget initialization. + * Initializes each widget in the given DOM context. + * + * @param {HTMLElement} context - DOM context for initialization. */ static initialize(context) { $('div.array', context).each(function() { @@ -72,44 +74,47 @@ export class ArrayWidget extends ArrayBase { } /** - * Handles the event for moving a row up and applies a visual effect. + * Handles the event for moving a row up. * * @param {Event} evt */ up_handle(evt) { super.up_handle(evt); const row = this.get_row(evt.currentTarget); - row.addClass('row-moved'); - setTimeout(() => { - row.removeClass('row-moved'); - }, 1000); + this.highlight(row); } /** - * Handles the event for moving a row down and applies a visual effect. + * Handles the event for moving a row down. * * @param {Event} evt */ down_handle(evt) { super.down_handle(evt); const row = this.get_row(evt.currentTarget); - row.addClass('row-moved'); - setTimeout(() => { - row.removeClass('row-moved'); - }, 1000); + this.highlight(row); } /** - * Creates a new row with a visual effect. + * Creates a new row. * * @returns {jQuery} - The created row element. */ create_row() { const row = super.create_row(); + this.highlight(row); + return row; + } + + /** + * Briefly highlights a row to indicate movement. + * + * @param {jQuery} row - The row to apply the effect to. + */ + highlight(row) { row.addClass('row-moved'); setTimeout(() => { row.removeClass('row-moved'); }, 1000); - return row; } } diff --git a/js/src/default/widget.js b/js/src/default/widget.js index ac9c949..004302b 100644 --- a/js/src/default/widget.js +++ b/js/src/default/widget.js @@ -1,5 +1,5 @@ import $ from 'jquery'; -import {ArrayBase} from '../array.js'; +import {ArrayBase} from '../base/array.js'; // B/C. Deprecated. Use ``on_array_event`` export let hooks = { diff --git a/src/yafowil/widget/array/resources/bootstrap5/widget.js b/src/yafowil/widget/array/resources/bootstrap5/widget.js index 12ed490..c9314f2 100644 --- a/src/yafowil/widget/array/resources/bootstrap5/widget.js +++ b/src/yafowil/widget/array/resources/bootstrap5/widget.js @@ -211,7 +211,7 @@ var yafowil_array = (function (exports, $) { _array_subscribers[event].push(subscriber); } function inside_template(elem) { - return elem.parents('.arraytemplate').length > 0 + return elem.parents('.arraytemplate').length > 0; } class ArrayWidget extends ArrayBase { static initialize(context) { @@ -235,26 +235,23 @@ var yafowil_array = (function (exports, $) { up_handle(evt) { super.up_handle(evt); const row = this.get_row(evt.currentTarget); - row.addClass('row-moved'); - setTimeout(function() { - row.removeClass('row-moved'); - }, 1000); + this.highlight(row); } down_handle(evt) { super.down_handle(evt); const row = this.get_row(evt.currentTarget); - row.addClass('row-moved'); - setTimeout(function() { - row.removeClass('row-moved'); - }, 1000); + this.highlight(row); } create_row() { const row = super.create_row(); + this.highlight(row); + return row; + } + highlight(row) { row.addClass('row-moved'); - setTimeout(function() { + setTimeout(() => { row.removeClass('row-moved'); }, 1000); - return row; } } diff --git a/src/yafowil/widget/array/resources/bootstrap5/widget.min.js b/src/yafowil/widget/array/resources/bootstrap5/widget.min.js index 5723316..bd87a43 100644 --- a/src/yafowil/widget/array/resources/bootstrap5/widget.min.js +++ b/src/yafowil/widget/array/resources/bootstrap5/widget.min.js @@ -1 +1 @@ -var yafowil_array=function(e,r){"use strict";class t{constructor(e){e.data("yafowil-array",this),this.wrapper=e;let t=r("> table",e),a=r("> thead .array_actions",t),i=this.add_first_handle.bind(this);this.table=t,r("a.array_row_add",a).off().on("click",i),this.bind_actions()}bind_actions(){let e=r("> tbody > tr > td.actions .array_actions",this.table),t=this.add_handle.bind(this),a=this.remove_handle.bind(this),i=this.up_handle.bind(this),s=this.down_handle.bind(this);this.mark_disabled(e),r("a.array_row_add",e).off().on("click",t),r("a.array_row_remove",e).off().on("click",a),r("a.array_row_up",e).off().on("click",i),r("a.array_row_down",e).off().on("click",s)}mark_disabled(e){r("a.array_row_up",e).removeClass("array_row_up_disabled").first().addClass("array_row_up_disabled"),r("a.array_row_down",e).removeClass("array_row_down_disabled").last().addClass("array_row_down_disabled")}create_row(){let e=this.wrapper.attr("class"),t="";t+="",t+='",-1===e.indexOf("array-static")&&(t+='"),t+="",t=r(t);let a=r("> .arraytemplate",this.wrapper).clone();return r(".widget",t).append(a.children()),t}get_row(e){return r(e).parent().parent().parent()}get base_id(){let e=this.wrapper.attr("id");return e.substring(6,e.length)}trigger(e,...r){let t=this.hooks[e.substring(3,e.length)];if(Object.entries(t).length){console.log("Array hooks are deprecated. Use ``on_array_event`` instead.");for(let e in t)console.log(` - ${e}`),t[e].apply(null,r)}r.splice(0,0,this);for(let t of this._array_subscribers[e])t.apply(null,r)}reset_indices(e){let t,a=0,i=this.base_id,s=this;e.children().each((function(){t=r(this),s.set_row_index(t,i,a),s.trigger("on_index",t,a),a++})),this.bind_actions()}set_row_index(e,t,a){let i,s=t.replace(/\-/g,"."),n=this.set_attr_index.bind(this),o=this;e.children().each((function(){i=r(this),n(i,"id",t,a,"-"),n(i,"for",t,a,"-"),n(i,"name",s,a,"."),o.set_row_index(i,t,a)}))}set_attr_index(e,r,t,a,i){let s=e.attr(r);s&&s.indexOf(t)>-1&&e.attr(r,this.set_value_index(s,t,a,i))}set_value_index(e,r,t,a){let i=e.indexOf(r)+r.length+1,s=e.indexOf(a,i),n=e.substring(0,i),o="";return s>-1&&(o=e.substring(s,e.length)),n+t+o}init_row(e,r){this.reset_indices(e),this.array_widget.initialize(r),this.trigger("on_add",r)}add_first_handle(e){e.preventDefault();let t=this.create_row(),a=r("> tbody",this.table);this.trigger("on_before_add",t,a),a.prepend(t),this.init_row(a,t)}add_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget),t=this.create_row(),a=r.parent();this.trigger("on_before_add",t,a),r.after(t),this.init_row(a,t)}remove_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget);this.trigger("on_remove",r);let t=r.parent();r.remove(),this.reset_indices(t)}up_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget);this.trigger("on_before_up",r),r.insertBefore(r.prev()),this.reset_indices(r.parent()),this.trigger("on_up",r)}down_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget);this.trigger("on_before_down",r),r.insertAfter(r.next()),this.reset_indices(r.parent()),this.trigger("on_down",r)}}let a={before_add:{},add:{},remove:{},before_up:{},up:{},before_down:{},down:{},index:{}},i={on_before_add:[],on_add:[],on_remove:[],on_before_up:[],on_up:[],on_before_down:[],on_down:[],on_index:[]};class s extends t{static initialize(e){r("div.array",e).each((function(){let e=r(this);-1===e.attr("id").indexOf("-TEMPLATE")&&new s(e)}))}constructor(e){super(e),this.hooks=a,this._array_subscribers=i,this.array_widget=s,this.icon_add="bi-plus-circle-fill",this.icon_remove="bi-dash-circle-fill",this.icon_up="bi-arrow-up-circle-fill",this.icon_down="bi-arrow-down-circle-fill"}up_handle(e){super.up_handle(e);const r=this.get_row(e.currentTarget);r.addClass("row-moved"),setTimeout((function(){r.removeClass("row-moved")}),1e3)}down_handle(e){super.down_handle(e);const r=this.get_row(e.currentTarget);r.addClass("row-moved"),setTimeout((function(){r.removeClass("row-moved")}),1e3)}create_row(){const e=super.create_row();return e.addClass("row-moved"),setTimeout((function(){e.removeClass("row-moved")}),1e3),e}}return r((function(){void 0!==window.ts?ts.ajax.register(s.initialize,!0):void 0!==window.bdajax?bdajax.register(s.initialize,!0):s.initialize()})),e.ArrayWidget=s,e.hooks=a,e.inside_template=function(e){return e.parents(".arraytemplate").length>0},e.on_array_event=function(e,r){i[e].push(r)},Object.defineProperty(e,"__esModule",{value:!0}),window.yafowil=window.yafowil||{},window.yafowil.array=e,e}({},jQuery); +var yafowil_array=function(e,r){"use strict";class t{constructor(e){e.data("yafowil-array",this),this.wrapper=e;let t=r("> table",e),i=r("> thead .array_actions",t),a=this.add_first_handle.bind(this);this.table=t,r("a.array_row_add",i).off().on("click",a),this.bind_actions()}bind_actions(){let e=r("> tbody > tr > td.actions .array_actions",this.table),t=this.add_handle.bind(this),i=this.remove_handle.bind(this),a=this.up_handle.bind(this),s=this.down_handle.bind(this);this.mark_disabled(e),r("a.array_row_add",e).off().on("click",t),r("a.array_row_remove",e).off().on("click",i),r("a.array_row_up",e).off().on("click",a),r("a.array_row_down",e).off().on("click",s)}mark_disabled(e){r("a.array_row_up",e).removeClass("array_row_up_disabled").first().addClass("array_row_up_disabled"),r("a.array_row_down",e).removeClass("array_row_down_disabled").last().addClass("array_row_down_disabled")}create_row(){let e=this.wrapper.attr("class"),t="";t+="",t+='",-1===e.indexOf("array-static")&&(t+='"),t+="",t=r(t);let i=r("> .arraytemplate",this.wrapper).clone();return r(".widget",t).append(i.children()),t}get_row(e){return r(e).parent().parent().parent()}get base_id(){let e=this.wrapper.attr("id");return e.substring(6,e.length)}trigger(e,...r){let t=this.hooks[e.substring(3,e.length)];if(Object.entries(t).length){console.log("Array hooks are deprecated. Use ``on_array_event`` instead.");for(let e in t)console.log(` - ${e}`),t[e].apply(null,r)}r.splice(0,0,this);for(let t of this._array_subscribers[e])t.apply(null,r)}reset_indices(e){let t,i=0,a=this.base_id,s=this;e.children().each((function(){t=r(this),s.set_row_index(t,a,i),s.trigger("on_index",t,i),i++})),this.bind_actions()}set_row_index(e,t,i){let a,s=t.replace(/\-/g,"."),n=this.set_attr_index.bind(this),o=this;e.children().each((function(){a=r(this),n(a,"id",t,i,"-"),n(a,"for",t,i,"-"),n(a,"name",s,i,"."),o.set_row_index(a,t,i)}))}set_attr_index(e,r,t,i,a){let s=e.attr(r);s&&s.indexOf(t)>-1&&e.attr(r,this.set_value_index(s,t,i,a))}set_value_index(e,r,t,i){let a=e.indexOf(r)+r.length+1,s=e.indexOf(i,a),n=e.substring(0,a),o="";return s>-1&&(o=e.substring(s,e.length)),n+t+o}init_row(e,r){this.reset_indices(e),this.array_widget.initialize(r),this.trigger("on_add",r)}add_first_handle(e){e.preventDefault();let t=this.create_row(),i=r("> tbody",this.table);this.trigger("on_before_add",t,i),i.prepend(t),this.init_row(i,t)}add_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget),t=this.create_row(),i=r.parent();this.trigger("on_before_add",t,i),r.after(t),this.init_row(i,t)}remove_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget);this.trigger("on_remove",r);let t=r.parent();r.remove(),this.reset_indices(t)}up_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget);this.trigger("on_before_up",r),r.insertBefore(r.prev()),this.reset_indices(r.parent()),this.trigger("on_up",r)}down_handle(e){e.preventDefault();let r=this.get_row(e.currentTarget);this.trigger("on_before_down",r),r.insertAfter(r.next()),this.reset_indices(r.parent()),this.trigger("on_down",r)}}let i={before_add:{},add:{},remove:{},before_up:{},up:{},before_down:{},down:{},index:{}},a={on_before_add:[],on_add:[],on_remove:[],on_before_up:[],on_up:[],on_before_down:[],on_down:[],on_index:[]};class s extends t{static initialize(e){r("div.array",e).each((function(){let e=r(this);-1===e.attr("id").indexOf("-TEMPLATE")&&new s(e)}))}constructor(e){super(e),this.hooks=i,this._array_subscribers=a,this.array_widget=s,this.icon_add="bi-plus-circle-fill",this.icon_remove="bi-dash-circle-fill",this.icon_up="bi-arrow-up-circle-fill",this.icon_down="bi-arrow-down-circle-fill"}up_handle(e){super.up_handle(e);const r=this.get_row(e.currentTarget);this.highlight(r)}down_handle(e){super.down_handle(e);const r=this.get_row(e.currentTarget);this.highlight(r)}create_row(){const e=super.create_row();return this.highlight(e),e}highlight(e){e.addClass("row-moved"),setTimeout((()=>{e.removeClass("row-moved")}),1e3)}}return r((function(){void 0!==window.ts?ts.ajax.register(s.initialize,!0):void 0!==window.bdajax?bdajax.register(s.initialize,!0):s.initialize()})),e.ArrayWidget=s,e.hooks=i,e.inside_template=function(e){return e.parents(".arraytemplate").length>0},e.on_array_event=function(e,r){a[e].push(r)},Object.defineProperty(e,"__esModule",{value:!0}),window.yafowil=window.yafowil||{},window.yafowil.array=e,e}({},jQuery); From 8c10db83924569453404d9a731fe17993ab1440f Mon Sep 17 00:00:00 2001 From: Lena Daxenbichler Date: Mon, 24 Feb 2025 13:56:39 +0100 Subject: [PATCH 15/17] fix corepack issue in CI --- .github/workflows/test_js.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/test_js.yaml b/.github/workflows/test_js.yaml index 009ed7f..54d5763 100644 --- a/.github/workflows/test_js.yaml +++ b/.github/workflows/test_js.yaml @@ -11,6 +11,11 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Corepack + run: | + npm install --global corepack@latest + corepack enable + - name: Install run: | corepack enable From bae67b6bfc7e052435f1dca171d065be5b33d5fe Mon Sep 17 00:00:00 2001 From: Lena Daxenbichler Date: Tue, 25 Feb 2025 12:06:43 +0100 Subject: [PATCH 16/17] update changelog --- CHANGES.rst | 18 +++++++++++++++++- js/src/default/widget.js | 2 +- package.json | 2 +- .../widget/array/resources/default/widget.js | 2 +- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 536ca93..90e74c5 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,7 +4,23 @@ Changes 2.0a2 (unreleased) ------------------ -- Nothing changed yet. +- Update jQuery to version ``4.0.0-beta.2``. + [lenadax] + +- Use ``bootstrap-icons`` font instead of glyphicons. + [lenadax] + +- Add visual effects to distinguish rows that have been moved or created. + [lenadax] + +- Implement dark theme for ``Bootstrap5`` dark theme mode. + [lenadax] + +- Use rollup for bundling scss. Use ``make rollup`` to compile js and scss. + [lenadax] + +- Create Bootstrap5 widget version. + [lenadax] 2.0a1 (2023-05-15) diff --git a/js/src/default/widget.js b/js/src/default/widget.js index 004302b..d301f0e 100644 --- a/js/src/default/widget.js +++ b/js/src/default/widget.js @@ -30,7 +30,7 @@ export function on_array_event(event, subscriber) { } export function inside_template(elem) { - return elem.parents('.arraytemplate').length > 0 + return elem.parents('.arraytemplate').length > 0; } export class ArrayWidget extends ArrayBase { diff --git a/package.json b/package.json index b64b704..3964896 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "@web/test-runner": "^0.18.3", "@web/test-runner-core": "^0.13.2", "install": "^0.13.0", - "jquery": "^4.0.0-beta", + "jquery": "^4.0.0-beta.2", "qunit": "^2.20.1", "rollup": "^2.79.2", "rollup-plugin-cleanup": "^3.2.1", diff --git a/src/yafowil/widget/array/resources/default/widget.js b/src/yafowil/widget/array/resources/default/widget.js index 92f0ace..829dfff 100644 --- a/src/yafowil/widget/array/resources/default/widget.js +++ b/src/yafowil/widget/array/resources/default/widget.js @@ -211,7 +211,7 @@ var yafowil_array = (function (exports, $) { _array_subscribers[event].push(subscriber); } function inside_template(elem) { - return elem.parents('.arraytemplate').length > 0 + return elem.parents('.arraytemplate').length > 0; } class ArrayWidget extends ArrayBase { static initialize(context) { From 5d6ae3923a3b368f0eaaef48f4a53d10d1831e91 Mon Sep 17 00:00:00 2001 From: Lena Daxenbichler Date: Tue, 25 Feb 2025 12:30:51 +0100 Subject: [PATCH 17/17] update changelog --- CHANGES.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index 90e74c5..fa355a2 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -19,6 +19,12 @@ Changes - Use rollup for bundling scss. Use ``make rollup`` to compile js and scss. [lenadax] +- Use ``webtestrunner`` instead of ``karma`` for js tests. Use ``make wtr`` to run tests. + [lenadax] + +- Use ``pnpm`` as package manager. + [lenadax] + - Create Bootstrap5 widget version. [lenadax]
',t+="',t+='
',e.indexOf("array-add")>-1&&(t+='',t+=` `,t+=""),e.indexOf("array-remove")>-1&&(t+='',t+=` `,t+=""),e.indexOf("array-sort")>-1&&(t+='',t+=` `,t+="",t+='',t+=` `,t+=""),t+="
",t+="
',t+="',t+='
',e.indexOf("array-add")>-1&&(t+='',t+=` `,t+=""),e.indexOf("array-remove")>-1&&(t+='',t+=` `,t+=""),e.indexOf("array-sort")>-1&&(t+='',t+=` `,t+="",t+='',t+=` `,t+=""),t+="
",t+="
',t+="',t+='
',e.indexOf("array-add")>-1&&(t+='',t+=` `,t+=""),e.indexOf("array-remove")>-1&&(t+='',t+=` `,t+=""),e.indexOf("array-sort")>-1&&(t+='',t+=` `,t+="",t+='',t+=` `,t+=""),t+="
",t+="
',t+="',t+='
',e.indexOf("array-add")>-1&&(t+='',t+=` `,t+=""),e.indexOf("array-remove")>-1&&(t+='',t+=` `,t+=""),e.indexOf("array-sort")>-1&&(t+='',t+=` `,t+="",t+='',t+=` `,t+=""),t+="
",t+="