2009-10-29 3 views
15
var oFra = document.createDocumentFragment(); 
// oFra.[add elements]; 
document.createElement("div").id="myId"; 
oFra.getElementById("myId"); //not in FF 

Как я могу получить «myId» перед прикреплением фрагмента к документу?Есть ли способ найти элемент в документеFragment?

+3

Этот вопрос задан в 2009 году. __В 2012 году у нас есть querySelectorAll, который работает с фрагментами документов. См. Ответ @ Стивена ниже. – mikemaccana

ответ

0

насчет:

var oFra = document.createDocumentFragment(); 
var myDiv = document.createElement("div"); 
myDiv.id="myId"; 
oFra.appendChild(myDiv); 
oFra.getElementById("myId"); //not in FF 

Если вы не добавили созданный div к вашему фрагмент документа я не знаю, почему getElementById бы это?

--edit

Если вы готовы свернуть свою собственную функцию getElementById, то вы должны быть в состоянии получить ссылку вы после этого, потому что этот код работает:

var oFra = document.createDocumentFragment(); 
var myDiv = document.createElement("div"); 
myDiv.id = "myId"; 
oFra.appendChild(myDiv); 
if (oFra.hasChildNodes()) { 
    var i=0; 
    var myEl; 
    var children = oFra.childNodes; 
    for (var i = 0; i < children.length; i++) { 
     if (children[i].id == "myId") { 
      myEl = children[i]; 
     } 
    } 
} 
window.alert(myEl.id); 
+0

Я пытался избежать этого решения, так как я проектирую форму данных в фрагменте, добавляю события и прикрепляю к документу. Работает в IE. Причина в том, что в фрагменте IE наследуется от документа, но в FF наследуется от Node (W3C) – pkario

+0

ОК, но если вы все равно создаете форму в JS, почему бы просто не хранить ссылки на элементы при их создании и использовать эти ссылки для добавления событий? – robertc

+0

В каждой форме есть много кнопок, текстовых полей, комбо и т. Д. Я стараюсь придерживаться идентификаторов и минимизировать ссылки на объект dom, где это возможно. Прилагаю сначала и назначаю события позже. – pkario

7

Нет . DocumentFragment API минимально: он не определяет никаких свойств или методов, что означает, что он поддерживает только свойства и методы, определенные в Node API. Поскольку такие методы, как getElementById, определены в Document API, они не могут использоваться с DocumentFragment.

+0

Несмотря на то, что getElementById определен в API документа, он не будет работать на вновь созданном элементе, который не привязан к dom. myObj.getElementById не работает, тогда как myObj.getElementsByTagName работает. – Olivvv

+2

@Olivvv: это следует ожидать: 'getElementById' - это метод' HTMLDocument' http://www.w3.org/TR/REC-DOM-Level-1/level-one-html.html#ID-36113835 , тогда как 'getElementsByTagName' является методом как« Document »http://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#i-Document, так и' Element' http: //www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#ID-745549614 Следовательно, 'getElementById' всегда будет генерировать исключение, когда делается попытка вызвать его на объект типа 'Element', прикреплен ли этот элемент к DOM или нет. – NickFitz

0

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

var textblock=document.createElement("p") 
textblock.setAttribute("id", "george") 
textblock.setAttribute("align", "center") 

который отображает другой способ установки параметра ID объекта.

Javascript Kit - Document Object Methods

7

NickFitz прав, DocumentFragment не имеет API вы ожидаете от Document или Element, в стандарте или в браузерах (что это позор, это было бы очень удобно иметь возможность установить fragment innerHTML.

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

function Node_getElementById(node, id) { 
     for (var i= 0; i<node.childNodes.length; i++) { 
      var child= node.childNodes[i]; 
      if (child.nodeType!==1) // ELEMENT_NODE 
       continue; 
      if (child.id===id) 
       return child; 
      child= Node_getElementById(child, id); 
      if (child!==null) 
       return child; 
     } 
     return null; 
} 

Было бы почти наверняка лучше отслеживать ссылки, когда вы идете вперед, чем полагаться на наивную, плохо выполняющую функцию, такую ​​как выше.

var frag= document.createDocumentFragment(); 
var mydiv= document.createElement("div"); 
mydiv.id= 'myId'; 
frag.appendChild(mydiv); 
// keep reference to mydiv 
24

Все эти ответы довольно старые, со спины, когда querySelectorAll и querySelector не были широко доступны. Следует отметить, что эти две функции, которые принимают селекторы CSS как параметры, работают на DocumentFragment s в современных браузерах и должны быть предпочтительным способом решения ситуации в вопросе. Альтернативные решения, представленные в некоторых ответах, будут хорошим подходом для устаревших браузеров, которые не поддерживают querySelectorAll или querySelector.

Ниже приведен пример использования:

var df = document.createDocumentFragment(); 
var div = document.createElement('div'); 
div.id = 'foo'; 
df.appendChild(div); 
var result = df.querySelector('#foo'); // result contains the div element 

Хорошая реализация должна сначала использовать обнаружение объекта, чтобы увидеть, если браузер поддерживает это.Например:

function getElementByIdInFragment(fragment, id) { 
    if (fragment.querySelector) { 
     return fragment.querySelector('#' + id); 
    } else { 
     // your custom implementation here 
    } 
} 
+0

Я уверен, что есть другой способ, чем вернуть элемент из documentfragment. В любом случае ** вы потеряете все преимущества **. –

1

Использование JQuery:

// Create DocumentFragment 
var fragment = document.createDocumentFragment(), 
    container = document.createElement('div'); 

container.textContent = 'A div full of text!'; 
container.setAttribute('id', 'my-div-1'); 
container.setAttribute('class', 'a-div-class'); 
fragment.appendChild(container); 

// Query container's class when given ID 
var div = $('<div></div>').html(fragment); 
console.log(div.find('#my-div-1').attr('class')); 

jsFiddle: http://jsfiddle.net/CCkFs/

У вас есть накладные расходы на создание DIV с JQuery, хотя. Немного взломанный, но он работает.

+0

$ ("

") .find (# my-div-1 "). Вы просто не можете найти корневой узел. – Scott

0

My DOM имеет # document-фрагмент под тегом элемента.

Это то, что я использую (с помощью JQuery), Также у меня есть случай, когда использование я имею HTML DOM в строке -

var texttemplate = $(filecontents).find('template').html(); 


$(texttemplate).children() 

     <p>​Super produced One​</p>​, 
     <appler-one>​</appler-one>, 
     <p>​Super produced Two​</p>, 
     <appler-two>​…​</appler-two>] 

$(texttemplate).html() 

       "<p>Super produced One</p> 
       <appler-one></appler-one> 
       <p>Super produced Two</p> 
       <appler-two> 
        <p>Super produced Three</p> 
        <appler-three></appler-three> 
       </appler-two>" 


$(texttemplate).find("appler-one") 

       [<appler-one>​</appler-one>​] 
0

Самый лучший способ на сегодняшний день, чтобы выяснить, что вы можете и не может сделать с DocumentFragment, чтобы изучить его прототип:

const newFrag = document.createDocumentFragment(); 
const protNewFrag = Object.getPrototypeOf(newFrag); 
console.log('£ protNewFrag:'); 
console.log(protNewFrag); 

Я получаю

DocumentFragmentPrototype {getElementById: getElementById(), querySelector: querySelector(), querySelectorAll: querySelectorAll(), перед именем: перед именем(), добавьте: добавление(), дети: Getter, firstElementChild: Getter, lastElementChild: Getter, childElementCount: Getter, более 1 ...}

... который говорит мне, что я могу сделать что-то вроде:

const firstChild = newFrag.children[ 0 ]; 

PS это не будет работать:

const firstChild = Object.getPrototypeOf(newFrag).children[ 0 ]; 

... вам скажут, что «объект не реализует интерфейс DocumentFragment»

Смежные вопросы