dynamic select field
This commit is contained in:
		
							parent
							
								
									f8cfcf9f34
								
							
						
					
					
						commit
						29a7b0c3e0
					
				|  | @ -1219,6 +1219,8 @@ class htmlSelect extends htmlElement { | |||
| 	protected $tableRowsToHide = array(); | ||||
| 	/** list of enclosing table rows to show when checked */ | ||||
| 	protected $tableRowsToShow = array(); | ||||
| 	/** dynamic scrolling */ | ||||
| 	private $dynamicScrolling = false; | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Constructor. | ||||
|  | @ -1349,6 +1351,10 @@ class htmlSelect extends htmlElement { | |||
| 	 * @param array $elements list of options | ||||
| 	 */ | ||||
| 	private function printOptionsHTML($elements) { | ||||
| 		if ($this->dynamicScrolling) { | ||||
| 			echo "<option value=\"#\">#</option>\n"; | ||||
| 			return; | ||||
| 		} | ||||
| 		// sorting
 | ||||
| 		if ($this->sortElements) { | ||||
| 			if ($this->hasDescriptiveElements) { | ||||
|  | @ -1568,6 +1574,24 @@ class htmlSelect extends htmlElement { | |||
| 		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 || {}; | ||||
| 
 | ||||
| /** | ||||
|  | @ -1173,6 +1306,7 @@ jQuery(document).ready(function() { | |||
| 	window.lam.tools.schema.select(); | ||||
| 	window.lam.html.activateLightboxes(); | ||||
| 	window.lam.html.preventEnter(); | ||||
| 	window.lam.dynamicSelect.activate(); | ||||
| }); | ||||
| 
 | ||||
| /** | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue