dynamic select field
This commit is contained in:
parent
f8cfcf9f34
commit
29a7b0c3e0
|
@ -1219,6 +1219,8 @@ class htmlSelect extends htmlElement {
|
||||||
protected $tableRowsToHide = array();
|
protected $tableRowsToHide = array();
|
||||||
/** list of enclosing table rows to show when checked */
|
/** list of enclosing table rows to show when checked */
|
||||||
protected $tableRowsToShow = array();
|
protected $tableRowsToShow = array();
|
||||||
|
/** dynamic scrolling */
|
||||||
|
private $dynamicScrolling = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
|
@ -1349,6 +1351,10 @@ class htmlSelect extends htmlElement {
|
||||||
* @param array $elements list of options
|
* @param array $elements list of options
|
||||||
*/
|
*/
|
||||||
private function printOptionsHTML($elements) {
|
private function printOptionsHTML($elements) {
|
||||||
|
if ($this->dynamicScrolling) {
|
||||||
|
echo "<option value=\"#\">#</option>\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
// sorting
|
// sorting
|
||||||
if ($this->sortElements) {
|
if ($this->sortElements) {
|
||||||
if ($this->hasDescriptiveElements) {
|
if ($this->hasDescriptiveElements) {
|
||||||
|
@ -1568,6 +1574,24 @@ class htmlSelect extends htmlElement {
|
||||||
return 'tr';
|
return 'tr';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable dynamic scrolling. This limits the number of select options to 10000 by dynamically adding/removing options.
|
||||||
|
* This will not be enabled when optgroups are used or the option size is less than 10000.
|
||||||
|
*/
|
||||||
|
public function enableDynamicScrolling() {
|
||||||
|
// not possible for optgroups and smaller option lists
|
||||||
|
if ((sizeof($this->elements) < 10000) || $this->containsOptgroups) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$this->dynamicScrolling = true;
|
||||||
|
$elementData = array();
|
||||||
|
foreach ($this->elements as $key => $value) {
|
||||||
|
$elementData[] = array('label' => $key, 'value' => $value);
|
||||||
|
}
|
||||||
|
$this->addDataAttribute('dynamic-options', json_encode($elementData));
|
||||||
|
$this->cssClasses[] = 'lam-dynamicOptions';
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1111,6 +1111,139 @@ window.lam.html.preventEnter = function() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window.lam.dynamicSelect = window.lam.dynamicSelect || {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Activates dynamic selection for all marked select fields.
|
||||||
|
*/
|
||||||
|
window.lam.dynamicSelect.activate = function() {
|
||||||
|
var dynamicSelects = jQuery('.lam-dynamicOptions');
|
||||||
|
dynamicSelects.each(function() {
|
||||||
|
var selectField = jQuery(this);
|
||||||
|
selectField.data('option-height', selectField.find("option").height());
|
||||||
|
selectField.data('select-height', selectField.height());
|
||||||
|
selectField.data('select-last-scroll-top', 0);
|
||||||
|
selectField.data('select-current-scroll', 0);
|
||||||
|
selectField.html('');
|
||||||
|
var options = selectField.data('dynamic-options');
|
||||||
|
var maxOptions = 3000;
|
||||||
|
var numOfOptionBeforeToLoadNextSet = 10;
|
||||||
|
var numberOfOptionsToLoad = 200;
|
||||||
|
for (var i = 0; i < maxOptions; i++) {
|
||||||
|
selectField.append(window.lam.dynamicSelect.createOption(options[i], i));
|
||||||
|
}
|
||||||
|
if (options.length > maxOptions) {
|
||||||
|
// activate scrolling logic only if enough options are set
|
||||||
|
selectField.scroll(function(event) {
|
||||||
|
window.lam.dynamicSelect.onScroll(selectField, event, maxOptions, numOfOptionBeforeToLoadNextSet, numberOfOptionsToLoad);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an option field inside the select.
|
||||||
|
*
|
||||||
|
* @param data option data
|
||||||
|
* @param index index in list of all options
|
||||||
|
* @returns option
|
||||||
|
*/
|
||||||
|
window.lam.dynamicSelect.createOption = function(data, index) {
|
||||||
|
var newOption = jQuery(document.createElement("option"));
|
||||||
|
newOption.attr('value', data.value);
|
||||||
|
newOption.data('index', index);
|
||||||
|
newOption.text(data.label);
|
||||||
|
return newOption;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Onscroll event.
|
||||||
|
*
|
||||||
|
* @param selectField select field
|
||||||
|
* @param event event
|
||||||
|
* @param maxOptions maximum options to show
|
||||||
|
* @param numOfOptionBeforeToLoadNextSet number of options to reach before end of list
|
||||||
|
* @param numberOfOptionsToLoad number of options to add
|
||||||
|
*/
|
||||||
|
window.lam.dynamicSelect.onScroll = function(selectField, event, maxOptions, numOfOptionBeforeToLoadNextSet, numberOfOptionsToLoad) {
|
||||||
|
var scrollTop = selectField.scrollTop();
|
||||||
|
var totalHeight = selectField.find("option").length * selectField.data('option-height');
|
||||||
|
var lastScrollTop = selectField.data('select-last-scroll-top');
|
||||||
|
var selectBoxHeight = selectField.data('select-height');
|
||||||
|
var singleOptionHeight = selectField.data('option-height');
|
||||||
|
var currentScroll = scrollTop + selectBoxHeight;
|
||||||
|
selectField.data('select-current-scroll-top', scrollTop);
|
||||||
|
if ((scrollTop >= lastScrollTop)
|
||||||
|
&& ((currentScroll + (numOfOptionBeforeToLoadNextSet * singleOptionHeight)) >= totalHeight)) {
|
||||||
|
window.lam.dynamicSelect.loadNextOptions(selectField, maxOptions, numberOfOptionsToLoad);
|
||||||
|
}
|
||||||
|
else if ((scrollTop <= lastScrollTop)
|
||||||
|
&& ((scrollTop - (numOfOptionBeforeToLoadNextSet * singleOptionHeight)) <= 0)) {
|
||||||
|
window.lam.dynamicSelect.loadPreviousOptions(selectField, maxOptions, numberOfOptionsToLoad);
|
||||||
|
}
|
||||||
|
selectField.data('select-last-scroll-top', scrollTop);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the next bunch of options at the end.
|
||||||
|
*
|
||||||
|
* @param selectField selct field
|
||||||
|
* @param maxOptions maximum options to show
|
||||||
|
* @param numberOfOptionsToLoad number of options to add
|
||||||
|
*/
|
||||||
|
window.lam.dynamicSelect.loadNextOptions = function(selectField, maxOptions, numberOfOptionsToLoad) {
|
||||||
|
var selectBoxHeight = selectField.data('select-height');
|
||||||
|
var singleOptionHeight = selectField.data('option-height');
|
||||||
|
var currentScrollPosition = selectField.data('select-current-scroll-top') + selectBoxHeight;
|
||||||
|
var options = selectField.data('dynamic-options');
|
||||||
|
var lastIndex = selectField.children().last().data('index');
|
||||||
|
for (var toAdd = 0; toAdd < numberOfOptionsToLoad; toAdd++) {
|
||||||
|
var addPos = lastIndex + 1 + toAdd;
|
||||||
|
if (options[addPos] === undefined) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
selectField.append(window.lam.dynamicSelect.createOption(options[addPos], addPos));
|
||||||
|
}
|
||||||
|
var numberOfOptions = selectField.children().length;
|
||||||
|
var toRemove = numberOfOptions - maxOptions;
|
||||||
|
if (toRemove > 0) {
|
||||||
|
selectField.children().slice(0, toRemove).remove();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
toRemove = 0;
|
||||||
|
}
|
||||||
|
selectField.scrollTop(currentScrollPosition - selectBoxHeight - (toRemove * singleOptionHeight));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the next bunch of options at the beginning.
|
||||||
|
*
|
||||||
|
* @param selectField selct field
|
||||||
|
* @param maxOptions maximum options to show
|
||||||
|
* @param numberOfOptionsToLoad number of options to add
|
||||||
|
*/
|
||||||
|
window.lam.dynamicSelect.loadPreviousOptions = function(selectField, maxOptions, numberOfOptionsToLoad) {
|
||||||
|
var singleOptionHeight = selectField.data('option-height');
|
||||||
|
var currentScrollPosition = selectField.data('select-current-scroll-top');
|
||||||
|
var options = selectField.data('dynamic-options');
|
||||||
|
var lastIndex = selectField.children().first().data('index');
|
||||||
|
var added = 0;
|
||||||
|
for (var toAdd = 0; toAdd < numberOfOptionsToLoad; toAdd++) {
|
||||||
|
var addPos = lastIndex - 1 - toAdd;
|
||||||
|
if (options[addPos] === undefined) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
added++;
|
||||||
|
selectField.prepend(window.lam.dynamicSelect.createOption(options[addPos], addPos));
|
||||||
|
}
|
||||||
|
var numberOfOptions = selectField.children().length;
|
||||||
|
var toRemove = numberOfOptions - maxOptions;
|
||||||
|
if (toRemove > 0) {
|
||||||
|
selectField.children().slice(maxOptions).remove();
|
||||||
|
}
|
||||||
|
selectField.scrollTop(currentScrollPosition + (added * singleOptionHeight));
|
||||||
|
}
|
||||||
|
|
||||||
window.lam.selfservice = window.lam.selfservice || {};
|
window.lam.selfservice = window.lam.selfservice || {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1173,6 +1306,7 @@ jQuery(document).ready(function() {
|
||||||
window.lam.tools.schema.select();
|
window.lam.tools.schema.select();
|
||||||
window.lam.html.activateLightboxes();
|
window.lam.html.activateLightboxes();
|
||||||
window.lam.html.preventEnter();
|
window.lam.html.preventEnter();
|
||||||
|
window.lam.dynamicSelect.activate();
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue