динамическое создание элементов
При нажатии на ссылку рядом с ней должно появляться поле ввода, которое создается с помощью js. Возник вопрос: как желательнее делать - 1-ым методом (через DOM), или вторым (через innerHTML)? И что будет быстрее работать?
1-ый метод: var Elem = { setAttrs : function(elem, attrs){ for(var a in attrs){ elem.setAttribute(a, attrs[a]); } }, newElem : function(elem, attrs){ var el = document.createElement(elem); Elem.setAttrs(el, attrs); return el; }, newTxt : function(elem, txt){ elem.appendChild(document.createTextNode(txt)); } } var prompt = Elem.newElem('table', {class:'std_form', id:'quickreply'}); prompt.innerHTML = "<tr><td></td><td></td></tr> <tr><td></td><td></td></tr> <tr><td></td><td></td></tr> <tr><td colspan=\"2\"></td></tr> <tr><td></td><td></td></tr> <tr><td></td><td></td></tr>"; var name = Elem.newElem('input',{type : 'text', name : 'name', id : 'name', size:'30', value : "asdasd"}); var subj = Elem.newElem('input', {type : 'text', name : 'subject', id : 'subj', size:'30', value : "фывыфв"); var txtarea = Elem.newElem('textarea', {wrap : 'virtual', name : 'message', id : 'quickreplytxt', cols:'60', rows:'10'}); var submit = Elem.newElem('input', {type : 'submit', value: 'Отправить'}); Elem.newTxt(prompt.cells[0], "Имя: "); Elem.newTxt(prompt.cells[4], "Тема комментария: "); prompt.getElementsByTagName('td')[1].appendChild(name); prompt.getElementsByTagName('td')[5].appendChild(subj); prompt.getElementsByTagName('td')[6].appendChild(txtarea); prompt.getElementsByTagName('td')[10].appendChild(submit); elem.appendChild(prompt); txtarea.focus(); 2-ой метод: var prompt = document.createElement('table'); prompt.innerHTML = "<tr><td>Имя:</td><td><input type=\"text\" name=\"name\" id=\"name\" /></td></tr><tr><td>Тема: </td><td><input type=\"text\" name=\"subject\" id=\"subj\" /></td></tr><tr><td><textarea wrap=\"virtual\" name=\"message\" id=\"quickreplytxt\" cols=\"60\" rows=\"10\"></textarea></td></tr><tr><td></td><td><input type=\"submit\" value=\"Отправить\" /></td></tr>"; |
А потестить не судьба?
|
2-ой метод, только не надо столько экранирования, можно использовать одинарные кавычки, а внутри двойные или наоборот. И не надо все в одну строку писать
а по поводу производительности: доделываешь страничку, а _потом_ начинаешь искать _узкие места_ |
Прервый метод (DOM) - это программирование. Второй (HTML) - это "разметка текста". Лично я склоняюсь к программированию!
При небольших количествах элементов на странице оба способа практически эквивалентны. Причем способ с innerHTML иногда выглядит читабельнее; и его можно быстрее написать. Однако, на больших количествах элементов появляется разница. Можете попробовать нарисовать таблицу 100 строк х 100 столбцов. По моим оценкам var o=getElementById (с которым прийдется работать при innerHTML ) работает заметно медленнее, чем прямое указание javascript объекта var o=someobject var someobject = document.createElement('div'); Особенно торможение заметно в IE. Хотя теоретически по скорости должны работать одинаково. Поэтому лучше DOM. Но... существует ряд проблем, которые без innerHTML не решишь. Например, Вы хотите создать форму с элементом "input" типа "file": var f=document.createElement('form'); f.method='POST'; f.action='lalala.php'; f.enctype='multipart/form-data'; ... ... Это работать не будет в IE. У него глюк с enctype. Как быть? - Только вот так: o.innerHTML='<form enctype="multipart/form-data"></form>'; ... ... |
Маэстро,
а так ? )) var f = document.createElement("form"); f.method = "POST"; f.action = "lalala.php"; f.setAttribute("enctype", "multipart/form-data"); f.setAttribute("encoding", "multipart/form-data"); var i = document.createElement("input"); i.setAttribute("type", "file"); f.appendChild(i); document.body.appendChild(f); |
Цитата:
во-вторых, почему прийдется работать с getElementById и о каком прямом указании javascript-объекта идет речь? Здесь, кстати, с getElementById работать не пришлось Цитата:
In practice there is. Yogi Berra ;) |
Цитата:
Цитата:
|
Цитата:
Только недолюбливаю я setAttribute()... или он меня недолюбливает...? ;) |
Цитата:
Любите друг друга. |
Цитата:
Цитата:
Цитата:
Пользователь прописывает формулу, в которой указывает, что типа возьми значение из ячейки талицы строки №5, столбца №30 и прибавь к ячейке 10/40. Как бы решить такую задачку? Очевидно что каждую ячейку надо снабдить своим id, каждый из которых будет вида "cell_xxx_yyy", где xxx-номер строки, а yyy-номер столбца. Дальше искать эти ячейки методом getElementById('cell_5_30') и getElementById('cell_10_40') Это при создании таблицы с помощью HTML. Если же всю таблицу создавать "на лету" с помощью javascript, то id ячейкам можно не задавать, т.к. мы имеем ПРЯМЫЕ УКАЗАТЕЛИ на ячейки таблицы: o_1_1= document.createElement("div"); o_1_2= document.createElement("div"); o_1_3= document.createElement("div"); ... и по ним можем сразу обращаться к содержимому ячеек. |
Цитата:
Цитата:
По-моему, написание функций создания (DOM) объектов и управления ими - это программирование. Что есть по-Вашему программирование? Написание функций сложения 2+3? |
Цитата:
И вообще, доказывать общий случай ну очень частным как-то неправильно. |
Цитата:
|
Цитата:
а также t.insertRow() ... r.insertCell()... Пример с таблицей я привёл очень упрощённый. В задаче, с которой приходилось сталкиваться мне, объекты находились не в строго структурированной таблице, к которой можно было бы обратиться по номеру строки и столбца. Точнее, они могли представлять сразу группы объектов, которые в свою очередь содержали другие группы... |
Цитата:
|
// создание wincontainer выше wincontainer.innerHTML='<div class="videowin" onmousedown="return GigDrag(event,this,'+wh+');"</div>'; // вся соль - в строке return... ;) winobj=wincontainer.firstChild; wincontainer.removeChild(winobj); G.videowin=winobj; if (bg0) // фон 0 { obj=d.createElement('div'); obj.className='vw0'; winobj.appendChild(obj); G['videowinbg0']=obj; } if (bg1) { obj=d.createElement('div'); obj.className='vw1'; winobj.appendChild(obj); G.videowinver=obj; } if (bg2) { obj=d.createElement('div'); obj.className='vw2'; winobj.appendChild(obj); G.videowinhor=obj; } obj=d.createElement('div'); // Tttle Window obj.className='vw4'; obj.innerHTML=title; if (title != '') obj.style.display='block'; winobj.appendChild(obj); G.videowintitle=obj; obj=d.createElement('div'); // внутренняя часть окна obj.className='vw5'; winobj.appendChild(obj); G.videowininside=obj; obj=d.createElement('div'); // кнопка закрытия окна (vw6 for IE!) obj.className='vw6'; objclose=d.createElement('img'); objclose.className='vw7'; objclose.onclick=function() {closevideowin(wh);} objclose.align='right'; objclose.src = 'close7.jpg'; if (IE) objclose.style.marginRight=4; obj.appendChild(objclose); if (Fclose) obj.style.display='block'; winobj.appendChild(obj); G.videowinclose=obj; obj=d.createElement('img'); // картинка "loading" obj.className='vw8'; obj.src = 'loading42.gif'; obj.id='videowinloading'+wh; if (Floading) obj.style.display='block'; winobj.appendChild(obj); G.videowinloading=obj; G.NoMoveIn = []; G.videowin = winobj; d.body.appendChild(winobj); Для поддержки вёрстки нужно понимать её структуру. Грубо говоря, понимать, какой html-код строит картинку на экране. Кто по данному коду может восстановить html-код? |
Цитата:
Например, вот так: var s='<b>Шаг 1.</b> Выберите картинку из предложенного списка'; m.s1 = settextbgpanelunit(0,v,360,h, 'mcellbg','mtext', 10,5, s); m.s1.container.onclick = step1; p.appendChild(m.s1.container); s='<b>Шаг 2.</b> Введите поздравительный текст'; m.s2 = settextbgpanelunit(0,v*2,360,h, 'mcellbg','mtext', 10,5, s); m.s2.container.onclick = step2; p.appendChild(m.s2.container); s='<b>Шаг 3.</b> или выберите текст из предложенного списка'; m.s3 = settextbgpanelunit(0,v*3,360,h, 'mcellbg','mtext', 10,5, s); m.s3.container.onclick = step3; p.appendChild(m.s3.container); s='<b>Шаг 4.</b> Определите шрифт текста, размер и цвет'; m.s4 = settextbgpanelunit(0,v*4,360,h, 'mcellbg','mtext', 10,5, s); m.s4.container.onclick = step4; p.appendChild(m.s4.container); s='<b>Шаг 5.</b> Выберите музыкальное сопровождение'; m.s5 = settextbgpanelunit(0,v*5,360,h, 'mcellbg','mtext', 10,5, s); m.s5.container.onclick = step5; p.appendChild(m.s5.container); s='<b>Шаг 6.</b> Добавьте прикольный смайлик к открытке'; m.s6 = settextbgpanelunit(0,v*6,360,h, 'mcellbg','mtext', 10,5, s); m.s6.container.onclick = step6; p.appendChild(m.s6.container); s='<b>Шаг 7.</b> Введите адрес получателя открытки'; m.s7 = settextbgpanelunit(0,v*7,360,h, 'mcellbg','mtext', 10,5, s); m.s7.container.onclick = step7; p.appendChild(m.s7.container); 2. Если оочень грубо говоря, ;) то "Кто по данному коду может восстановить html-код" - пусть это Вас не беспокоит. Для этого есть люди. Да и зачем его восстанавливать? |
Цитата:
Вы не привели примера создания элементов. Цитата:
Цитата:
Цитата:
|
Цитата:
Цитата:
Цитата:
|
Цитата:
Но в некотором будущем, возможно, частично это будет выставлено на всеобщее пользование и будет представлять что-то вроде web-excell-таблиц. Надеюсь, что реализовывать будете бесплатно :) Хотя, думаю, что Google, или Мicrosoft сделают это быстрее... |
Цитата:
|
Цитата:
Понимаете, у меня как бы в принципе нет HTML-вёрстки в привычном понимании этого слова при разработке сайта. Все объекты хранятся в базе. Предположим их два типа: автомобили и контейнеры (морские). Каждый объект обладает набором свойств. Часть свойств одинакова (например, координаты и название), а часть свойств разные. Причём те свойства, которые разные - это не свойства DOM-объектов, а бизнес-свойства. Например, у машины есть марка и кубометраж. У контейнера есть тоннаж и условия инкотермс (FOB, CIF, DDP,...) которых нет у автомобиля. Все бизнес-свойства должны в конечном итоге отображаться на экране в виде картинок, текстов, таблиц, полей ввода.... То есть, каждый объект на экране - это комплект из table, div, img и т.д. Свойства объектов не верстаются (как на типичных сайтах), а добавляются самими пользователями, для чего имеется набор "стандартных" заготовок. Как это реализовать? Вариант первый: формировать весь html-текст на сервере (например, PHP) и отправлять клиенту. Объем получится не менее 1 Мегабайта. Все объекты прийдётся снабдить уникальными id, для дальнейшего оперирования ими. Вариант второй: Формировать DOM-объекты всего этого пространства с помощью javascript на клиенте; клиенту отправлять только массив чисто данных (любым транспортным механизмом). В заключение добавлю, что все объекты отображаются на некой "карте местности", размер которой 30000х30000 пикселей. И не думайте, что я ошибся в ноликах ;) |
ну так это же совсем другой случай, в отличие от указанного в первом сообщении топика. Есть три вида компонентов: карта, автомобили, контейнеры. У каждого минимум разметки, судя по описанию, т.е. по сути каждый из них - это один абсолютно-спозиционированный div. Причем карта просто содержит коллекцию автомобилей/контейнеров, т.е. нету никакого сложного шаблона, по которому автомобили/контейнеры включаются в карту. Создавать разметку каждого компонента проще создавать с помощью createElement, потому что каждый элемент - это один div
в общем, чем сложнее шаблон, тем лучше подходит innerHTML p.s. мы собирались сравнивать innerHTML vs createElement/appendChild... |
Цитата:
Цитата:
подчеркну только, что что каждый элемент - это не один div, а один div, содержащий в себе ещё кучу div_ов и других элементов. а главное, я утверждал, что при использовании innerHTML приходится снабжать элементы идентификаторами, а потом обращаться к ним с помощью GetElementByID(). и при их большом количестве начинается торможение |
Цитата:
Цитата:
Цитата:
|
по вашему опсанию получается где-то так
var Map = new Class({ initialize: function(){ this._objs = []; this._el = new Element('div'); }, addObject: function( o ){ this._objs.push( o ) o.inject(this._el); } }); var Car = new Class({ initialize: function(){ this._el = new Element('div'); } }); var map = new Map(); var car = new Car(); map.addObject(car); если же там не просто div, то this._el = new Element('div') превращается в что-то типа this._el = template( '<table>'+ '<tr><td>Имя:</td>'+ '<td><input type="text" name="name" id="name" /></td>'+ '</tr>'+ '<tr><td>Тема: </td>'+ '<td><input type="text" name="subject" id="subj" /></td>'+ '</tr>'+ '<tr><td><textarea wrap="virtual" name="message" id="quickreplytxt" cols="60" rows="10"></textarea></td></tr>'+ '<tr><td></td>'+ '<td><input type="submit" value="Отправить" /></td>'+ '</tr>'+ '</table>'); |
Цитата:
(id="name", name="subject", id="quickreplytxt") Зачем id? -затем, чтобы взять значение переменной, или прописать его туда. теперь насчёт "this._el = ..." Когда вся эта "Карта полётов" уже создана (а так её называет Заказчик), то все ссылки "this" уже забыты. И вот наступает момент, когда поступает информация, что груз номер 5 едет в автомобилях 7,8 и 15 (к примеру). Как обратиться к элементам 7,8 и 15? Очевидно, что либо снабдить их id_шками типа id=object_7, id=object_8, id=object_15. Либо, ещё при создании запомнить все созданные this._el в отдельном массиве например, map[...] (можно в объекте map{} ) и тогда при поиске элементов делать не o=document.getElementById('object_7') a o=map[7]; - вот это я и называл прямым доступом к объектам. |
Цитата:
Цитата:
|
продолжая пример (если нужно обращаться к textarea)
var Car = new Class({ initialize: function(){ this._el = template( '<table>'+ '<tr><td>Имя:</td>'+ '<td><input type="text" name="name" id="name" /></td>'+ '</tr>'+ '<tr><td>Тема: </td>'+ '<td><input type="text" name="subject" id="subj" /></td>'+ '</tr>'+ '<tr><td><textarea wrap="virtual" name="message" id="quickreplytxt" cols="60" rows="10"></textarea></td></tr>'+ '<tr><td></td>'+ '<td><input type="submit" value="Отправить" /></td>'+ '</tr>'+ '</table>'); }, _textarea: function(){ if( ! this._textareaEl ) this._textareaEl = this._el.getElement('textarea'); return this._textareaEl; } }); |
Часовой пояс GMT +3, время: 20:55. |