Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
PHP Puzzles. Авторы: Кузнецов М.В., Симдянов И.В. PHP на примерах (2 издание). Авторы: Кузнецов М.В., Симдянов И.В. Объектно-ориентированное программирование на PHP. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5/6. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. C++. Мастер-класс в задачах и примерах. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

HTML+CSS+JavaScript

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Помогите пожалуйста найти ошибку в JS
 
 автор: kosta_in_net   (10.11.2011 в 23:31)   письмо автору
 
 

Не могу найти причину, почему не удаляется выполнить удаление элемента из массива

<div id=tabsbody>
    <div class=tab>
        ...
    </div>
    <div class=tab>
        ...
        <div class=other>...</div>

    </div>
</div>
<script>
    var coll_blocks = document.getElementById("tabsbody").getElementsByTagName("div");
    for(i=coll_blocks.length-1;i>0;i--){
        if(coll_blocks[i].className !='tab'){
            coll_blocks.splice(i,1);
        }
    }
</script>

Кто-нибудь, помогите сделать код, способный удалить из коллекции coll_blocks дивы с классом, отличающимся от "tab".

  Ответить  
 
 автор: АЯС   (11.11.2011 в 00:14)   письмо автору
 
   для: kosta_in_net   (10.11.2011 в 23:31)
 

Это баг метода splice ().
Реализован в JS он криво - первый элемент (с нулевым индексом) он не удаляет.

Потому в вашем случае лучше формировать новый массив, который будет содержать только нужные вам элементы, и в дальнейшем работать с этим новым массивом:
var coll_blocks = document.getElementById ("tabsbody").getElementsByTagName ("div");
for (var new_blocks = [], j = i = 0; i < coll_blocks.length; i++) 
   if (coll_blocks [i].className == 'tab') new_blocks [j++] = coll_blocks [i];

  Ответить  
 
 автор: kosta_in_net   (11.11.2011 в 01:05)   письмо автору
 
   для: АЯС   (11.11.2011 в 00:14)
 

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

  Ответить  
 
 автор: АЯС   (11.11.2011 в 01:26)   письмо автору
 
   для: kosta_in_net   (11.11.2011 в 01:05)
 

Хе-хе... купил я вас за "рупь-двадцать".

У метода splice (как и у яваскрипта) проблем нет.
Моё ложное утверждение ("не удаляет первый элемент") проверить было легче лёгкого:
 var arr = [1,2,3]; arr.splice (0, 1); alert (arr);

Но вам захотелось поверить в "баг".
-----

У вас неверно было написано условие выхода из цикла. Сравните:
for(i=coll_blocks.length-1;i>0;i--) //неверно 

for(i=coll_blocks.length-1;i==0;i--) //правильно

  Ответить  
 
 автор: kosta_in_net   (11.11.2011 в 01:39)   письмо автору
 
   для: АЯС   (11.11.2011 в 01:26)
 

в вашем случае ничего не удаляется

<div id=tabsbody>
    <div class=tab>
        ...
    </div>
    <div class=tab>
        ...
        <div class=other>...</div>

    </div>
</div>
<script>
    coll_blocks = document.getElementById("tabsbody").getElementsByTagName("div");
    a='';
    for(i=0;i<coll_blocks.length;i++){
        a+=' '+coll_blocks[i].className;
    }
    alert(a);
    for(i=coll_blocks.length-1;i==0;i--){
        if(coll_blocks[i].className !='tab'){
            coll_blocks.splice(i,1);
        }
    }
    a='';
    for(i=0;i<coll_blocks.length;i++){
        a+=' '+coll_blocks[i].className;
    }
    alert(a);
</script>

Так как выход из цикла происходит сразу, поскольку i никогда не равно 0.

Но дело даже не в нулевом индексе. Скорее всего функция просто не применима к массиву объектов:

<div id=tabsbody>
    <div class=tab>
        ...
    </div>
    <div class=tab>
        ...
        <div class=other>...</div>

    </div>
</div>
<script>
    coll_blocks = document.getElementById("tabsbody").getElementsByTagName("div");
    a='';
    for(i=0;i<coll_blocks.length;i++){
        a+=' '+coll_blocks[i].className;
    }
    alert(a);
    for(i=coll_blocks.length-1;i>0;i--){
        if(coll_blocks[i].className !='tab'){
            alert('index='+i+'\nclassName='+coll_blocks[i].className);
            coll_blocks.splice(i,1);
            alert('Yes!');
        }
    }
</script>

