×
Внимание, мошенник-работодатель (10 авг 2017)

Вниманию программистов Санкт-Петербурга, на SuperJob-е вновь активизировался Семен Григорьевич Шумейко..

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

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


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>
Последнее редактирование: 1 год 2 мес. назад от p.rishard.

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

Больше
1 год 2 мес. назад - 1 год 2 мес. назад #2 от Aleksej
Aleksej ответил в теме JavaScript SELECT. Динамические списки
Начнем с утверждения, что способов реализовать связанные списки - JavaScript SELECT - очень и очень немало. Даже без всякого AJAX. Но, просмотрев ряд форумов рунета, я увидел кое-где настолько громоздкие решения, что... невольно возник вопрос, считать ли километры кода за действительно решение профессиональное. И в качестве разумной альтернативы подобному подходу приведу здесь вот такой скрипт, вполне себе адекватный и довольно компактный:


<!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 - данные формочки. Это способно быть, например, следующим образом:


<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 . На момент создания этого материала он выглядит следующим образом:


/*! 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);


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


<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>


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


<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-класс не может состоять из двух слов и содержать пробелы... таким образом, осталось сделать последний штрих, задействовав регулярки:


<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>


И вот теперь это действительно все. Хотя продолжение, как обычно, следует.
Последнее редактирование: 1 год 2 мес. назад от Aleksej.

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

Больше
1 год 2 мес. назад - 1 год 2 мес. назад #3 от serge
serge ответил в теме JavaScript SELECT. Динамические списки

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



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


First you must include jQuery and Chained in your 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:
<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.
$("#series").chained("#mark"); /* or $("#series").chainedTo("#mark"); */[/quote]


А я смогу! - А поглядим! - А я упрямый!
Последнее редактирование: 1 год 2 мес. назад от serge.
Спасибо сказали: Aleksej

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.