Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Мозговой штурм !!!! Построение иерархической модели данных. (https://javascript.ru/forum/misc/21155-mozgovojj-shturm-postroenie-ierarkhicheskojj-modeli-dannykh.html)

DjDiablo 30.08.2011 20:04

Мозговой штурм !!!! Построение иерархической модели данных.
 
Всем доброго времени суток.

Есть
элементы с классом column в них вложены элементы с классом portlet, в portlet вложены элементы с классом column, а в этот новый column снова portlets и так как угодно много.

стоит задача превратить всю эту абракадабру в дерево данных и хранит в обьекте.
Должно получится что то вроде

........................колумн
......................./
............портлет- колумн
........../............\
колумн ..............колумн
..........\
...........портлет

сразу отвечаю на вопрос а нафига это надо.
Всё дело в том что мне надо анализировать вложенность портлетов и колумнов при каждом движении мышки над областью портлетов, поэтому я стремлюсь прокешировать информацию чтобы сократить до минимума работу с селекторами, и добиться приличной скорости, за счёт работы только с нужными ветвями дерева.

в результате всего должен получится аналог UI sortable
Но с возможностью размещать ёмкости для портлетов(.column) внутри портлетов, к сожалению ui sortable глубокую вложенность не поддерживает.

Пытаюсь реализовать создание дерева методом рекурсии.

function trackman (obj,type){  //рекурсивная функция обходчик.
    this.link=obj; //ссылка на элемент DOM для каких нибудь манипуляций с ним   
    this.name=$(obj).attr("id");  // ID портлета или column  
    this.subject=[];                 // обьявляем массив в котором храним дочерние обьекты.
    self=this;                         // делаем ссылку на контекст чтобы использовать его  внутри  each
    if (type==1){ // если изучаем column, тоесть ищем портлеты
        jQuery.each($(obj).find(">.portlet"), function(){            
            self.subject.push(new trackman(this,-1));            //вызываем обходчик для каждого найденного портлета
        });         
    } else {      //если изучаем portlet, тоесть ищем column                
        jQuery.each($(obj).find(".column:not(.column .column)"), function(){                                                                   
            self.subject.push(new trackman(this,1));             //вызываем обходчик для каждого найденного column                                    
        });
    }                          

//функция строительства дерева
function arrangerRefrash(){
var i=0;
jQuery.each($(".wrpage> .column"),function(){ // перебираем все column    
   arrObj[i]=new trackman (this,1)                           
   i=i+1;            
});
}


но нофига невыходит, так как вместо массива с портлет я получаю portlets вложенные друг в друга.

DjDiablo 30.08.2011 20:18

только сейчас пришла идея, заменить $.each на обычный for, это позволит упростить код и избавится от захвата контекста в self. Но не уверен что это как то поможет ))))))

popov654 30.08.2011 20:20

А вложенные друг в друга portlet и column Вас, судя по коду, не интересуют, верно я понял?

Оффтоп: не понял Вашу подпись :) Ни первую её мысль, ни вторую... :blink:

DjDiablo 30.08.2011 20:26

Portlet может находится только внутри column
Column'ы только внутри portlet.

Portlet не может находится внутри portlet непосредственно.
Портлет можно разместить только в контейнере column. А вот уже column находится в каком нибудь портлете.

Пример
мы имеем column во всю страницу.
1)Пользователь пераскивает в него портлет "текст". и пишет большими буквами заголовок.
2) Затем он перетаскивает ниже текста портлет "Layer", внутри которого есть 3 column- левый,центральный,и правый. как при стандартной разметки страницы
3) пользователь заполняет column'ы портлетами с контентом.

Вот собственно откуда вложенность.

офтоп: как то нехочется обьяснять свой статус буквально )). Спросите у майкрософта ))).

popov654 30.08.2011 20:32

А, ну тогда всё логично)

DjDiablo 30.08.2011 20:56

Цитата:

Сообщение от popov654 (Сообщение 123657)
А, ну тогда всё логично)

Это сарказм ?.
или это логично но не работает ))))

DjDiablo 30.08.2011 21:16

А вот это вот похоже работает.

function trackman (obj,type){      
    this.link=obj;                      //ссылка на обьект для манипуляция.
    this.name=$(obj).attr("id");   //сохраняем id  
    this.subject=[];                  //здесь храним вложенные обьекты
    if (type==1){ // если изучаем column, тоесть ищем портлеты
        finder=$(obj).find(">.portlet");  //делаем выборку
        length=finder.length;              // определяем длинну выборки
        
        for (i=0;i<length;i++){            // перебираем выборку в цикле                   
            this.subject.push(new trackman(finder[i],-1));     // передаём в рекурсию            
       }                                                  
        console.log(this); //показываем в логе что у нас получилось
                              
    } else {      //если изучаем portlet, тоесть ищем column                
        jQuery.each($(obj).find(".column:not(.column .column)"), function(){ // здесь пока на FOR не менял, но поменяю                                                                  
            self.subject.push(new trackman(this,1));                                                
        });//*/                                  
    }                          
}