Сообщение Yes! не появляется. Даже просто
coll_blocks.splice(1,1);
вызывает ошибку

  Ответить  
 
 автор: АЯС   (11.11.2011 в 05:34)   письмо автору
 
   для: kosta_in_net   (11.11.2011 в 01:39)
 

Итак, теперь по-серьёзному.

1. Имеем какой-то массив под названием array_111

2. Если мы запишем array_222 = array_111, то мы НЕ создадим НОВОГО САМОСТОЯТЕЛЬНОГО массива array_222, мы просто сделаем ССЫЛКУ на первый массив.

3. ПОЭТОМУ всё, что мы будем делать с массивом array_222, будет происходить и с массивом array_111.
Если ко второму массиву добавим элемент, то он добавится и к первому.
Соответственно, если удалим элемент из второго массива, то он удалится и из первого.
Пример:
<script> 
var array_111 = [0,1,2,3];
var array_222 = array_111;

array_222.push (4); //добавляем ко второму массиву ещё один элемент в конец
array_222.splice (0, 1); //удаляем из второго массива самый первый элемент

alert (array_111 + '\n' + array_222); //видим, что изменились ОБА массива и изменились ОДИНАКОВО
//хотя с первым массивом мы как бы ничего не делали
</script> 
-----

В вашем случае первый массив - это коллекция document.getElementById ("tabsbody").getElementsByTagName ("div") и эта коллекция - она только для чтения, изменять эту коллекцию НЕЛЬЗЯ. Ни добавлением элементов, ни удалением элементов. Она такая, какая она есть, её элементы определяются наличием DIV'ов в документе.
Массив coll_blocks является ССЫЛКОЙ на эту коллекцию, следовательно, ИЗМЕНЯТЬ массив coll_blocks ТОЖЕ НЕЛЬЗЯ.
-----

Решение: Массив coll_blocks вам надо сформировать при помощи конструктора. А именно так:
<script>
//формируем массив с помощью конструктора
for (var coll_blocks = new Array (), j = 0; j < document.getElementById ('tabsbody').getElementsByTagName ('div').length; j++)
coll_blocks [j] = document.getElementById ('tabsbody').getElementsByTagName ('div') [j];

//удаляем ненужные элементы
for (var i = coll_blocks.length - 1; i >= 0; i--) //обращаем внимание на правильную запись условия выхода из цикла
   if (coll_blocks [i].className != 'tab') coll_blocks.splice (i, 1);

//как видим, метод splice () прекрасно работает. В том числе и с объектами.
</script>


PS. Сорри за две мои предыдущие мессаги. Никак не думал, что бутылка коньяку так повлияет... старею, видимо...

  Ответить  
 
 автор: kosta_in_net   (11.11.2011 в 12:16)   письмо автору
 
   для: АЯС   (11.11.2011 в 05:34)
 

Еще до вашей первой мессаги сделал так:

    var coll_blocks_x = document.getElementById("tabsbody").getElementsByTagName("div");
    var coll_blocks=new Array();
    var a=0;
    for(i=0;i<coll_blocks_x.length;i++){
        if(coll_blocks_x[i].className =='tab'){
            coll_blocks[a]=coll_blocks_x[i];
            a++;
        }
    }

Это компактней и быстрее работает. Однако за мысль о том, что в splice есть баг, спасибо. Именно после этой идеи до меня дошло, что дело не в ошибке кода, а в самом splice, который не применим к коллекции и, следовательно, не следовало пытаться изменить им коллекцию.

  Ответить  
 
 автор: АЯС   (11.11.2011 в 17:51)   письмо автору
 
   для: kosta_in_net   (11.11.2011 в 12:16)
 

Увы, сути, по-моему, вы не поняли.

Дело совсем не в splice ().
Метод push () также неприменим.
И метод pop () не будет работать...
А также и ВСЁ прочее, с помощью чего вы будете пытаться фактически изменить то, что является read only.

Например, если вы (безо всяких методов) пропишете coll_blocks [j] = '', или coll_blocks [j] = new Array (), то это тоже у вас не получится (если coll_blocks будет у вас ссылкой на объект read only).

  Ответить  
 
 автор: kosta_in_net   (15.11.2011 в 19:20)   письмо автору
 
   для: АЯС   (11.11.2011 в 17:51)
 

Это ли не суть: "splice ... не применим к коллекции"? О пушах или причинах неприменимости речь не идет. Просто до фразы о багах, я думал, что допустил какую-то ошибку в коде. А оказалось, что пытаюсь выполнить невозможное (то есть, ошибка не в том, как написано, а в самом подходе)

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования