Когда выполняются обновления DOM, дочерние элементы добавляются в javascript

#javascript #dom

#javascript #dom

Вопрос:

В javascript я создаю divs, которые размещаются на странице. Я получаю верхнюю левую ширину высоты для последнего добавленного элемента, чтобы разместить новый. Информация сохраняется в XML-файл для размещения divs при перезагрузке страницы. Когда я извлекаю размещение для последнего div, я получаю информацию для div, размещенную из xml info. Другими словами, divs, созданные в javascript, похоже, еще не находятся в DOM. Есть ли функция, которую я должен вызвать, чтобы обновить DOM?

Вот код, в котором я извлекаю информацию для последнего div на странице.

     var last_top = $('.linkcard:last', $("#page")).position().top;
    var last_left = $('.linkcard:last', $("#page")).position().left;
    var last_height = $('.linkcard:last', $("#page")).height();
    var last_width = $('.linkcard:last', $("#page")).width();
  

Этот код вызывается в событии onClick кнопки. В первый раз он работает и извлекает информацию для статических divs (те, которые извлекаются из xml). В последующие разы он не извлекает правильную информацию, потому что, похоже, он не знает о div, добавленном в javascript. Я полагаю, что написанный код просматривает часть DOM, которая не знает о новом div. Это правильно? Что я должен сделать, чтобы получить правильную информацию?

Редактировать

* Полная функция javascript *

 function create_linkcard() {

    // Create LinkCard id
    var created_id_string = $.ajax({
        url: "create_id.php",
        type: "GET",
        data: { },
        cache: false,
        async: false,
        success: function (response) {
            if (response != '') 
            {
               /* alert(response); */
            }
        }
    }).responseText;

    var card_id = "c"   String(created_id_string);

    // Create Linkcard, add toolbar, resize #page
    $("#page").append('<div id="' card_id '" class="linkcard_init ui-widget-content" style="z-index: 9999;"></div>');
    $('#' card_id).append('<p class="linkcard_header editableText">C' created_id_string '</p>');

    // Make edit box for LinkCard title
    $('#' card_id).append('<form id="frm_name" name="frm_name" class="editableToolbar frm_add_linkcard"> <input type="text" placeholder="Type a name..." name="linkcard_name" class="txt_form"> <a href="#" title="Save" class="save btn_form" onClick="save_name('' card_id '', this.form); "></a> <a href="#" title="Cancel" class="cancel btn_form" onClick="delete_linkcard(' ''' card_id ''' ');"></a> </form>');

    // Add toolbar
    $('#' card_id).append('<div class="toolbar"> <a href="#" title="Options" class="ico_tools"></a> <a href="#" title="Delete" class="ico_delete" onClick="delete_linkcard(' ''' card_id ''' ');"></a> </div>');

    // Add drag and drop box
    $('#' card_id).append('<div class="link_drop_box"></div>');

    // Add scrolling buttons
    $('#' card_id).append('<div class="scrolling_prev" title="Previous"></div>');
    $('#' card_id).append('<div class="scrolling_next" title="Next"></div>');

    // Add search tool and add link tool
    $('#' card_id).append('<div class="tools" > <a href="#" title="Add Link" class="ico_add" onClick="add_link(' ''' card_id ''' ');"></a> <a href="#" title="Search Links" class="ico_search" onClick="open_search(' ''' card_id ''' ');"></a> </div>');

    // Add script for scrolling
    $(document).ready(function($) {
        $(".scrolling_prev", $('#' card_id)).mousedown(function() {
                        startScrolling($(".link_drop_box", $('#' card_id)), "-=50px");
                    }).mouseup(function() {
                        $(".link_drop_box", $('#' card_id)).stop()
                    });
        $(".scrolling_next", $('#' card_id)).mousedown(function() {
                        startScrolling($(".link_drop_box", $('#' card_id)), " =50px");
                    }).mouseup(function() {
                        $(".link_drop_box", $('#' card_id)).stop();
                    });
    }); 

    // Place new LinkCard
    /* var last_top = parseInt($('.linkcard:last', $("#page")).position().top);
    var last_left = parseInt($('.linkcard:last', $("#page")).position().left);
    var last_otop = parseInt($('.linkcard:last', $("#page")).offset().top);
    var last_oleft = parseInt($('.linkcard:last', $("#page")).offset().left);
    var last_height = parseInt($('.linkcard:last', $("#page")).height());
    var last_width = parseInt($('.linkcard:last', $("#page")).width()); */
    var last_top = parseInt($("#page").children('.linkcard:last').position().top);
    var last_left = parseInt($("#page").children('.linkcard:last').position().left);
    var last_otop = parseInt($("#page").children('.linkcard:last').offset().top);
    var last_oleft = parseInt($("#page").children('.linkcard:last').offset().left);
    var last_height = parseInt($("#page").children('.linkcard:last').height());
    var last_width = parseInt($("#page").children('.linkcard:last').width());
    alert ('top ' last_top ' left ' last_left ' offset top ' last_otop ' offset left ' last_oleft);
    var new_top = 0;
    var new_left = 0;
    /* if (last_left < 250) {
       new_top = last_top - last_height - last_height;
       new_left = last_left   last_width   20;
    }
    else  {
       new_top = last_top - last_height   20;
       new_left = 0;
    }*/
    if (last_left < 250) {
       new_top = last_top - last_height - last_height;
       new_left = last_left   last_width   20;
    }
    else  {
       new_top = last_top - last_height   20;
       new_left = 0;
    }

    // Define more LinkCard options
    $('#' card_id).css('width',350);
    $('#' card_id).css('height',250);
    $('#' card_id).css('top',new_top);
    $('#' card_id).css('left',new_left);
    $('#' card_id).resizable();
    $('#' card_id).draggable();
    $('#' card_id).draggable("option", "handle", '.linkcard_header');
    $('#' card_id ' p').editableText();
    $('#' card_id).draggable({ stop: function(event, ui) { update_linkcard_xml(card_id) } });

    // Make droppable
    $('div.link_drop_box', $('#' card_id)).droppable({
        drop: function( event, ui ) {
            var $item = ui.draggable;
            $item.fadeOut(function() {
                $item.css( {"left":"", "top":"", "bottom":"", "right":"" }).fadeIn();
            }); 
            $item.appendTo( this );
            /* update_links_xml("card_id"); */
       },
        out: function( event, ui ) {
            /* update_links_xml("card_id"); */ 
        },
        accept: ".link",
    });

    // Get LinkCard info for XML
    linkcard_name = $('#' card_id).children('.linkcard_header').text();
    linkcard_top = $('#' card_id).position().top;
    linkcard_left = $('#' card_id).position().left;
    linkcard_width = $('#' card_id).width();
    linkcard_height = $('#' card_id).height();

    // Scroll LinkCard into view
    linkcard_offset = $('#' card_id).offset().top 40;
    var scroll_top = parseInt(linkcard_top);
    alert (linkcard_offset);
    $('#matting').scrollTop(linkcard_offset);

    // Make ajax call to update XML
    $.ajax({
        url: "add_node.php",
        type: "POST",
        data: { nodeid: card_id, name: linkcard_name, top: linkcard_top, left: linkcard_left, width: linkcard_width, height: linkcard_height },
        cache: false,
        success: function (response) {

            if (response != '') 
            {
                /* alert(response); */

            }
        }
    });

}
  

