Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 18.01.2020, 13:28
Аватар для Esm1nec
Новичок на форуме
Отправить личное сообщение для Esm1nec Посмотреть профиль Найти все сообщения от Esm1nec
 
Регистрация: 18.03.2018
Сообщений: 8

[HELP] Зависимые списки Select с переходом по URL на JS
Элите программирования привет! Есть такой скрипт каскада выпадающих меню: https://codepen.io/mgiulio/pen/OMwPJa

Как я понимаю в каждый <select> генерируется тег <option> из массива формата JSON (наверное), который расположен в конце скрипта.

Вопрос: Есть 3 выпадающих меню. Как сделать так, чтоб выбирая из 3 меню какой-либо элемент, был переход по URL (каждому пункту привязан свой URL)?

Я понимаю, что нужно третьему <select> задать onChange.
URL будет браться из атрибута value:
<option value="https://">Пункт №1</option>

Но как задать свой атрибут value каждому тегу <option>, которые генерируется из массива?
Ответить с цитированием
  #2 (permalink)  
Старый 18.01.2020, 14:05
Аватар для Esm1nec
Новичок на форуме
Отправить личное сообщение для Esm1nec Посмотреть профиль Найти все сообщения от Esm1nec
 
Регистрация: 18.03.2018
Сообщений: 8

Для третьего селекта прикрутил:
onchange="if (this.value) window.location.href = this.value"


и в коде дописал фрагмент, чтобы при создании <option> добавлялся атрибут value

var urls = document.querySelectorAll('#select-3 > option:not(:first-child');
    for (j = 0; j < urls.length; ++j) {
    urls[j].setAttribute('value', ' ');
}


Вопрос: как теперь value для каждого option из массива (см. конец скрипта) задать также массивом?


<div class="chained-selects">
             	<select id="select-1">
	            	<option selected>Choose level 1 option</option>
	            	<option>1</option>
	            	<option>2</option>
	            	<option>3</option>
            	</select>
            	<select id="select-2" disabled>
	            	<option selected>Choose level 2 option</option>
            	</select>
            	<select id="select-3" onchange="if (this.value) window.location.href = this.value" disabled >
	            	<option selected>Choose level 3 option</option>
            	</select>
            </div>



var options = generateOptions();

            document.querySelector('.chained-selects').addEventListener('change', onChange, false);

            function onChange(e) {
            	e.stopPropagation();
	
	            var s = e.target;
	
            	if (!s.nextElementSibling)
	            	return;
		
	            var next = s.nextElementSibling;
		
            	if (s.selectedIndex === 0)
	            	deactivateBoxes(next);
            	else {
	            	var path = [];
		            for (var p = s; p; p = p.previousElementSibling) {
		            	var selOptNode = p.options[p.selectedIndex];
		            	path.push(selOptNode.value);
		            }
	            	path.reverse();
		
		            var children = path.reduce(
		            	function(o, optName) {
			            	return o[optName];
		            	},
		            	options
	            	);
		
		            children = Object.keys(children);
		
	            	// Insert children in s.nextChild
		            	for (var q = next.firstElementChild.nextElementSibling; q; q = nextq) {
			            	nextq = q.nextElementSibling;
			            	next.removeChild(q);
		            	}
		            	for (var i = 0; i < children.length; ++i) {
				            var optEl = document.createElement('option');
			            	optEl.innerHTML = children[i];
			            	next.appendChild(optEl);
			            	
			            	/**/
			        var urls = document.querySelectorAll('#select-3 > option:not(:first-child');
                                    for (j = 0; j < urls.length; ++j) {
                                    urls[j].setAttribute('value', ' ');
                                }
			            	/**/
			            	
			            }
		
		            next.selectedIndex = 0;
	            	next.disabled = false;
		
		            deactivateBoxes(next.nextElementSibling);
            	}
            }
            
            function deactivateBoxes(s) {
            	while (s) {
	            	s.selectedIndex = 0;
	            	s.disabled = true;
		
	            	s = s.nextElementSibling;
            	}
            }

            function generateOptions() {
	            return {
		            '1': {
		            	'1-1': {
			            	'1-1-1': null,
			            	'1-1-2': null
		            	},
			            '1-2': {
			            	'1-2-1': null,
				            '1-2-2': null,
				            '1-2-3': null,
			            	'1-2-4': null,
		            	},
		            	'1-3': {
			            	'1-3-1': null,
			            	'1-3-2': null,
			            	'1-3-3': null,
			            	'1-3-4': null,
			            	'1-3-5': null,
		            	}
	            	},
	            	'2': {
		            	'2-1': {
			            	'2-1-1': null,
				            '2-1-2': null
		            	},
		            	'2-2': {
			            	'2-2-1': null,
			            	'2-2-2': null,
			            	'2-2-3': null,
			            	'2-2-4': null,
			            },
		            	'2-3': {
			            	'2-3-1': null,
			            	'2-3-2': null,
			            	'2-3-3': null,
				            '2-3-4': null,
			            	'2-3-5': null,
		            	}
	            	},
	            	'3': {
		            	'3-1': {
			            	'3-1-1': null,
			            	'3-1-2': null
			            },
			            '3-2': {
			            	'3-2-1': null,
			            	'3-2-2': null,
			            	'3-2-3': null,
			            	'3-2-4': null,
		            	},
		            	'3-3': {
				            '3-3-1': null,
				            '3-3-2': null,
				            '3-3-3': null,
			            	'3-3-4': null,
			            	'3-3-5': null,
		            	}
	            	}
            	};
            }

Последний раз редактировалось Esm1nec, 18.01.2020 в 14:11.
Ответить с цитированием
  #3 (permalink)  
Старый 18.01.2020, 15:29
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,068

зависимые селекты
Esm1nec,
выбирать для теста 1 , 1 - 1, ...
<!DOCTYPE html>
<html>
<head>
  <title>Untitled</title>
  <meta charset="utf-8">
</head>
<body>
<div class="chained-selects">
	<select id="select-1">
		<option selected>Choose level 1 option</option>
		<option>1</option>
		<option>2</option>
		<option>3</option>
	</select>
	<select id="select-2" disabled>
		<option selected>Choose level 2 option</option>
	</select>
	<select id="select-3" disabled>
		<option selected>Choose level 3 option</option>
	</select>
</div>
<script>
 var options = generateOptions();
document.querySelector('.chained-selects').addEventListener('change', onChange, false);
function onChange(e) {
	e.stopPropagation();
	var s = e.target;
	if (!s.nextElementSibling)
		return;
	var next = s.nextElementSibling;
	if (s.selectedIndex === 0)
		deactivateBoxes(next);
	else {
		var path = [];
		for (var p = s; p; p = p.previousElementSibling) {
			var selOptNode = p.options[p.selectedIndex];
			path.push(selOptNode.value);
		}
		path.reverse();
		var children = path.reduce(
			function(o, optName) {
				return o[optName];
			},
			options
		);
		/*
		if (children === null) {
			children = fetch(path);
			o[...] = children;
		}
		*/
        var values = next.id == "select-3" ? Object.values(children)  : [];
        children = Object.keys(children);
		// Insert children in s.nextChild
			for (var q = next.firstElementChild.nextElementSibling; q; q = nextq) {
				nextq = q.nextElementSibling;
				next.removeChild(q);
			}
			for (var i = 0; i < children.length; ++i) {
			    var text = children[i];
                var value =  values[i] || text;
				var optEl = new Option(text, value)
				next.appendChild(optEl);
			}
		next.selectedIndex = 0;
		next.disabled = false;
		deactivateBoxes(next.nextElementSibling);
	}
}
function deactivateBoxes(s) {
	while (s) {
		s.selectedIndex = 0;
		s.disabled = true;
		s = s.nextElementSibling;
	}
}
function generateOptions() {
	return {
		'1': {
			'1-1': {
				'1-1-1 codepen': 'https://codepen.io/',
				'1-1-2 google': 'https://www.google.com/'
			},
			'1-2': {
				'1-2-1': null,
				'1-2-2': null,
				'1-2-3': null,
				'1-2-4': null,
			},
			'1-3': {
				'1-3-1': null,
				'1-3-2': null,
				'1-3-3': null,
				'1-3-4': null,
				'1-3-5': null,
			}
		},
		'2': {
			'2-1': {
				'2-1-1': null,
				'2-1-2': null
			},
			'2-2': {
				'2-2-1': null,
				'2-2-2': null,
				'2-2-3': null,
				'2-2-4': null,
			},
			'2-3': {
				'2-3-1': null,
				'2-3-2': null,
				'2-3-3': null,
				'2-3-4': null,
				'2-3-5': null,
			}
		},
		'3': {
			'3-1': {
				'3-1-1': null,
				'3-1-2': null
			},
			'3-2': {
				'3-2-1': null,
				'3-2-2': null,
				'3-2-3': null,
				'3-2-4': null,
			},
			'3-3': {
				'3-3-1': null,
				'3-3-2': null,
				'3-3-3': null,
				'3-3-4': null,
				'3-3-5': null,
			}
		}
	};
}
document.querySelector("#select-3").addEventListener("change", function() {
if(this.value.startsWith("https") ) window.location = this.value;
})
</script>
</body>
</html>
Ответить с цитированием
  #4 (permalink)  
Старый 18.01.2020, 18:36
Аватар для Esm1nec
Новичок на форуме
Отправить личное сообщение для Esm1nec Посмотреть профиль Найти все сообщения от Esm1nec
 
Регистрация: 18.03.2018
Сообщений: 8

Снимаю шляпу!

Мне тут ещё друг помог, делюсь другим для помощи!

var options = generateOptions();

document
  .querySelector(".chained-selects")
  .addEventListener("change", onChange, false);

function onChange(e) {
  e.stopPropagation();

  var s = e.target;

  if (!s.nextElementSibling) return;

  var next = s.nextElementSibling;

  if (s.selectedIndex === 0) deactivateBoxes(next);
  else {
    var path = [];
    for (var p = s; p; p = p.previousElementSibling) {
      var selOptNode = p.options[p.selectedIndex];
      path.push(selOptNode.value);
    }
    path.reverse();

    var children = path.reduce(function(o, optName) {
      return o[optName];
    }, options);

    let childrenNames = [];

    for (let key in children) {
      let obj = {
        name: key,
        params: children[key]
      };

      childrenNames.push(obj);
    }

    // Insert childrenNames in s.nextChild
    for (let q = next.firstElementChild.nextElementSibling; q; q = nextq) {
      nextq = q.nextElementSibling;
      next.removeChild(q);
    }
    for (let i = 0; i < childrenNames.length; ++i) {
      let optEl = document.createElement("option");
      let current = childrenNames[i];
      let { name, params } = current;
      optEl.innerHTML = name;

      if (params && params.url) {
        optEl.setAttribute('url', params.url);
      }

      next.appendChild(optEl);
    }

    next.selectedIndex = 0;
    next.disabled = false;

    deactivateBoxes(next.nextElementSibling);
  }
}

function deactivateBoxes(s) {
  while (s) {
    s.selectedIndex = 0;
    s.disabled = true;

    s = s.nextElementSibling;
  }
}

function generateOptions() {
  return {
    audi: {
      "audi model 1": {
        "audi model 1 url 1": {
          url: "https://google.com"
        },
        "audi model 1 url 2": {
          url: "https://yandex.ru"
        }
      },
      "audi model 2": {
        "1-2-1": null,
        "1-2-2": null,
        "1-2-3": null,
        "1-2-4": null
      },
      "audi model 3": {
        "1-3-1": null,
        "1-3-2": null,
        "1-3-3": null,
        "1-3-4": null,
        "1-3-5": null
      }
    },
    "2": {
      "2-1": {
        "2-1-1": null,
        "2-1-2": null
      },
      "2-2": {
        "2-2-1": null,
        "2-2-2": null,
        "2-2-3": null,
        "2-2-4": null
      },
      "2-3": {
        "2-3-1": null,
        "2-3-2": null,
        "2-3-3": null,
        "2-3-4": null,
        "2-3-5": null
      }
    },
    "3": {
      "3-1": {
        "3-1-1": null,
        "3-1-2": null
      },
      "3-2": {
        "3-2-1": null,
        "3-2-2": null,
        "3-2-3": null,
        "3-2-4": null
      },
      "3-3": {
        "3-3-1": null,
        "3-3-2": null,
        "3-3-3": null,
        "3-3-4": null,
        "3-3-5": null
      }
    }
  };
}

var urlDropdownRef = document.querySelector("#select-3");
urlDropdownRef.addEventListener("change", onUrlDropdownChange);

function onUrlDropdownChange(e) {
  e.stopPropagation();

  let { target } = e;
  let { options, selectedIndex } = target;
  let selectedElem = options[selectedIndex];
  let url = selectedElem.getAttribute('url');

  if (url) {
    redirect(url);
  }
}

function redirect(url) {
  window.location.assign(url);
}
Ответить с цитированием
  #5 (permalink)  
Старый 19.01.2020, 10:17
Аватар для Malleys
Профессор
Отправить личное сообщение для Malleys Посмотреть профиль Найти все сообщения от Malleys
 
Регистрация: 20.12.2009
Сообщений: 1,714

Esm1nec, ещё способ...
<div class="chained-selects">
	<select id="select-1">
		<option selected>Choose level 1 option</option>
	</select>
	<select id="select-2" disabled>
		<option selected>Choose level 2 option</option>
	</select>
	<select id="select-3" disabled>
		<option selected>Choose level 3 option</option>
	</select>
</div>
<script>
const options = generateOptions();
const chainedSelects = document.querySelector(".chained-selects");
chainedSelects.addEventListener("change", onChange, false);
draw(chainedSelects.firstChild, options);

function onChange(event) {
	const { target } = event;
	let node = target, path = [];

	while (node = node.nextElementSibling) {
		node.length = 1;
		node.disabled = true;
	}

	if (target.selectedIndex === 0) return;

	node = target;
	do path.push(node.value);
	while (node = node.previousElementSibling);

	if (target.nextElementSibling) {
		const option = path.reduceRight((option, property) => option[property], options);
		draw(target, option);
	} else {
		const option = path.slice(1).reduceRight((option, property) => option[property], options);
		const value = option[target.value];
		if (value == null) return;
		location.href = value.url || value;
	}
}

function draw(target, option) {
	for (const [property, value] of Object.entries(option))
		target.nextElementSibling.add(new Option(property, property));
	target.nextElementSibling.disabled = false;
}

function generateOptions() {
	return {
		audi: {
			"audi model 1": {
				"audi model 1 url 1": {
					url: "https://google.com"
				},
				"audi model 1 url 2": {
					url: "https://yandex.ru"
				}
			}
		},
		"1": {
			"1-1": {
				"1-1-1": null
			},
			"1-2": {
				"1-2-1": null
			},
			"1-3": {
				"1-3-1": null,
				"1-3-2": null
			}
		}
	};
}
</script>

Последний раз редактировалось Malleys, 19.01.2020 в 10:19.
Ответить с цитированием
  #6 (permalink)  
Старый 20.10.2023, 14:15
Новичок на форуме
Отправить личное сообщение для MavR Посмотреть профиль Найти все сообщения от MavR
 
Регистрация: 20.10.2023
Сообщений: 3

Подскажите пожалуйста, я новичок, а как сделать чтобы ссылка открывалась в новой вкладке, куда нужно подставить window.open?
Ответить с цитированием
  #7 (permalink)  
Старый 20.10.2023, 14:42
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,701

Что бы ссылка открывалась
<a href="...url..." target="_blank">ссылка</a>
Ответить с цитированием
  #8 (permalink)  
Старый 20.10.2023, 15:07
Новичок на форуме
Отправить личное сообщение для MavR Посмотреть профиль Найти все сообщения от MavR
 
Регистрация: 20.10.2023
Сообщений: 3

Сообщение от рони Посмотреть сообщение
Esm1nec,
выбирать для теста 1 , 1 - 1, ...
<!DOCTYPE html>
<html>
<head>
  <title>Untitled</title>
  <meta charset="utf-8">
</head>
<body>
<div class="chained-selects">
	<select id="select-1">
		<option selected>Choose level 1 option</option>
		<option>1</option>
		<option>2</option>
		<option>3</option>
	</select>
	<select id="select-2" disabled>
		<option selected>Choose level 2 option</option>
	</select>
	<select id="select-3" disabled>
		<option selected>Choose level 3 option</option>
	</select>
</div>
<script>
 var options = generateOptions();
