function updateItemName(item, name) { if(name === undefined) name = item.name; if(item.infoName === name) return; item.infoName = name; item.name = name; const namePath = name.split('.'); item.order = namePath.reduce((total, level, index) => total + (+level * ([1000000, 1000, 1, 0.001, 0.000001][index])), 0); item.level = namePath.length; item.selfName = namePath.pop(); item.parentName = namePath.join('.'); } function updateChildrenName(item) { if(!item.children) return; item.children.forEach((subItem, subIndex) => { updateItemName(subItem, `${item.name}.${subIndex + 1}`); updateChildrenName(subItem); }); } /** ThinkMatrixOptions component. */ class ThinkMatrixOptions extends zui.Component { static NAME = 'ThinkMatrixOptions'; static DEFAULT = { colName: 'colFields', cols: ['', '', '', ''], moveIcon: 'move', deleteIcon: 'close', deleteColTip: '', addColTip: '', changeLevelByDrag: false, colPlaceholder: '', addColText: '', isSaveData: true, }; init() { this.reset(this.options.cols, true); } afterInit() { this.render(); const $element = this.$element; const multipleData = $('.think-multiple').data(); const quotedQuestions = multipleData.quotedQuestions; const linkColumn = multipleData.linkColumn; $element.on('focus', 'input', e => { const $input = $(e.target); $input.closest('.think-multiple-item').addClass('is-focus'); }) .on('blur', 'input', e => { const $input = $(e.target); $input.closest('.think-multiple-item').removeClass('is-focus'); this.saveData(); }) .on('input', 'input', e => {this.saveData();}) .on('click', '.btn-action', e => { const $btn = $(e.currentTarget); if($btn.is('.disabled')) return; const action = $btn.attr('data-action'); const name = $btn.closest('.think-multiple-item').attr('data-name'); if(action === 'delete') this.deleteItem(name); else if(action === 'sib') this.addSib(); }).on('mouseenter', '.think-multiple-item-move', e => { $element.find('.move-hover').removeClass('move-hover'); $(e.currentTarget).closest('.think-multiple-item').addClass('move-hover'); }).on('mouseleave', '.think-multiple-item-move', e => { $element.find('.move-hover').removeClass('move-hover'); }); /* 如果当前多列填空题被其他多选题引用,不可以重新排列列标题顺序。*/ /* If the current multiple column fill in the blank question is referenced by other multiple-choice questions, the column headings cannot be rearranged. */ if((!quotedQuestions || !quotedQuestions.length) && !linkColumn.length) { $element.draggable( { selector: '.think-multiple-item', handle: '.think-multiple-item-move', beforeDrag: (_event, dragElement) => { const dragName = $(dragElement).attr('data-name'); this.dragName = dragName; this.dragItem = this.getByName(dragName); this.dragMaxLevel = this.dragItem.level; this.isValidLevel = true; $element.find(`.think-multiple-item[data-name^="${dragName}."]`).addClass('is-sub-dragging').each((_index, ele) => { const level = +($(ele).attr('data-level')); if(level > this.dragMaxLevel) this.dragMaxLevel = level; }); $element.removeClass('cursor-not-allowed'); }, onDragStart: (event, dragElement) => { event.dataTransfer.setDragImage($(dragElement).find('.think-multiple-drag-ghost')[0], 0, 0); }, onDragEnd: () => { $element.find('.is-sub-dragging').removeClass('is-sub-dragging'); const dropName = this.dropName; if(dropName) { this.dropName = null; const $dropRow = this.getRow(dropName); if($dropRow && $dropRow.length) $dropRow.removeAttr('data-drop-side').removeAttr('data-drop-level'); } if(!this.isValidLevel) return; const dragName = this.dragName; if(!dropName || dragName === dropName) return; if(this.dropSide === 'right') this.moveAfter(dragName, dropName); else this.moveBefore(dragName, dropName); this.saveData(true); }, onDragOver: (event, dragElement, dropElement) => { const $col = $(dropElement); const dropName = $col.attr('data-name'); let idDiff = false; if(dropName !== this.dropName) { this.dropName = dropName; const $oldRow = this.getRow(dropName); $oldRow.removeAttr('data-drop-side') .removeAttr('data-drop-level') .removeAttr('data-invalid-nested'); this.dropSide = ''; this.dropLevel = ''; this.isValidLevel = undefined; idDiff = true; } const dropItem = this.getByName(dropName); const dropBounding = dropElement.getBoundingClientRect(); const dropSide = event.clientX > (dropBounding.left + dropBounding.width / 2) ? 'right' : 'left'; const dropLevel = Math.max(1, Math.min(4, (!this.options.changeLevelByDrag || event.clientX <= (dropBounding.left + 24)) ? dropItem.level : (Math.round((event.clientX - dropBounding.left - 24 - 8) / 14)))); const isValidLevel = (this.dragMaxLevel + (dropLevel - this.dragItem.level)) <= 4; if(this.isValidLevel !== isValidLevel) { this.isValidLevel = isValidLevel; $col.toggleClass('is-invalid-drop-level', !isValidLevel); } $element.toggleClass('cursor-not-allowed', !isValidLevel); if(this.dropSide !== dropSide) { this.dropSide = dropSide; $col.attr('data-drop-side', dropSide); idDiff = true; } if(this.dropLevel !== dropLevel) { this.dropLevel = dropLevel; $col.attr('data-drop-level', dropLevel); idDiff = true; } }, target: (dragElement) => { return $element.find('.think-multiple-item').not('.is-sub-dragging').not(dragElement); } }); } } saveData(isClear = false) { if(!this.options.isSaveData) return; const cols = []; $('.think-multiple-body .think-multiple-item-text').each(function() { if($(this).val()) { const item = {value: $(this).closest('.think-multiple-item').data('name'), text: $(this).val()}; cols.push(item); } }); let values = $('.required-options .picker-box').zui('picker').$.value; values = values.split(''); const result = []; values.forEach(function(item) { if($(`.think-multiple-item[data-name="${item}"] .think-multiple-item-text`).val()) result.push(item); }); $('.required-options .picker-box').zui('picker').$.setValue(result.join(',')); $('.required-options .picker-box').zui('picker').render({items: cols}); if(isClear) $('.required-options .picker-box').zui('picker').$.setValue(''); } getByID(id) { return this._items.find(x => x.id === id); } getByName(name) { return this._items.find(x => x.name === name); } getParent(item) { if(typeof item === 'string') item = this.getByName(item); return (item && item.parentName) ? this.getByName(item.parentName) : null; } getRow(name) { return this.$element.find(`.think-multiple-item[data-name="${name}"]`); } reset(data, skipRender) { this._items = []; this.update(data, skipRender); } update(data, skipRender) { data.forEach(item =>{this.updateItem(item, true);}); if(!skipRender) this.render(); } updateItem(item, skipRender) { item = typeof item === 'string' ? {name: item, id: $.guid++, step: ''} : $.extend({id: $.guid++, step: ''}, item); updateItemName(item); const index = this._items.findIndex(x => x.id === item.id); if(index >= 0) { const oldItem = this._items[index]; const parent = this.getParent(oldItem); if(parent) parent.children.splice(parent.children.indexOf(oldItem), 1); item = $.extend(oldItem, item); this._items.splice(index, 1); updateChildrenName(item); } if(item.level > 1) { this._items.push(item); const parent = this._ensureItem(item.parentName); const siblings = parent.children || []; const oldIndex = siblings.findIndex(x => x.id === item.id); if(oldIndex >= 0) siblings.splice(oldIndex, 1); const index = siblings.findIndex(x => x.order > item.order); if(index === 0) siblings.unshift(item); else if(index < 0) siblings.push(item); else if(index > 0) siblings.splice(index, 0, item); parent.children = siblings; } else { const siblings = this._items; const index = siblings.findIndex(x => x.level === 1 && x.order > item.order); if(index === 0) siblings.unshift(item); else if(index < 0) siblings.push(item); else if(index > 0) siblings.splice(index, 0, item); } if(!skipRender) this.render(); return item; } _ensureItem(name) { return this.getByName(name) || this.updateItem(name); } _createCol(item, options) { const name = options.cols[item.index] || ''; const $col = $ ([ `