iterar a través de elementos de forma anidada en jQuery
Pregunta
Lo siento, si esto ya se ha publicado, he estado buscando en vano ...
Solo quiero saber cómo recorrer en bucle los 'elementos' de forma anidada (los elementos no son solo los elementos de forma estricta, como las etiquetas de entrada, sino también otros elementos html) en jQuery. Actualmente tengo este pedazo de código para hacerlo:
$('#'+arguments[i].formid).children().each(function(){
var child = $(this);
alert(child.attr('id'));
if(child.is(":input")) { alert(child.attr('id'));
if(child.attr('id')!='') eval("p."+child.attr('id')+"='"+child.attr('value')+"'");
}
if(child.is(":textarea")) {
if(child.attr('id')!='') eval("p."+child.attr('id')+"='"+child.attr('value')+"'");
}
});
no funciona cuando mi formulario contiene otros elementos como este:
<form>
<div id='tabs'>
<ul>...</ul>
<div id='tab-1'>
<input type='text' id='fname' />
<textarea id='desc' ></textarea>
</div>
</div>
</form>
por favor ayuda ...
Solución
Puedes hacerlo en una función recursiva.
function doStuff(child) {
if(child.is(":input")) {
...
}
if(child.is(":textarea")) {
...
}
}
function walk(children) {
if (typeof children == "undefined" || children.size() === 0) {
return;
}
children.each(function(){
var child = $(this);
if (child.children().size() > 0) {
walk(child.children());
}
doStuff(child);
}
}
walk($('#'+arguments[i].formid).children());
EDIT : me acabo de dar cuenta de lo que estás tratando de hacer y puedes dividirlo en esto
var p = {};
$('#'+arguments[i].formid + " input[id], #"+arguments[i].formid + " textarea[id]").each(function(){
var child = $(this);
p[child.attr("id")] = child.attr("value");
});
Probablemente debería leer más sobre jQuery selectores .
Otros consejos
Puede usar contents () (y filtrar los nodos de texto si es necesario) o find ('*') para obtener todos los elementos, aunque no me gusta el uso de comodines.
$('form').contents()
.filter( function() { return this.nodeType == 1; } )
.each(...);
o
$('form').find('*')
.each(...);
Volví a corregirme :) jQuery Rocks! Así que después de un curso intensivo aquí es lo mismo en jQuery ...
/*
menu.jq : main menu jQuery for ekerner.com
Author : 'Eugene Kerner' <ekerner@ekerner.com>
Date : 16-12-2009
Dependencies: jQuery javascript lib
: menu.css
: an unordered list structure as per the below Example.
: a javascript call to menu.init(menuId, selectedMenuItemsArray) as per the below Example.
Notes : if your menu link has an onclick that returns false then it needs to call menu.init before returning (see Example).
Example : -
<ul id="mainMenu" class="menuItems">
<li>
<a href="/">Menu Item</a>
<ul>
<li><a href="/webpage" onclick="window.open('/webpage'); menu.init('mainMenu', ['Menu Item', 'Sub Menu Item']); return false;">Sub Menu Item</a></li>
</ul>
</li>
</ul>
<script type="text/javascript">$(document).ready(function(){menu.init('mainMenu', ['Menu Item'])});</script>
*/
var menu = {
selectedClass : 'selected',
animateSpeed : 'fast',
selectedLinks : [],
init : function(menuId, selectedLinks)
{
$('#' + menuId).children('li').each(function(){
var menuItem = $(this);
var menuLink = menuItem.children('a:first-child');
var subMenu = menuItem.children('ul:last-child');
menu.selectedLinks = selectedLinks;
menu.applySelectedClass(menuLink);
if (subMenu.length == 1) {
menuItem.hover(
function(){menuLink.addClass(menu.selectedClass); subMenu.slideDown(menu.animateSpeed)},
function(){subMenu.slideUp(menu.animateSpeed); menu.applySelectedClass(menuLink)}
);
subMenu.find('a').each(function(){menu.applySelectedClass($(this))});
}
});
},
applySelectedClass : function(menuLink)
{
($.inArray(menuLink.html(), menu.selectedLinks) > -1) ? menuLink.addClass(menu.selectedClass) : menuLink.removeClass(menu.selectedClass);
}
}
Y aquí está el css en caso de que alguien quiera usarlo ...
/*
menu.css - main menu cascading style sheet for ekerner.com all media
'Eugene Kerner' <ekerner@ekerner.com>
14-12-2007
*/
.menuItems, .menuItems li, .menuItems li ul, .menuItems li ul li {
padding: 0;
margin: 0;
}
.menuItems, .menuItems li ul {
list-style: none;
}
.menuItems {
background: url(/shared/images/menu/menu_button_bg.png) repeat-x;
height: 30px;
}
.menuItems:after {
content: ".";
height: 0;
clear: both;
display: none;
}
.menuItems li {
width: 80px;
float: left;
}
.menuItems li a {
color: #0d2a86;
font-size: 14px;
font-weight: bold;
text-decoration: none;
text-align: center;
height: 24px;
padding-top: 6px;
border-right: 1px solid #f3f3f3;
display: block;
}
.menuItems li a:hover, .menuItems li .selected {
background: url(/shared/images/menu/menu_button_bg_selected.png) repeat-x;
color: #518ed3;
}
.menuItems li ul {
position: absolute;
z-index: 100;
border: 1px solid #e0e7ef;
border-top: 0;
display: none;
}
.menuItems li ul li {
width: 77px;
clear: both;
}
.menuItems li ul li a {
background: #f3f3f3;
font-size: 12px;
font-weight: normal;
height: 18px;
padding: 0;
padding-top: 2px;
border: 0;
}
.menuItems li ul li a:hover, .menuItems li ul li .selected {
background: #e0e7ef;
}
.visible {
display: block;
}
.hidden {
display: none;
}
No sé si necesita el jQuery, vea el ejemplo de domerador a continuación ...
/*
menu.js : main menu javascript class for ekerner.com
Author : 'Eugene Kerner' <ekerner@ekerner.com>
Date : 14-12-2007
Dependencies: menu.css
: an unordered list structure as per the below Example.
: a javascript call to menu.init(menuId, selectedMenuItemsArray) as per the below Example.
Notes : if your menu link has an onclick that returns false then it needs to call menu.init before returning (see Example).
Example : -
<ul id="mainMenu" class="menuItems">
<li>
<a href="/">Menu Item</a>
<ul>
<li><a href="/webpage" onclick="window.open('/webpage'); menu.init('mainMenu', ['Menu Item', 'Sub Menu Item']); return false;">Sub Menu Item</a></li>
</ul>
</li>
</ul>
<script type="text/javascript">menu.init('mainMenu', ['Menu Item']);</script>
*/
var menu = {
selectedItems : [],
init : function(menuId, selectedMenuItems)
{
this.selectedItems = selectedMenuItems;
var menuItem = domIterator.getFirstChild(document.getElementById(menuId));
while (menuItem) {
var menuItemLink = domIterator.getFirstChild(menuItem);
var subMenu = domIterator.getNextSibling(menuItemLink);
this.applySelectedClass(menuItemLink);
if (subMenu) {
menuItem.onmouseover = function(){menu.showSubMenu(this)};
menuItem.onmouseout = function(){menu.hideSubMenu(this)};
var subMenuLinks = subMenu.getElementsByTagName('a');
for (var i = 0; i < subMenuLinks.length; i++)
this.applySelectedClass(subMenuLinks[i]);
}
menuItem = domIterator.getNextSibling(menuItem);
}
},
applySelectedClass : function(menuLink)
{
for (var i = 0; i < this.selectedItems.length; i++) {
if (menuLink.innerHTML == this.selectedItems[i]) {
menuLink.className = 'selected';
return;
}
}
menuLink.className = '';
},
showSubMenu : function(menuItem)
{
domIterator.getFirstChild(menuItem).className = 'selected';
domIterator.getLastChild (menuItem).style.display = 'block';
},
hideSubMenu : function(menuItem)
{
domIterator.getLastChild (menuItem).style.display = 'none';
this.applySelectedClass(domIterator.getFirstChild(menuItem));
}
}; // end menu
var domIterator = {
getFirstChild : function(elem)
{
if (elem) return domIterator.continueUntilType1(elem.firstChild, 'next');
},
getLastChild : function(elem)
{
if (elem) return domIterator.continueUntilType1(elem.lastChild, 'previous');
},
getNextSibling : function(elem)
{
if (elem) return domIterator.continueUntilType1(elem.nextSibling, 'next');
},
continueUntilType1 : function(elem, direction)
{
while (elem && elem.nodeType != 1)
elem = elem[direction + 'Sibling'];
return elem;
}
}; // end domIterator