Комментарии:

1. Когда вы запускаете этот код? Это должно быть в document.ready, чтобы убедиться, что DOM правильно загружен.

2. @bfavaretto Я запускаю этот код, нажав кнопку «создать div». Страница загружается в то время. Есть ли функция, которую я должен вызвать, чтобы убедиться, что DOM загружен?

3. Не могли бы вы добавить больше кода, чтобы прояснить сценарий? Например, код, который создает и добавляет <div> s с классом ‘linkcard’ на страницу.

4. @bfavaretto Я добавил полный javascript к вопросу.

Ответ №1:

DOM обновляется после каждого вашего вызова .append() . Я все еще не уверен, полностью ли я понимаю, чего вы пытаетесь достичь, но вот что я заметил в вашем коде:

  • Когда вы присваиваете last_* переменным, вы получаете информацию из последнего <div> класса with linkcard . Однако новые divs, созданные с create_linkcard() помощью, не имеют linkcard класса. Вместо этого у них есть класс linkcard_init . Таким образом, ваш следующий вызов create_linkcard() никогда не найдет новый div, потому что у него нет класса, на который вы ориентируетесь.

  • Если вы просто измените имя класса linkcard_init на linkcard , ваш код завершится ошибкой, потому что ваша логика сначала добавляет новый div и только после этого ищет last_* значения. Таким образом, последним значениям будут присвоены верхние, левые, ширина и высота нового div, который вы только что вставили, вместо предыдущего.

  • Я заметил, что ваш код начинается с синхронного вызова сервера. Это, вероятно, на некоторое время заморозит пользовательский интерфейс. Разве это не проблема?

Комментарии:

1. Большое спасибо! Вы правы! Я экспериментировал с css для новой linkcard и css для существующих linkcards. Это определенно объясняет, почему .linkcard: последний не смог найти новые карты. Я рассмотрю возможность сохранения одного класса для всего или поиска группировки, которая объединяет .linkcard и .linkcard_init. Должен быть способ заставить это работать. Что касается синхронного вызова, я знаю, что он не идеален. Но мне нужен ответ от этого вызова для создания карты. Это работает нормально. Вызываемый код довольно прост и быстр.