Заменить XML ответом из XMLHttprequest
РЕДАКТИРОВАТЬ
Со всеми правками на мой вопрос он стал довольно длинным. Итак, позвольте мне попытаться немного укоротить его и сделать так, чтобы ему было легче следовать.
Я создаю XUL-приложение, используя XULRunner. Я загрузил фиктивную XUL-страницу, а потом ищу использовать XMLHttprequest
чтобы загрузить все с моего сервера (локальный сервер ampps), используя PHP, чтобы сделать всю реальную работу. Мой PHP устанавливает XML Content-Type
заголовок и форматирование всех выходных данных в формате XML.
Вот то, что функция JavaScript, которая обрабатывает XMLHttprequest
и ответ, в настоящее время выглядит так.
function RequestData()
{
if (window.XMLHttpRequest)
{
var url = 'newmenu.xml';
var request = new XMLHttpRequest();
}
else
{
var url = 'http://localdomain.prog/';
var request = Components.classes['@mozilla.org/xmlextras/xmlhttprequest;1'].createInstance(Components.interfaces.nsIXMLHttpRequest);
}
request.onload = function(aEvent)
{
var xmlDoc = aEvent.target.responseXML;
var oldmenu = document.getElementById('menubarwrapper');
oldmenu.parentNode.replaceChild(xmlDoc.documentElement, oldmenu);
};
request.onerror = function(aEvent)
{
window.alert("Error Status: " + aEvent.target.status);
};
request.open('POST', url, true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
request.send('pageid=menu');
}
RequestData()
вызывается с окном onload
событие.
Мой исходный код, похоже, ничего не делал, но когда я исследовал и протестировал, я в итоге заставил XULRunner выдавать некоторые ошибки в консоль ошибок. В конечном итоге это привело к тому, что, как я теперь предполагаю, были рабочие версии, но я просто не знал об этом.
Консоль ошибок выкладывала это сообщение (и до сих пор есть)
Предупреждение: блок XUL для элемента окна содержал встроенный дочерний элемент панели инструментов, заставляя все его дочерние элементы быть обернутыми в блок.
Чтобы выяснить, работает ли мой код, я должен был поместить его в Firefox. Отсюда и причина if (window.XMLHttpRequest)
, так как это позволяет мне тестировать как с Firefox, так и с XULRunner. Затем я взял XML, который генерировал мой PHP, и сделал локальный файл, так как Firefox не позволит XMLHttprequest
загрузить удаленный файл (даже если он технически локальный).
Приведенный выше код импортирует XML и заменяет <menubar id="menubarwrapper">...</menubar>
, Но и в Firefox, и в XULRunner меню исчезает. Я вижу все элементы, если использую Firebug, но почему они больше не видны, я не вижу, и в консоли Firebug нет ошибок. Это где я в настоящее время в тупике.
В случае его использования ниже приведена копия фиктивного XUL-файла, который я загружаю.
<?xml version="1.0"?>
<?xml-stylesheet href="main.css" type="text/css"?>
<window id="main" title="My App" width="1000" height="800" sizemode="maximized" orient="vertical" persist="screenX screenY width height" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript" src="main.js"/>
<toolbox id="toolboxwrapper">
<menubar id="menubarwrapper">
<menu id="file-menu" label="File" accesskey="F">
<menupopup id="file-popup">
<menuitem label="Refresh" funcname="RefreshWin"/>
<menuitem label="Open Window" funcname="OpenWin" acceltext="Ctrl+O" accesskey="O" />
<menuseparator/>
<menuitem label="Exit" funcname="ExitProg"/>
</menupopup>
</menu>
<menu id="edit-menu" label="Edit" accesskey="E">
<menupopup id="edit-popup">
<menuitem label="Undo"/>
<menuitem label="Redo"/>
</menupopup>
</menu>
</menubar>
</toolbox>
</window>
XML, который генерирует мой PHP, довольно длинный, но в основном это <menubar>
элемент со всеми его дочерними элементами, похожими на выше, но с гораздо большим <menu>
а также <menuitem>
элементы.
2 ответа
У меня все получилось, но код на 80 с лишним строк длиннее, чем должен быть. Я перепробовал каждый вариант importNode
, replaceChild
, appendChild
, adoptNode
, removeChild
и т. д. Я мог думать о. Я вполне уверен, что мог бы написать книгу о том, как вы можете обрабатывать любой данный элемент или узел XML.
Вот пример того, насколько нелепой была эта проблема. Это будет работать
function AddNewElem()
{
var menubar = document.getElementById('menubarwrapper');
var menuitem = '<menu id="help-menu" label="Help" accesskey="H" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">';
menuitem += '<menupopup id="help-popup">';
menuitem += '<menuitem id="test-menu" label="Test" acceltext="Ctrl+T" accesskey="T" />';
menuitem += '<menuseparator/>';
menuitem += '<menuitem id="about-menu" label="About" acceltext="Ctrl+A" accesskey="A" />';
menuitem += '</menupopup>';
menuitem += '</menu>';
var parser = new DOMParser();
var xmlDoc = parser.parseFromString(menuitem, 'text/xml').documentElement;
menubar.appendChild(xmlDoc);
}
но это не будет
function RequestData()
{
var url = 'newmenu.txt';
var request = new XMLHttpRequest();
request.onload = function(aEvent)
{
var menubar = document.getElementById('menubarwrapper');
var responsetxt = aEvent.target.responseText;
var parser = new DOMParser();
var xmlDoc = parser.parseFromString(responsetxt, 'text/xml').documentElement;
menubar.appendChild(xmlDoc);
};
request.onerror = function(aEvent)
{
alert("Error Status: " + aEvent.target.status);
};
request.open('POST', url, true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
request.send('pageid=menu');
}
newmenu.txt
это просто содержимое menuitem
в предыдущем фрагменте кода. Я даже пошел настолько далеко, чтобы сериализовать xmlDoc
вернуться к строке, а затем проанализировать ее снова и все равно не будет работать. Я испробовал кучу глупых идей, и многие из тех, кого я знал, не сработали, если бы не было шанса, что я мог бы получить представление о проблеме. Когда вы терпите крах Firefox, вы знаете, что слишком сильно толкнули.
Но я отвлекся. Поэтому ради других попыток использовать XHR с XULrunner ниже - это то, что я должен был сделать.
function RequestData()
{
var url = 'http://localdomain.prog/';
var request = Components.classes['@mozilla.org/xmlextras/xmlhttprequest;1'].createInstance(Components.interfaces.nsIXMLHttpRequest);
request.onload = function(aEvent)
{
var xmlDoc = aEvent.target.responseXML;
var toolbar = document.getElementById('toolboxwrapper');
var menubar = document.getElementById('menubarwrapper');
toolbar.removeChild(menubar);
var menubar = document.createElement('menubar');
menubar.setAttribute('id', 'menubarwrapper');
var docfrag = document.createDocumentFragment();
docfrag.appendChild(menubar);
var newmenus = xmlDoc.getElementsByTagName('menu');
var menuslen = newmenus.length;
for (var i = 0; i < menuslen; i++)
{
docfrag = CreateMenu(newmenus[i], docfrag);
}
toolbar.appendChild(docfrag);
};
request.onerror = function(aEvent)
{
window.alert("Error Status: " + aEvent.target.status);
};
request.open('POST', url, true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
request.send('pageid=menu');
}
function CreateMenu(obj, docfrag)
{
var fragbar = docfrag.getElementById('menubarwrapper');
var menu = document.createElement('menu');
menu = SetMenuAttr(obj, 'id', menu);
menu = SetMenuAttr(obj, 'label', menu);
menu = SetMenuAttr(obj, 'accesskey', menu);
var fragmenu = fragbar.appendChild(menu);
var popup = obj.getElementsByTagName('menupopup')[0];
var menupopup = document.createElement('menupopup');
menupopup = SetMenuAttr(popup, 'id', menupopup);
var fragpopup = fragmenu.appendChild(menupopup);
if (popup.hasChildNodes())
{
var childmenu = popup.childNodes;
var menulen = childmenu.length;
for (var i = 0; i < menulen; i++)
{
if (childmenu[i].nodeName == 'menuitem' || childmenu[i].nodeName == 'menu')
{
if (childmenu[i].nodeName == 'menuitem')
{
var menuitem = CreateMenuitem(childmenu[i]);
}
if (childmenu[i].nodeName == 'menu')
{
var menuitem = CreateMenu(childmenu[i]);
}
fragpopup.appendChild(menuitem);
}
}
}
return docfrag;
}
function CreateMenuitem(obj)
{
var menuitem = document.createElement('menuitem');
menuitem = SetMenuAttr(obj, 'id', menuitem);
menuitem = SetMenuAttr(obj, 'label', menuitem);
menuitem = SetMenuAttr(obj, 'accesskey', menuitem);
menuitem = SetMenuAttr(obj, 'acceltext', menuitem);
menuitem = SetMenuAttr(obj, 'disabled', menuitem);
return menuitem;
}
function SetMenuAttr(obj, attr, newobj)
{
if (obj.hasAttribute(attr))
{
newobj.setAttribute(attr, obj.getAttribute(attr));
}
return newobj;
}
В основном приходилось извлекать каждый элемент и его атрибуты и создавать новые элементы. Безусловно его не предпочтительное решение. Для меня, если мне нужно написать на одну строку кода больше, чем это абсолютно необходимо, это неправильно. Решение должно было быть 2 строки.
Без дополнительной информации это только предположение о том, в чем проблема.
Может случиться так, что данные XML, которые извлекаются из вашего XMLHttpRequest()
интерпретируется как XML/HTML, а не XUL. Это может привести к поведению, которое вы описываете. Вы можете проверить это с помощью DOM Inspector, чтобы просмотреть элементы, которые были вставлены в вашу строку:
oldmenu.parentNode.replaceChild(xmlDoc.documentElement, oldmenu);
То, что вы должны искать, это то, что Namespace URI
показывает для этих элементов. Если это не так http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul
тогда элементы не рассматриваются как XUL.
Одним из способов решения этой проблемы было бы сделать:
oldmenu.insertAdjacentHTML("afterend", aEvent.target.responseText);
oldmenu.setAttribute("hidden","true");
//Alternately (if you don't want to keep the placeholder <menubar>):
//oldmenu.parentNode.removeChild(oldmenu);