function arrangerRefrash(){
var i=0;
jQuery.each($(".wrpage> .column"),function(){ // перебираем все column    
   arrObj[i]=new trackman (this,1)  ;                         
   i=i+1;            
});
}


Значит проблема была в контексте сохранённом в self, хотя механизьм это проблемы я так до конца и не понял. Всё равно спасибо, недогнал пока не написал на форум. )))

popov654 30.08.2011 23:39

Цитата:

Это сарказм ?.
Да Боже упаси) Просто пытался написать что-нибудь по делу. Я вообще jQuery ещё не изучал :)

Цитата:

Спросите у майкрософта )))
Очень смешно :(

ksa 31.08.2011 09:16

Цитата:

Сообщение от DjDiablo
Есть
элементы с классом column в них вложены элементы с классом portlet, в portlet вложены элементы с классом column, а в этот новый column снова portlets и так как угодно много.

стоит задача превратить всю эту абракадабру в дерево данных и хранит в обьекте.

У нас объектноориентированая СУБД... Сделал бы хранение в двух табличках/объектах

column
Код
Код-ссылка на экземпляр в portlet
Другие поля


portlet
Код
Код-ссылка на экземпляр в column
Другие поля

kadabrik 31.08.2011 13:10

ksa дело говорит, храни все не в иерархическом, а в релиационном виде, алгоритмы будут проще, а скорость в разы выше.

DjDiablo 31.08.2011 17:02

Цитата:

Сообщение от kadabrik (Сообщение 123809)
ksa дело говорит, храни все не в иерархическом, а в релиационном виде, алгоритмы будут проще, а скорость в разы выше.

Ребят нечего против не имею. В процессе реализации я получаю стабильно бесконечную рекурсию, которая должна идеально работать на C++ но на javascript отказывается, и очевидно что проблема в коттексте. Так что я не против уже отказатся от рекурсии, можно по подробнее как вы предлагаете это реализовать.
если делать дерево при помощи циклов, мне всё равно придётся прибегать к стекам и имулировать рекурсию.
Так что реаляционная модель этом плане интереснее так как сводится к двум таблицам.

Надо полагать что нужно составить два массива, один с колумнами с указанием родительских portlet.
другой с портлетами с указанием родительских column.

Как вы предлагаете реализовать решение ?

вот код на данный момент, но его результат бесконечная рекурсия.
function trackman (obj,type){      
    this.link=obj;    //ссылка на обьект для дальнейших мманипуляций
    this.name=$(obj).attr("id");   //id анализируемого обьекта           
    this.subject=[];                  //вложенные субьекты 
    if (type==1){ // если изучаем column, тоесть ищем портлеты                
        var finder=$(obj).find(">.portlet"); //ссылка на выборку портлетов
        var length=finder.length;             //Количество вложенных портлетов
                
        for (i=0;i<length;i++){                // перебор портлетов
            var thisobj= finder[i];                                                                     
            this.subject.push(new trackman(thisobj,-1)); //вызываем рекурсию
            
       }                                                  
       console.log(this);
                              
    } else {      //если изучаем portlet, тоесть ищем column                          
        
      var finder2=$(obj).find(".column:not(.column .column)");      
        var length2=finder2.length;
        
        for(var i2=0;i2<length2;i2++){     
            thisobj2= finder2[i];
            this.subject.push(new trackman(thisobj2,1));                                                                                   
        };                   
    }                          
}

function arrangerRefrash(){
var i=0;
jQuery.each($(".wrpage> .column"),function(){ // перебираем все column    
   //arrObj.push( new trackman (this,1));   
   arrObj[i]=new trackman (this,1)                                
   i=i+1;            
});

kadabrik 31.08.2011 17:34

Я бы вообще использовал один релиационный набор, так как это проще, тем более дерево здесь по сути одно.

DjDiablo 01.09.2011 12:36

В общем то я так и поступил :)
Алгоритм в разы проще, и что удивительно скорости хватает во всех браузерах, даже если не кешировать заранее. Тем не менее от кеширования я конечно не отказался. Ограничился одним реляционным набором, но не потому что так проще, а потому что порядок следования обьектов в этом наборе соответствует вложенности.

ТОБИШ вибираю таким макаром
jQuery.each($(".column, .portlet"),function(){ // перебираем все column    
   arrObj.push (new trackman (this));                             
});


Часовой пояс GMT +3, время: 00:59.