document.querySelector('.chained-selects').addEventListener('change', onChange, false);
function onChange(e) {
	e.stopPropagation();
	var s = e.target;
	if (!s.nextElementSibling)
		return;
	var next = s.nextElementSibling;
	if (s.selectedIndex === 0)
		deactivateBoxes(next);
	else {
		var path = [];
		for (var p = s; p; p = p.previousElementSibling) {
			var selOptNode = p.options[p.selectedIndex];
			path.push(selOptNode.value);
		}
		path.reverse();
		var children = path.reduce(
			function(o, optName) {
				return o[optName];
			},
			options
		);
		/*
		if (children === null) {
			children = fetch(path);
			o[...] = children;
		}
		*/
        var values = next.id == "select-3" ? Object.values(children)  : [];
        children = Object.keys(children);
		// Insert children in s.nextChild
			for (var q = next.firstElementChild.nextElementSibling; q; q = nextq) {
				nextq = q.nextElementSibling;
				next.removeChild(q);
			}
			for (var i = 0; i < children.length; ++i) {
			    var text = children[i];
                var value =  values[i] || text;
				var optEl = new Option(text, value)
				next.appendChild(optEl);
			}
		next.selectedIndex = 0;
		next.disabled = false;
		deactivateBoxes(next.nextElementSibling);
	}
}
function deactivateBoxes(s) {
	while (s) {
		s.selectedIndex = 0;
		s.disabled = true;
		s = s.nextElementSibling;
	}
}
function generateOptions() {
	return {
		'1': {
			'1-1': {
				'1-1-1 codepen': 'https://codepen.io/',
				'1-1-2 google': 'https://www.google.com/'
			},
			'1-2': {
				'1-2-1': null,
				'1-2-2': null,
				'1-2-3': null,
				'1-2-4': null,
			},
			'1-3': {
				'1-3-1': null,
				'1-3-2': null,
				'1-3-3': null,
				'1-3-4': null,
				'1-3-5': null,
			}
		},
		'2': {
			'2-1': {
				'2-1-1': null,
				'2-1-2': null
			},
			'2-2': {
				'2-2-1': null,
				'2-2-2': null,
				'2-2-3': null,
				'2-2-4': null,
			},
			'2-3': {
				'2-3-1': null,
				'2-3-2': null,
				'2-3-3': null,
				'2-3-4': null,
				'2-3-5': null,
			}
		},
		'3': {
			'3-1': {
				'3-1-1': null,
				'3-1-2': null
			},
			'3-2': {
				'3-2-1': null,
				'3-2-2': null,
				'3-2-3': null,
				'3-2-4': null,
			},
			'3-3': {
				'3-3-1': null,
				'3-3-2': null,
				'3-3-3': null,
				'3-3-4': null,
				'3-3-5': null,
			}
		}
	};
}
document.querySelector("#select-3").addEventListener("change", function() {
if(this.value.startsWith("https") ) window.location = this.value;
})
</script>
</body>
</html>
Простите, я не правильно выразился, меня интересует как в этом готовом решении нужно правильно подправить, чтобы ссылка после выбора из выпадающего списка открывалась в новой вкладке?
Ответить с цитированием
  #9 (permalink)  
Старый 20.10.2023, 16:34
Новичок на форуме
Отправить личное сообщение для MavR Посмотреть профиль Найти все сообщения от MavR
 
Регистрация: 20.10.2023
Сообщений: 3

Вроде получилось)
заменил это
document.querySelector("#select-3").addEventListener("change", function() {
if(this.value.startsWith("https") ) window.location = this.value;
})


на это

document.querySelector("#select-3").addEventListener("change", function() {
if(this.value.startsWith("https")) window.open(this.value);
})
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Зависимые списки! DSHA Элементы интерфейса 12 27.06.2012 12:27
проблема с переходом на url ret1k Events/DOM/Window 3 20.10.2011 20:42
Воздействие на страницу с помощью JS через URL dimaan777 Javascript под браузер 7 23.08.2011 10:50
JS на конкретный Url Blizzart Общие вопросы Javascript 5 21.02.2010 19:23
Отображение длинного URL с помощью JS velo Общие вопросы Javascript 2 28.10.2009 10:07