mirror of
https://github.com/processwire/processwire.git
synced 2025-08-12 01:34:31 +02:00
Add support for copy and paste of repeater items between pages (or same page). To copy, click the copy/clone icon and a dialog will appear asking what action you want. Use the same dialog action to paste. This also updates the clone feature to support insert before/after.
This commit is contained in:
@@ -332,7 +332,7 @@ class FieldtypeFieldsetPage extends FieldtypeRepeater implements ConfigurableMod
|
||||
* @return Page
|
||||
*
|
||||
*/
|
||||
protected function getRepeaterPageParent(Page $page, Field $field, $create = true) {
|
||||
public function getRepeaterPageParent(Page $page, Field $field, $create = true) {
|
||||
return $this->getRepeaterParent($field);
|
||||
}
|
||||
|
||||
|
@@ -33,7 +33,7 @@ class FieldtypeRepeater extends Fieldtype implements ConfigurableModule {
|
||||
return array(
|
||||
'title' => __('Repeater', __FILE__), // Module Title
|
||||
'summary' => __('Maintains a collection of fields that are repeated for any number of times.', __FILE__), // Module Summary
|
||||
'version' => 108,
|
||||
'version' => 110,
|
||||
'autoload' => true,
|
||||
'installs' => 'InputfieldRepeater'
|
||||
);
|
||||
@@ -1114,7 +1114,7 @@ class FieldtypeRepeater extends Fieldtype implements ConfigurableModule {
|
||||
* @return Page|NullPage
|
||||
*
|
||||
*/
|
||||
protected function getRepeaterPageParent(Page $page, Field $field, $create = true) {
|
||||
public function getRepeaterPageParent(Page $page, Field $field, $create = true) {
|
||||
|
||||
$repeaterParent = $this->getRepeaterParent($field);
|
||||
$parentName = self::repeaterPageNamePrefix . $page->id; // for-page-123
|
||||
@@ -1149,7 +1149,7 @@ class FieldtypeRepeater extends Fieldtype implements ConfigurableModule {
|
||||
* @throws WireException
|
||||
*
|
||||
*/
|
||||
protected function getRepeaterParent(Field $field) {
|
||||
public function getRepeaterParent(Field $field) {
|
||||
|
||||
$pages = $this->wire()->pages;
|
||||
$parentID = (int) $field->get('parent_id');
|
||||
|
File diff suppressed because one or more lines are too long
@@ -189,7 +189,76 @@ function InputfieldRepeater($) {
|
||||
});
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Event when the copy/clone/paste action is clicked
|
||||
*
|
||||
* @returns {boolean}
|
||||
*
|
||||
*/
|
||||
var eventCopyCloneClick = function() {
|
||||
|
||||
if(isActionDisabled($(this))) return false;
|
||||
|
||||
var labels = ProcessWire.config.InputfieldRepeater.labels;
|
||||
var $item = $(this).closest('.InputfieldRepeaterItem');
|
||||
var itemID = $item.attr('data-page');
|
||||
var $inputfield = $item.closest('.InputfieldRepeater');
|
||||
var fieldName = $inputfield.attr('data-name');
|
||||
var cookieName = copyPasteCookieName(fieldName);
|
||||
var copyValue = jQuery.cookie(cookieName);
|
||||
var itemLabel = getItemLabel($item).text();
|
||||
var pasteID = copyValue ? parseInt(copyValue.item) : '';
|
||||
var pasteDisabled = copyValue ? '' : 'disabled ';
|
||||
var pasteSelected = pasteID > 0 ? 'selected ' : '';
|
||||
var note = '';
|
||||
|
||||
if(pasteID > 0) {
|
||||
note = "<div><i class='fa fa-paste fa-fw'></i>" + labels.copyInMemory + ' (id ' + pasteID + ')</div>';
|
||||
}
|
||||
|
||||
var input =
|
||||
'<option value="copy">' + labels.copy + '</option>' +
|
||||
'<option value="clone-before">' + labels.cloneBefore + '</option>' +
|
||||
'<option value="clone-after">' + labels.cloneAfter + '</option>' +
|
||||
'<option ' + pasteDisabled + 'value="paste-before">' + labels.pasteBefore + '</option>' +
|
||||
'<option ' + pasteDisabled + pasteSelected + 'value="paste-after">' + labels.pasteAfter + '</option>' +
|
||||
'<option ' + pasteDisabled + 'value="clear">' + labels.clear + '</option>';
|
||||
|
||||
if(note.length) note = "<span class='detail'>" + note + "</span>";
|
||||
|
||||
var options = {
|
||||
message: labels.selectAction + ' (id ' + itemID + ')', // message displayed at top
|
||||
input: '<select name="action" class="uk-select">' + input + '</select>' + note, // HTML content that is to be displayed
|
||||
callback: function(value) {
|
||||
var action = value.action;
|
||||
if(action === 'copy') {
|
||||
copyRepeaterItem($item);
|
||||
$item.fadeOut('fast', function() { $item.fadeIn('fast') });
|
||||
$inputfield.addClass('InputfieldRepeaterCanPaste');
|
||||
} else if(action === 'clone-before') {
|
||||
cloneRepeaterItem($item, true);
|
||||
} else if(action === 'clone-after') {
|
||||
cloneRepeaterItem($item, false);
|
||||
} else if(action === 'paste-before') {
|
||||
pasteRepeaterItem($item, true);
|
||||
} else if(action === 'paste-after') {
|
||||
pasteRepeaterItem($item, false);
|
||||
} else if(action === 'clear') {
|
||||
jQuery.cookie(cookieName, null);
|
||||
$inputfield.removeClass('InputfieldRepeaterCanPaste');
|
||||
} else {
|
||||
console.log('unknown action: ' + action);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// open the add-type selection dialog
|
||||
vex.dialog.open(options);
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
var eventSettingsClick = function(e) {
|
||||
var $this = $(this);
|
||||
var $item = $this.closest('.InputfieldRepeaterItem');
|
||||
@@ -357,8 +426,10 @@ function InputfieldRepeater($) {
|
||||
var newItemTotal = 0; // for noAjaxAdd mode
|
||||
var useAjax = $addLink.attr('data-noajax').length == 0;
|
||||
var cloneID = $addLink.attr('data-clone');
|
||||
var pageID = 0;
|
||||
var depth = 0;
|
||||
var redoSortAll = false;
|
||||
var inputfieldPageID = parseInt($inputfieldRepeater.attr('data-page'));
|
||||
|
||||
function addRepeaterItem($addItem) {
|
||||
// make sure it has a unique ID
|
||||
@@ -382,7 +453,16 @@ function InputfieldRepeater($) {
|
||||
}
|
||||
|
||||
if(typeof cloneID == "undefined" || !cloneID) cloneID = null;
|
||||
if(cloneID) $addLink.removeAttr('data-clone');
|
||||
|
||||
if(cloneID) {
|
||||
$addLink.removeAttr('data-clone');
|
||||
// when data-clone contains pageID:itemID it is from a previous copy operation
|
||||
if(cloneID.indexOf(':') > 0) {
|
||||
var a = cloneID.split(':');
|
||||
pageID = parseInt(a[0]); // for copy/paste
|
||||
cloneID = parseInt(a[1]);
|
||||
}
|
||||
}
|
||||
|
||||
if(!useAjax) {
|
||||
var $newItem = $inputfields.children('.InputfieldRepeaterNewItem'); // for noAjaxAdd mode, non-editable new item
|
||||
@@ -399,8 +479,9 @@ function InputfieldRepeater($) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// get addItem from ajax
|
||||
var pageID = $inputfieldRepeater.attr('data-page');
|
||||
if(!pageID) pageID = inputfieldPageID;
|
||||
var fieldName = $inputfieldRepeater.attr('id').replace('wrap_Inputfield_', '');
|
||||
var $spinner = $addLink.parent().find('.InputfieldRepeaterSpinner');
|
||||
var ajaxURL = ProcessWire.config.InputfieldRepeater.editorUrl + '?id=' + pageID + '&field=' + fieldName;
|
||||
@@ -408,7 +489,7 @@ function InputfieldRepeater($) {
|
||||
$spinner.removeClass($spinner.attr('data-off')).addClass($spinner.attr('data-on'));
|
||||
|
||||
if(cloneID) {
|
||||
ajaxURL += '&repeater_clone=' + cloneID;
|
||||
ajaxURL += '&repeater_clone=' + cloneID + '&repeater_clone_to=' + inputfieldPageID;
|
||||
} else {
|
||||
ajaxURL += '&repeater_add=' + $addLink.attr('data-type');
|
||||
}
|
||||
@@ -568,6 +649,18 @@ function InputfieldRepeater($) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Event called when the "Paste" link in the footer is clicked
|
||||
*
|
||||
*/
|
||||
var eventPasteClick = function(e) {
|
||||
var $inputfield = $(this).closest('.InputfieldRepeater');
|
||||
// use the InputfieldRepeaterNewItem as our substitute for a contextual item
|
||||
var $newItem = $inputfield.children('.InputfieldContent').children('.Inputfields').children('.InputfieldRepeaterNewItem');
|
||||
pasteRepeaterItem($newItem, false);
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Event when mouseout of insert before/after action
|
||||
*
|
||||
@@ -1084,10 +1177,11 @@ function InputfieldRepeater($) {
|
||||
function initHeaders($headers, $inputfieldRepeater, renderValueMode) {
|
||||
|
||||
var $clone = $("<i class='fa fa-copy InputfieldRepeaterClone'></i>").css('display', 'block');
|
||||
// var $paste = $("<i class='fa fa-paste InputfieldRepeaterPaste'></i>").css('display', 'block');
|
||||
var $delete = $("<i class='fa fa-trash InputfieldRepeaterTrash'></i>");
|
||||
var $toggle = $("<i class='fa InputfieldRepeaterToggle' data-on='fa-toggle-on' data-off='fa-toggle-off'></i>");
|
||||
var $insertAfter = $("<i class='fa fa-download xfa-arrow-circle-down InputfieldRepeaterInsertAfter'></i>");
|
||||
var $insertBefore = $("<i class='fa fa-upload xfa-arrow-circle-up InputfieldRepeaterInsertBefore'></i>");
|
||||
var $insertAfter = $("<i class='fa fa-download InputfieldRepeaterInsertAfter'></i>");
|
||||
var $insertBefore = $("<i class='fa fa-upload InputfieldRepeaterInsertBefore'></i>");
|
||||
var cfg = ProcessWire.config.InputfieldRepeater;
|
||||
var allowClone = !$inputfieldRepeater.hasClass('InputfieldRepeaterNoAjaxAdd');
|
||||
var allowSettings = $inputfieldRepeater.hasClass('InputfieldRepeaterHasSettings');
|
||||
@@ -1096,6 +1190,7 @@ function InputfieldRepeater($) {
|
||||
$toggle.attr('title', cfg.labels.toggle);
|
||||
$delete.attr('title', cfg.labels.remove);
|
||||
$clone.attr('title', cfg.labels.clone);
|
||||
// $paste.attr('title', 'Paste'); // @todo
|
||||
$insertBefore.attr('title', cfg.labels.insertBefore);
|
||||
$insertAfter.attr('title', cfg.labels.insertAfter);
|
||||
}
|
||||
@@ -1134,7 +1229,10 @@ function InputfieldRepeater($) {
|
||||
.attr('title', cfg.labels.settings);
|
||||
$controls.prepend($settingsToggle);
|
||||
}
|
||||
if(allowClone) $controls.prepend($clone.clone(true));
|
||||
if(allowClone) {
|
||||
$controls.prepend($clone.clone(true));
|
||||
// $controls.prepend($paste.clone(true));
|
||||
}
|
||||
$controls.prepend($toggleControl);
|
||||
$controls.prepend($deleteControl);
|
||||
$t.prepend($controls);
|
||||
@@ -1340,6 +1438,107 @@ function InputfieldRepeater($) {
|
||||
$.cookie('repeaters_open', val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone a repeater item in place
|
||||
*
|
||||
* @param $item
|
||||
* @param pasteValue Optional cookie object value that was previously copied
|
||||
*
|
||||
*/
|
||||
function cloneRepeaterItem($item, insertBefore, pasteValue) {
|
||||
|
||||
if(typeof pasteValue === "undefined") pasteValue = null;
|
||||
|
||||
var actionName = pasteValue === null ? 'clone' : 'paste';
|
||||
var $addLink = $item.closest('.InputfieldRepeater').children('.InputfieldContent')
|
||||
.children('.InputfieldRepeaterAddItem').find('.InputfieldRepeaterAddLink:eq(0)');
|
||||
// $('html, body').animate({ scrollTop: $addLink.offset().top - 100}, 250, 'swing');
|
||||
|
||||
$item.siblings('.InputfieldRepeaterInsertItem').remove();
|
||||
|
||||
var depth = getItemDepth($item);
|
||||
var $newItem = $item.hasClass('InputfieldRepeaterNewItem') ? $item.clone() : $item.siblings('.InputfieldRepeaterNewItem').clone();
|
||||
var $nextItem = $item.next('.InputfieldRepeaterItem');
|
||||
var nextItemDepth = $nextItem.length ? getItemDepth($nextItem) : depth;
|
||||
var $prevItem = $item.prev('.InputfieldRepeaterItem');
|
||||
var prevItemDepth = $prevItem.length ? getItemDepth($prevItem) : depth;
|
||||
|
||||
if(typeof insertBefore === "undefined") {
|
||||
insertBefore = depth < nextItemDepth;
|
||||
}
|
||||
|
||||
$newItem.addClass('InputfieldRepeaterInsertItem').attr('id', $newItem.attr('id') + '-' + actionName); // .removeClass('InputfieldRepeaterNewItem); ?
|
||||
$newItem.find('.InputfieldHeader').html("<i class='fa fa-spin fa-spinner'></i>");
|
||||
|
||||
if(insertBefore) {
|
||||
depth = getInsertBeforeItemDepth($item);
|
||||
$newItem.addClass('InputfieldRepeaterInsertItemBefore');
|
||||
$newItem.insertBefore($item);
|
||||
} else {
|
||||
depth = getInsertAfterItemDepth($item);
|
||||
$newItem.addClass('InputfieldRepeaterInsertItemAfter');
|
||||
$newItem.insertAfter($item);
|
||||
}
|
||||
|
||||
setItemDepth($newItem, depth);
|
||||
|
||||
$newItem.show();
|
||||
|
||||
if(actionName === 'paste') {
|
||||
// data-clone attribute with 'pageID:itemID' indicates page ID and item ID to clone
|
||||
$addLink.attr('data-clone', pasteValue.page + ':' + pasteValue.item).click();
|
||||
} else {
|
||||
// current page ID is implied when only itemID is supplied
|
||||
$addLink.attr('data-clone', $item.attr('data-page')).click();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Paste previously copied item
|
||||
*
|
||||
* @param $item Item to insert before or after
|
||||
* @param insertBefore True to insert before, false to insert after
|
||||
*
|
||||
*/
|
||||
function pasteRepeaterItem($item, insertBefore) {
|
||||
var $inputfield = $item.closest('.InputfieldRepeater');
|
||||
var fieldName = $inputfield.attr('data-name');
|
||||
var cookieName = copyPasteCookieName(fieldName);
|
||||
var copyValue = jQuery.cookie(cookieName);
|
||||
if(copyValue) cloneRepeaterItem($item, insertBefore, copyValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a repeater item to memory
|
||||
*
|
||||
* @param $item
|
||||
*
|
||||
*/
|
||||
function copyRepeaterItem($item) {
|
||||
var $title = $('#Inputfield_title');
|
||||
var $name = $('#Inputfield__pw_page_name');
|
||||
var $inputfield = $item.closest('.InputfieldRepeater');
|
||||
var fieldName = $inputfield.attr('data-name');
|
||||
var copyValue = {
|
||||
page: parseInt($inputfield.attr('data-page')),
|
||||
item: parseInt($item.attr('data-page')),
|
||||
field: fieldName,
|
||||
};
|
||||
var cookieName = copyPasteCookieName(fieldName);
|
||||
jQuery.cookie(cookieName, copyValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the copy/paste cookie name
|
||||
*
|
||||
* @param fieldName
|
||||
* @returns {string}
|
||||
*
|
||||
*/
|
||||
function copyPasteCookieName(fieldName) {
|
||||
return fieldName + '_copy';
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialization for document.ready
|
||||
*
|
||||
@@ -1354,7 +1553,9 @@ function InputfieldRepeater($) {
|
||||
.on('reloaded', '.InputfieldRepeater', eventReloaded)
|
||||
.on('click', '.InputfieldRepeaterTrash', eventDeleteClick)
|
||||
.on('dblclick', '.InputfieldRepeaterTrash', eventDeleteDblClick)
|
||||
.on('click', '.InputfieldRepeaterClone', eventCloneClick)
|
||||
//.on('click', '.InputfieldRepeaterClone', eventCloneClick)
|
||||
.on('click', '.InputfieldRepeaterClone', eventCopyCloneClick)
|
||||
.on('click', '.InputfieldRepeaterPaste', eventPasteClick)
|
||||
.on('click', '.InputfieldRepeaterSettingsToggle', eventSettingsClick)
|
||||
.on('dblclick', '.InputfieldRepeaterToggle', eventOpenAllClick)
|
||||
.on('click', '.InputfieldRepeaterToggle', eventToggleClick)
|
||||
|
File diff suppressed because one or more lines are too long
@@ -26,7 +26,7 @@ class InputfieldRepeater extends Inputfield implements InputfieldItemList {
|
||||
return array(
|
||||
'title' => __('Repeater', __FILE__), // Module Title
|
||||
'summary' => __('Repeats fields from another template. Provides the input for FieldtypeRepeater.', __FILE__), // Module Summary
|
||||
'version' => 109,
|
||||
'version' => 110,
|
||||
'requires' => 'FieldtypeRepeater',
|
||||
);
|
||||
}
|
||||
@@ -620,14 +620,16 @@ class InputfieldRepeater extends Inputfield implements InputfieldItemList {
|
||||
* Render a new item for ajax after 'add new' link clicked
|
||||
*
|
||||
* @param int $cloneItemID
|
||||
* @param int $cloneToParentID
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
public function renderAjaxNewItem($cloneItemID = 0) {
|
||||
public function renderAjaxNewItem($cloneItemID = 0, $cloneToParentID = 0) {
|
||||
|
||||
/** @var PageArray $value */
|
||||
$value = $this->attr('value');
|
||||
$clonePage = null;
|
||||
$cloneToParent = null;
|
||||
$readyPage = null;
|
||||
|
||||
if($cloneItemID) {
|
||||
@@ -637,12 +639,23 @@ class InputfieldRepeater extends Inputfield implements InputfieldItemList {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if($cloneToParentID && $cloneToParentID != $this->page->id) {
|
||||
$cloneToParent = $this->wire()->pages->get((int) $cloneToParentID);
|
||||
if($cloneToParent->id && $cloneToParent->hasField($this->field) && $cloneToParent->editable($this->field)) {
|
||||
// ok
|
||||
$fieldtype = $this->field->type; /** @var FieldtypeRepeater $fieldtype */
|
||||
// convert from /path/to/page having repeater to /processwire/repeaters/for-field-123/for-page-456/
|
||||
$cloneToParent = $fieldtype->getRepeaterPageParent($cloneToParent, $this->field);
|
||||
} else {
|
||||
$cloneToParent = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($clonePage && $clonePage->id) {
|
||||
/** @var FieldtypeRepeater $fieldtype */
|
||||
$fieldtype = $this->field->type;
|
||||
$readyPage = $this->wire()->pages->clone($clonePage, null, true,
|
||||
$readyPage = $this->wire()->pages->clone($clonePage, $cloneToParent, true,
|
||||
array('set' => array(
|
||||
'name' => $fieldtype->getUniqueRepeaterPageName() . 'c', // trailing "c" indicates clone
|
||||
'sort' => count($value)+1,
|
||||
@@ -685,6 +698,17 @@ class InputfieldRepeater extends Inputfield implements InputfieldItemList {
|
||||
if(!strlen($addLabel)) $addLabel = $this->_('Add New');
|
||||
return $addLabel;
|
||||
}
|
||||
|
||||
protected function renderPasteLabel() {
|
||||
return $this->_('Paste');
|
||||
}
|
||||
|
||||
protected function renderPasteLink() {
|
||||
$icon = wireIconMarkup('paste', 'fw');
|
||||
$label = $this->renderPasteLabel();
|
||||
$out = "<a class='InputfieldRepeaterPaste' href='#'>$icon $label</a>";
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called before render() or renderValue() method by InputfieldWrapper, before Inputfield-specific CSS/JS files added
|
||||
@@ -730,6 +754,11 @@ class InputfieldRepeater extends Inputfield implements InputfieldItemList {
|
||||
if($this->accordionMode) {
|
||||
$this->addClass('InputfieldRepeaterAccordion', 'wrapClass');
|
||||
}
|
||||
if(!empty($_COOKIE[$this->copyPasteCookieName()])) {
|
||||
$this->addClass('InputfieldRepeaterCanPaste', 'wrapClass');
|
||||
}
|
||||
|
||||
$this->wrapAttr('data-name', $this->field->name);
|
||||
$this->wrapAttr('data-page', $this->page->id);
|
||||
$this->wrapAttr('data-max', (int) $this->repeaterMaxItems);
|
||||
$this->wrapAttr('data-min', (int) $this->repeaterMinItems);
|
||||
@@ -757,7 +786,15 @@ class InputfieldRepeater extends Inputfield implements InputfieldItemList {
|
||||
'insertBefore' => $this->_x('Insert new item before this one', 'repeater-item-action'),
|
||||
'insertAfter' => $this->_x('Insert new item after this one', 'repeater-item-action'),
|
||||
'insertHere' => $this->_x('Insert new item here', 'repeater-item-action'),
|
||||
'disabledMinMax' => $this->_('This action is disabled per min and/or max item settings.')
|
||||
'disabledMinMax' => $this->_('This action is disabled per min and/or max item settings.'),
|
||||
'selectAction' => $this->_x('Select an action for this item ', 'dialog-header'),
|
||||
'copy' => $this->_x('COPY this item in memory to paste elsewhere', 'repeater-item-action'),
|
||||
'copyInMemory' => $this->_x('Item in copy/paste memory', 'dialog-note'),
|
||||
'cloneBefore' => $this->_x('CLONE this item and insert ABOVE this', 'repeater-item-action'),
|
||||
'cloneAfter' => $this->_x('CLONE this item and insert BELOW this', 'repeater-item-action'),
|
||||
'pasteBefore' => $this->_x('PASTE copied item ABOVE this', 'repeater-item-action'),
|
||||
'pasteAfter' => $this->_x('PASTE copied item BELOW this', 'repeater-item-action'),
|
||||
'clear' => $this->_x('CLEAR copy/paste memory', 'repeater-item-action'),
|
||||
)
|
||||
));
|
||||
|
||||
@@ -774,6 +811,13 @@ class InputfieldRepeater extends Inputfield implements InputfieldItemList {
|
||||
protected function renderFooter($noAjaxAdd) {
|
||||
// a hidden checkbox with link that we use to identify when items have been added
|
||||
if($this->singleMode) return '';
|
||||
|
||||
if(!empty($_COOKIE[$this->copyPasteCookieName()])) {
|
||||
$paste = ' ' . $this->renderPasteLink();
|
||||
} else {
|
||||
$paste = '';
|
||||
}
|
||||
|
||||
$out =
|
||||
"<p class='InputfieldRepeaterAddItem'>" .
|
||||
"<input class='InputfieldRepeaterAddItemsQty' type='text' name='_{$this->name}_add_items' value='0' />" . // for noAjaxAdd
|
||||
@@ -781,8 +825,9 @@ class InputfieldRepeater extends Inputfield implements InputfieldItemList {
|
||||
"<i class='fa fa-fw fa-plus-circle InputfieldRepeaterSpinner' " .
|
||||
"data-on='fa-spin fa-spinner' data-off='fa-plus-circle'></i>" .
|
||||
$this->renderAddLabel() .
|
||||
"</a>" .
|
||||
"</a>" . $paste .
|
||||
"</p>";
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
@@ -802,9 +847,10 @@ class InputfieldRepeater extends Inputfield implements InputfieldItemList {
|
||||
$repeaterAdd = $input->get('repeater_add');
|
||||
$repeaterEdit = (int) $input->get('repeater_edit');
|
||||
$repeaterClone = (int) $input->get('repeater_clone');
|
||||
$repeaterCloneTo = (int) $input->get('repeater_clone_to');
|
||||
if($input->get('inrvm')) $this->renderValueMode = true;
|
||||
if($repeaterClone) {
|
||||
return $this->renderValueMode ? '' : $this->renderAjaxNewItem($repeaterClone);
|
||||
return $this->renderValueMode ? '' : $this->renderAjaxNewItem($repeaterClone, $repeaterCloneTo);
|
||||
} else if($repeaterAdd !== null && !$noAjaxAdd) {
|
||||
return $this->renderValueMode ? '' : $this->renderAjaxNewItem();
|
||||
} else if($repeaterEdit) {
|
||||
@@ -1139,6 +1185,17 @@ class InputfieldRepeater extends Inputfield implements InputfieldItemList {
|
||||
return $this->wrappers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the copy/paste cookie name
|
||||
*
|
||||
* @return string
|
||||
* @since 3.0.188
|
||||
*
|
||||
*/
|
||||
public function copyPasteCookieName() {
|
||||
return $this->field->name . '_copy';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return InputfieldWrapper
|
||||
*
|
||||
|
@@ -7,6 +7,21 @@
|
||||
}
|
||||
}
|
||||
|
||||
.InputfieldRepeaterPaste {
|
||||
display: none;
|
||||
}
|
||||
&.InputfieldRepeaterCanPaste {
|
||||
.InputfieldRepeaterPaste {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
// prevents longer item headers from going outside Inputfield box horizontally
|
||||
.InputfieldRepeaterItem {
|
||||
max-width: 100%;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.InputfieldRepeaterItem > .InputfieldHeader {
|
||||
line-height: 1em;
|
||||
padding: 0.5em 0 0.5em 0.4em;
|
||||
|
File diff suppressed because one or more lines are too long
@@ -640,6 +640,10 @@ $focusPointCircleSize: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.AdminThemeUikit .InputfieldImageValidExtensions {
|
||||
position: relative;
|
||||
top: -15px;
|
||||
}
|
||||
|
||||
// Narrow mode applies when width of Inputfield is under 500px
|
||||
.InputfieldImageNarrow {
|
||||
|
Reference in New Issue
Block a user