Joomla 4. Компонент K2 и форк K2ForJ4 (18 янв 2024)

Если вас, как и меня, достало выслушивать (вычитывать) бесконечные обещания разработчика K2 опубликовать версию компонента K2 под Joomla 4 (без чего невозможно реализовать апгрейд from Joomla 3 to Joomla 4) - воспользуйтесь форком K2ForJ4. Который в данный момент установлен и без каких-либо проблем работает на этом веб-сайте.

JavaScript SELECT. Динамические списки

Больше
8 года 2 нед. назад - 8 года 2 нед. назад #1 от Aleksej
Представленный материал относится к циклу статей о jTriad contact form , и в то же время данный пост можно рассматривать как совершенно отдельный учебный материал, посвященный нередко возникающей у новичков-кодеров проблеме создания JavaScript SELECT - динамических связанных списков. Да, мы оставим сегодня в стороне технологию AJAX и разберем, насколько сможем подробно, способы применить именно джаваскрипт в этом контексте; а jTriad contact form послужит нам площадкой для работы. Надо же где-то брать данные для отображения в наших зависимых селектах! - ну и вот, почему бы не взять ее из масссивов формочки. Итак, JavaScript SELECT - динамические списки... да, но прежде всего необходимо чуть реорганизовать php-скрипты, берущие начало еще от Fancy AJAX Contact Form - модуля Joomla 3 . Быстренько сделаем это следующим образом, и вперед:


Code:
Add ModContactformMasterproMailSettings::getAllVacanciesByCity() method diff --git a/ModContactformMasterproMailSettings.class.php b/ModContactformMasterproMailSettings.class.php index 0b29bb6..1f6fa81 100644 --- a/ModContactformMasterproMailSettings.class.php +++ b/ModContactformMasterproMailSettings.class.php @@ -43,8 +43,33 @@ private $arr; return array_keys($this->arr); } + /** + * Returns array of all possible vacancies in all cities. + * + * @return One dimentional array. + */ public function getAllVacancies(){ - return array_unique(call_user_func_array('array_merge', array_map(create_function('$x', 'return array_keys($x);'), array_values($this->arr))) + return array_unique( + call_user_func_array( + 'array_merge' + ,array_map( + create_function('$x', 'return array_keys($x);') + ,array_values($this->arr) + ) + ) + ); + } + + /** + * Array of cities which are the arrays ov vacancies in it. + **/ + public function getAllVacanciesByCity(){ + return array_map( + function($a){ + return array_keys($a); + } + , $this->arr + ); } public function getMailByCityAndVacancy($city, $vacancy){ diff --git a/tmpl/default.php b/tmpl/default.php index d8d37ce..5bcac5f 100644 --- a/tmpl/default.php +++ b/tmpl/default.php @@ -85,4 +85,8 @@ $oldData = $session->get('postTwergewrtgert', '', SESSION_NAMESPACE); <div class="error" id="errorMessage"><?=$errorMessage?></div> </form> <?=$successMessage?> -</div> \ No newline at end of file +</div>
Последнее редактирование: 8 года 2 нед. назад пользователем p.rishard.
Тема заблокирована.
Dev banner 1
Больше
8 года 2 нед. назад - 8 года 2 нед. назад #2 от Aleksej
Начнем с утверждения, что способов реализовать связанные списки - JavaScript SELECT - очень и очень немало. Даже без всякого AJAX. Но, просмотрев ряд форумов рунета, я увидел кое-где настолько громоздкие решения, что... невольно возник вопрос, считать ли километры кода за действительно решение профессиональное. И в качестве разумной альтернативы подобному подходу приведу здесь вот такой скрипт, вполне себе адекватный и довольно компактный:


Code:
<!DOCTYPE html> <html> <head> <title>Test</title> <script> var users = Array('Petya','Vasya'); var admins = Array('Kolya','Seva'); function showNames(v){ var mas = eval(v); var el = document.getElementById('names'); while(el.childNodes.length>0){ el.removeChild(el.childNodes[el.childNodes.length-1]); } for(var i=0;i<mas.length;i++){ var opt = document.createElement("option"); opt.innerHTML=mas[i]; el.appendChild(opt); } } </script> </head> <body onload="showNames('admins')"> <select id="level" onchange="showNames(this.value)"> <option value="admins">ADMIN</option> <option value="users">USER</option> </select> <select id="names"> </select> </body> </html>


Вполне грамотно, одним словом. Берите на вооружение... сохраните приведенный код в виде текстового файла и откройте в браузере - получите отличный пример связанных селектов. Теперь давайте подумаем, каким же образом нам с вами подставить в скрипт вместо Petya,Vasya - данные формочки. Это способно быть, например, следующим образом:


Code:
<script> <? $lists = $mailSettings->getAllVacanciesByCity(); foreach($lists as $key => $value) { echo( " var $key = Array(\n"); $string = ''; foreach($value as $lists) $string .= ",'$lists'"; { $string = substr($string, 1); echo ("$string \n"); } echo ');'; } ?> function showNames(v){ var mas = eval(v); var el = document.getElementById('names'); while(el.childNodes.length>0){ el.removeChild(el.childNodes[el.childNodes.length-1]); } for(var i=0;i<mas.length;i++){ var opt = document.createElement("option"); opt.innerHTML=mas[i]; el.appendChild(opt); } } </script> <body onload="showNames('Chicago')"> <select id="level" onchange="showNames(this.value)"> <? foreach($mailSettings->getAllCyties() as $city){ echo "<option value='" . htmlentities(trim($city), ENT_QUOTES, "UTF-8") . "'>$city</option>"; } ?> </select> <select id="names">



Вот как-то так. Если подставите этот код в конце default.php старого варианта формочки - увидите его в действии (сказанное справедливо и для последующих ревизий кода, приведенных в этой статье). Скажем прямо, решение для поставленной задачки нелучшее, хотя и вполне себе работает. Но у нас с вами возникают некоторые затруднения, например - если название города в первом селекте состоит из двух слов. Проблема не самая глобальная, но... но попробуем все-таки пойти по иному пути.

Нам с вами поможет очень небольшой и крайне полезный скрипт, актуальную версию которого всегда можно достать на гитхабе: jquery.chained.min.js . На момент создания этого материала он выглядит следующим образом:


Code:
/*! Chained 1.0.0 - MIT license - Copyright 2010-2014 Mika Tuupola */ !function(a,b){"use strict";a.fn.chained=function(c){return this.each(function(){function d(){var d=!0,g=a("option:selected",e).val();a(e).html(f.html());var h="";a(c).each(function(){var c=a("option:selected",this).val();c&&(h.length>0&&(h+=b.Zepto?"\\\\":"\\"),h+=c)});var i;i=a.isArray(c)?a(c[0]).first():a(c).first();var j=a("option:selected",i).val();a("option",e).each(function(){a(this).hasClass(h)&&a(this).val()===g?(a(this).prop("selected",!0),d=!1):a(this).hasClass(h)||a(this).hasClass(j)||""===a(this).val()||a(this).remove()}),1===a("option",e).size()&&""===a(e).val()?a(e).prop("disabled",!0):a(e).prop("disabled",!1),d&&a(e).trigger("change")}var e=this,f=a(e).clone();a(c).each(function(){a(this).bind("change",function(){d()}),a("option:selected",this).length||a("option",this).first().attr("selected","selected"),d()})})},a.fn.chainedTo=a.fn.chained,a.fn.chained.defaults={}}(window.jQuery||window.Zepto,window,document);


, а наши с вами динамические селекты приобретают следующие черты, уже отдаленно напоминающие то, к чему в итоге хотелось бы прийти:


Code:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> <script src="//jquery.chained.min.js"></script> <select id="town" name="town"> <option value="">--</option> <? $lists = $mailSettings->getAllVacanciesByCity(); foreach($lists as $key => $value) { foreach($value as $lists) { echo ("<option value=" . "\"$key\"" . ">" . "$key" ."</option>"); }} ?> </select> <select id="vac" name="vac"> <option value="">--</option> <? $lists = $mailSettings->getAllVacanciesByCity(); foreach($lists as $key => $value) { $string = ''; foreach($value as $lists) $string .= "$lists"; { echo ("<option value=" . "\"$string\"" . " class=" . " \"$key\"" . ">" . "$string" . "</option>"); }} ?> </select> <script> $("#vac").chained("#town"); </script>


Снова все работает, снова остались лишь совсем небольшие минусы... в частности, код довольно неуклюж, к тому же на выходе мы рискуем получить два одинаковых названия города в первом селекте, если в админке модуля предусмотрены для одного города две разные вакансии. Идем дальше:


Code:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> <script src="//jquery.chained.min.js"></script> <select id="town" name="town"> <option value="">--</option> <?foreach($mailSettings->getAllCyties() as $city){?> <option value="<?=htmlentities($city)?>"><?=$city?></option> <?} ?> </select> <select id="vac" name="vac"> <option value="">--</option> <?foreach($mailSettings->getAllVacanciesByCity() as $city => $vacancies){ foreach ($vacancies as $vacancy){?> <option value="<?=htmlentities($vacancy)?>" class="<?=htmlentities($city)?>"><?=$vacancy?></option> <?} }?> </select> <script> $("#vac").chained("#town"); </script>


Так значительно лучше, не правда ли? - но одно по-прежнему плохо: css-класс не может состоять из двух слов и содержать пробелы... таким образом, осталось сделать последний штрих, задействовав регулярки:


Code:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> <script src="//f09954de.bget.ru/test/test2/jquery.chained.min.js"></script> <select id="town" name="town"> <option value="">--</option> <?foreach($mailSettings->getAllCyties() as $city){?> <option value="<?=preg_replace('/[^\w\d]/iu', '_', $city)?>"><?=$city?></option> <?} ?> </select> <select id="vac" name="vac"> <option value="">--</option> <?foreach($mailSettings->getAllVacanciesByCity() as $city => $vacancies){ foreach ($vacancies as $vacancy){?> <option value="<?=htmlentities($vacancy)?>" class="<?=preg_replace('/[^\w\d]/iu', '_', $city)?>"><?=$vacancy?></option> <?} }?> </select> <script> $("#vac").chained("#town"); </script>


И вот теперь это действительно все. Хотя продолжение, как обычно, следует.
Последнее редактирование: 8 года 2 нед. назад пользователем Aleksej.
Тема заблокирована.
Больше
8 года 2 нед. назад - 8 года 2 нед. назад #3 от serge

Aleksej пишет: Нам с вами поможет очень небольшой и крайне полезный скрипт, актуальную версию которого всегда можно достать на гитхабе: jquery.chained.min.js .



Ты позабыл оставить ссылку на сайт разраба скрипта:
www.appelsiini.net/projects/chained
Также полезно сказать, что HTML зависимых селектов будет выглядеть в этом случае так:


First you must include jQuery and Chained in your code:

Code:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> <script src="jquery.chained.min.js"></script>

Then lets assume you have the following HTML code:
Code:
<select id="mark" name="mark"> <option value="">--</option> <option value="bmw">BMW</option> <option value="audi">Audi</option> </select> <select id="series" name="series"> <option value="">--</option> <option value="series-3" class="bmw">3 series</option> <option value="series-5" class="bmw">5 series</option> <option value="series-6" class="bmw">6 series</option> <option value="a3" class="audi">A3</option> <option value="a4" class="audi">A4</option> <option value="a5" class="audi">A5</option> </select>
You can now chain the #series to #mark. There are two different ways to do it. Choose yourself if you prefer more english like or shorter version. I prefer the shorter version.
Code:
$("#series").chained("#mark"); /* or $("#series").chainedTo("#mark"); */[/quote]


А я смогу! - А поглядим! - А я упрямый!
Последнее редактирование: 8 года 2 нед. назад пользователем serge.
Спасибо сказали: Aleksej
Тема заблокирована.
Больше
6 года 3 мес. назад #4 от yotson
Здравствуйте. Я может быть, не в ту ветку форума. Но вопрос имеет отношение к связанным селектам. Как сделать, посоветуйте, если нужно чтобы по определенным выборам селектов открывалось текстовое поле?
Тема заблокирована.
Больше
6 года 3 мес. назад #5 от serge

yotson пишет: если нужно чтобы по определенным выборам селектов открывалось текстовое поле?


Это совсем просто:

Code:
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Тест</title> </head> <body> <select onchange="this.value=='мир'?document.getElementById('blablabla').style.display='':document.getElementById('blablabla').style.display='none'"> <option value=""></option> <option value="мир">мир</option> <option value="труд">труд</option> <option value="май">май</option> </select> <div><textarea id="blablabla" rows="5" style="display:none; width:50%;"></textarea></div> </body> </html>

А я смогу! - А поглядим! - А я упрямый!
Спасибо сказали: yotson
Тема заблокирована.
Больше
6 года 3 мес. назад #6 от yotson
а если нужно чтобы не по одному селекту из трех textarea открывалось, а по нескольким?
Тема заблокирована.
Больше
6 года 3 мес. назад #7 от Aleksej

yotson пишет: а если нужно чтобы не по одному селекту из трех textarea открывалось, а по нескольким?



Как вариант. :)

Code:
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Тест</title> </head> <body> <select onchange="this.value.includes('р')?document.getElementById('blablabla').style.display='':document.getElementById('blablabla').style.display='none'"> <option value=""></option> <option value="мир">мир</option> <option value="труд">труд</option> <option value="май">май</option> </select> <div><textarea id="blablabla" rows="5" style="display:none; width:50%;"></textarea></div> </body> </html>
Тема заблокирована.
Больше
6 года 3 мес. назад #8 от unior
еще вот так можно

Code:
<input type="checkbox" checked="checked" onclick="if(this.checked){this.nextSibling.style.display=''}else {this.nextSibling.style.display='none'; this.nextSibling.value='';}"><input type="text">

Источник
Тема заблокирована.
Больше
4 года 11 мес. назад #9 от Aleksej
Еще один интересный скрипт на тему

Chained Selects

html
Code:
<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>

js
Code:
<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; } */ 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); } 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, } } }; } </script>

Взглянуть возможно здесь .
Тема заблокирована.
Больше
4 года 11 мес. назад - 4 года 11 мес. назад #10 от serge

serge пишет: www.appelsiini.net/projects/chained


Объединение bootstrap-select и jquery-chained:

html
Code:
<select id="mark" name="mark" class="selectpicker" multiple data-max-options="2"> <option value="">--</option> <option value="bmw">BMW</option> <option value="audi">Audi</option> </select> <select id="series" name="series" class="selectpicker" multiple data-max-options="2"> <option value="">--</option> <option value="series-3" class="bmw">3 series</option> <option value="series-5" class="bmw">5 series</option> <option value="series-6" class="bmw">6 series</option> <option value="a3" class="audi">A3</option> <option value="a4" class="audi">A4</option> <option value="a5" class="audi">A5</option> </select>

javascript
Code:
*! Chained 1.0.0 - MIT license - Copyright 2010-2014 Mika Tuupola */ !function (a, b) { "use strict"; a.fn.chained = function (c) { return this.each(function () { function d() { var d = !0; a(e).html(f.html()); var h = a("option:selected", this).parent().val(); var arr = h.toString().split(","); a("option", e).each(function () { var current_class = a(this).attr("class"); if(h != current_class && $.inArray(current_class, arr) < 0){ a(this).remove() } }); if (1 === a("option", e).size() && "" === a(e).val()) { a(e).prop("disabled", !0) } else { a(e).prop("disabled", !1) } d && a(e).trigger("change") } var e = this, f = a(e).clone(); a(c).each(function () { a(this).bind("change", function () { d() }), a("option:selected", this).length || a("option", this).first().attr("selected", "selected"), d() }) }) }, a.fn.chainedTo = a.fn.chained, a.fn.chained.defaults = {} }(window.jQuery || window.Zepto, window, document); $('selectpicker').selectpicker(); $('select').on('change', function() { $(this).selectpicker('refresh'); }); $("#series").chained("#mark");

jsfiddle.net/80zkodod/1/

А я смогу! - А поглядим! - А я упрямый!
Последнее редактирование: 4 года 11 мес. назад пользователем serge.
Тема заблокирована.
Работает на Kunena форум