PDA

View Full Version : Counting Items Similiar Name



bluewalrus
10-02-2010, 03:04 PM
Is there a way to count all the ids on a page that contain a certain text? Also is there a way to change the id of an element for example a div?

For example I have:


<div id="order_1" style="position:relative; height:inherit;">



These div's are generated dynamically so I know I will always have one but don't know how many will be on the page at once.
I was thinking to search for <div id="order_\d+" and count all the results with the length but I don't know where to use that.

I'm also moving these divs around with jquery's animate and would like to rename them so the content is the only thing that really moves. I can post a more specific example if needed. Thanks.

jscheuer1
10-02-2010, 04:06 PM
In jQuery there is:

http://api.jquery.com/attribute-starts-with-selector/

You can use that like:


$('div[id^=order_]')

Doing:


var numOrders = $('div[id^=order_]').size();

will tell you how many there are. Once you get a reference to a particular one of these you may change its id by (if using it as a DOM element):


el.id = 'whatever';

If it's a jQuery object:


el.attr('id', 'whatever');

bluewalrus
10-03-2010, 01:04 AM
I think I mixed something up in here but can't seem to figure out what it is. I tried using firebugs console to view the values but they looked correct to me.


function down (arrow){
var numOrders = $('div[id^=order_]').size();
if (arrow == numOrders) {
return;
}
var id_name = "#order_" + arrow;
var math_move = arrow + 1;
var inverse_id_name = "#order_" + math_move;
$(id_name).animate({"top": "+=30px"}, "slow");
$(inverse_id_name).animate({"top": "-=30px"}, "slow");
var new_id = id_name.replace("#", "");
var new_id2 = inverse_id_name.replace("#", "");
$(id_name).attr('id',new_id + "delay");
$(inverse_id_name).attr('id',new_id2);
$("#"+ new_id + "delay").attr('id',new_id);
}
function up (arrow){
var numOrders = $('div[id^=order_]').size();
var check = arrow - 1;
if (check <= numOrders) {
return;
}
var id_name = "#order_" + arrow;
var math_move = arrow - 1;
var inverse_id_name = "#order_" + math_move;
$(id_name).animate({"top": "-=30px"}, "slow");
$(inverse_id_name).animate({"top": "+=30px"}, "slow");
var new_id = id_name.replace("#", "");
var new_id2 = inverse_id_name.replace("#", "");
$(id_name).attr('id',new_id + "delay");
$(inverse_id_name).attr('id',new_id2);
$("#"+ new_id + "delay").attr('id',new_id);
}

The buttons code is



<p class="author_up"><a href="javascript:move();" onclick="up(arrow=1); return false;"><img src="arrow_up.jpg" alt="up" /></a></p>
<p class="author_down"><a href="javascript:move();" onclick="down(arrow=1); return false;"><img src="arrow_down.jpg" alt="down" /></a></p>

The are generated dynamically as well as the content being moved. Thanks for any ideas you can offer.

jscheuer1
10-03-2010, 02:12 PM
Mmm . . . You're getting into a bad habit:



onclick="down(arrow=1); . . .

In javascript what this does is create or modify a global variable named arrow, while at the same time passing the value 1 to the down (arrow) function. In your previous code (from our last thread together), where you did something like this, you needed the global variable, at least the way the rest of your code was constructed. And it was an object. So it was the same object as passed locally to the function. Here it's a number. So it's two distinct variables, one global and the other local, neither of which interact with the other.

As currently constructed, the code in your post doesn't appear to use the global arrow variable.

Next item - It would be easier if I had a link to the page where this code is being used, but here, if you click the up button:


function up (arrow){ // arrow is always 1
var numOrders = $('div[id^=order_]').size(); // regardless of how we got here, this is always 0 or more
var check = arrow - 1; // check is always 0
if (check <= numOrders) { // this is always true
return; // so processing always stops here
}

In the down function things are a bit better. If invoked by clicking the down button, as long as there are 0 or more than 1 div[id^=order_] processing will continue to:


var id_name = "#order_" + arrow; // id_name is always #order_1
var math_move = arrow + 1; // math_move is always 2
var inverse_id_name = "#order_" + math_move; // inverse_id_name is always #order_2
$(id_name).animate({"top": "+=30px"}, "slow"); // we animate these if they exist
$(inverse_id_name).animate({"top": "-=30px"}, "slow");
var new_id = id_name.replace("#", ""); // new_id is always order_1
var new_id2 = inverse_id_name.replace("#", ""); // new_id2 is always order_2
$(id_name).attr('id',new_id + "delay"); // if it exists, the first element with the id order_1 now has the id of order_1delay
$(inverse_id_name).attr('id',new_id2); // similarly for element with id order_2, is now id order_2delay
$("#"+ new_id + "delay").attr('id',new_id); // element, if it existed that we just changed to id order_1delay is now id order_1 again

Note: Elements with an id of order_1delay or order_2delay fit the criteria of [id^=order_].

bluewalrus
10-03-2010, 04:55 PM
Not sure I understand. The previous link should still be working.

So the 1 is being passed in so it knows which container to move. The arrows are staying in the same place. My example wasn't a very good one because as 1 when there is only 1 it should do nothing. This full code is related with PHP, it basically just increases the arrow count so it knows which container to move.



<?php
$author_count = $_POST['get_count'];
$author_count++;
?>
<div id="author_id_###">
<p class="author_up"><a href="javascript:move();" onclick="up(arrow=<?php echo $author_count;?>); return false;"><img src="arrow_up.jpg" alt="up" /></a></p>
<p class="author_down"><a href="javascript:move();" onclick="down(arrow=<?php echo $author_count;?>); return false;"><img src="arrow_down.jpg" alt="down" /></a></p>
<div id="order_<?php echo $author_count;?>" style="position:relative; height:inherit;">
<p class="author_name"><?php echo $_POST['firstname'] . " " . $_POST['lastname']?></p>
<p class="author_email"><?php echo $_POST['email'];?></p>
<p class="buttons">
<a href="#">edit</a>
<a href="#">delete</a></p>
</div>
</div>

jscheuer1
10-04-2010, 12:26 AM
Not understanding is fine. We all start there. I'm still in the process of wrapping my head around this one.

What exactly don't you understand? And what's the "previous link"?

Anyways, having the value passed to the up and down functions by their activating link buttons being determined by PHP could perhaps take care of a lot. Either you didn't make that clear at first and/or I didn't get it. If it was all me, please accept my apologies.

Like before though, to really get at this, I need to see the page and know what to do to see the problem. This includes knowing what you want to happen as well as what, if anything, is happening instead.

You could always comment the code as I did, only using your own ideas as to what should be happening with each line. Use alerts and/or observation to see if your expectations are borne out.

That might help clarify the issue(s) enough to solve it or to make it clearer what specifically you want help on.



What I said about the habit of doing something like:


<a href="javascript:move();" onclick="down(arrow=1); return false;">

still stands. But it's just about good javascript coding practices. I don't think it's a factor in things not behaving as you want. And it may work out for you in the short term. In the long term you are just asking for problems. In this case the code doesn't appear to even use it.

You should get the same result from:


<a href="javascript:move();" onclick="down(1); return false;">

Or from:


<a href="javascript:move();" onclick="down(<?php echo $author_count;?>); return false;">

bluewalrus
10-07-2010, 12:21 AM
I don't understand why the "down(arrow=1)" is a bad javascript coding.

I've gotten the conditionals to work, I think, but now need to change the element div names accordingly. When I look at the values in firebug they are what i expect but they don't set.

Is it also poor javascript practice to mix jquery with regular javascript (is there a phrasing for that as well?)?

Thanks for any help you can offer.

Code with functioning conditionals:



function down (arrow){
var numOrders = $('div[id^=order_]').size();
if (arrow == numOrders) {
return;
}
var id_name = "#order_" + arrow;
var math_move = arrow + 1;
var inverse_id_name = "#order_" + math_move;
$(id_name).animate({"top": "+=30px"}, "slow");
$(inverse_id_name).animate({"top": "-=30px"}, "slow");
var new_id = id_name.replace("#", "");
var new_id2 = inverse_id_name.replace("#", "");
$(id_name).attr('id',new_id + "delay");
$(inverse_id_name).attr('id',new_id2);
$("#"+ new_id + "delay").attr('id',new_id);
}
function up (arrow){
var numOrders = $('div[id^=order_]').size();
var checkNum = numOrders- (numOrders - 1);
if (arrow <= checkNum) {
return;
}
var id_name = "#order_" + arrow;
var math_move = arrow - 1;
var inverse_id_name = "#order_" + math_move;
$(id_name).animate({"top": "-=30px"}, "slow");
$(inverse_id_name).animate({"top": "+=30px"}, "slow");
var new_id = id_name.replace("#", "");
var new_id2 = inverse_id_name.replace("#", "");
$(id_name).attr('id', new_id + "delay");
$(inverse_id_name).attr('id', new_id2);
$("#"+ new_id + "delay").attr('id', new_id);
}

jscheuer1
10-07-2010, 08:34 AM
I'll comment on the specifics of the code later.

As for:


down(arrow=1)

to activate:


function down (arrow){

What arrow=1 in there does is create or alter a global variable named arrow. In this case this is an undeclared global variable. It's the same thing as doing (outside of any function):


arrow=1;
down(arrow);

So it will conflict in some browsers with an element (if any) with an id of arrow. It will also overwrite the value of any other global variable named arrow. You don't need or use this global variable in your code.

It also evaluates into a value of 1. To see both concepts try:


alert(arrow=1); //alerts 1 and sets an undeclared global arrow to 1
alert(arrow); //alerts 1, the value of the undeclared global arrow

In so doing it passes that value as the first argument to the function down (arrow){, which also happens to be named arrow, but is local to the function down (arrow){. That local variable is needed and used. To further understand these concepts do:


function down(arrow){
arrow = arrow + 1;
alert(arrow);
}
down(arrow=1);
alert(arrow);

You are dealing with two arrow variables, one global and the other local. Changing the local one doesn't change the global one. And unless you invoke it again in the same way, changing the global one doesn't affect the local one.


As for mixing regular javascript with jQuery, jQuery is regular javascript. It's a library of routines that do specific things. Do:


alert($);

and it will alert:


function (a, b) {
return new (c.fn.init)(a, b);
}

What the new keyword does is create an instance, an instance where the keyword this will refer to the instance. It's a little more complicated than that, but still just javascript. The key to 'mixing' them is to know what this is in any particular case where you use it in your code.

jscheuer1
10-07-2010, 01:02 PM
More on 'mixing' jQuery and ordinary javascript -

In my previous post I mentioned the importance of knowing what this refers to. Another consideration is knowing when a jQuery or an ordinary javascript method might be more appropriate. These sorts of things come with experience. Generally though you can convert an object to using jQuery methods from ordinary ones and visa versa:


var obj = document.getElementById('test'); // ordinary html element object
obj = $(obj); // now it's a jQuery object
obj = obj.get(0); // it's an ordinary html element object again

The conversion back to ordinary only works equivalently if the jQuery object had one and only one member. If it has more than one, obj will now be just the first member from the jQuery object. If it had no members, the ordinary object will now be null.

Frequent use of these types of conversions usually aren't required. If your code relies upon frequent use of them, it's probably not as efficient as it could be. jQuery itself routinely performs the conversion to ordinary though in this and many similar constructs:


var objs = $('div[id^=order_]');
objs.click(function(){
alert(this.innerHTML);
}

this in this case refers to the ordinary html element object that was clicked.

And there are at least several jQuery methods that can accept either a jQuery object or an ordinary html element object as an argument.

It's generally best to determine what method you want to use and to read its api reference from:

http://api.jquery.com/

to determine what it will accept as arguments. Weigh this against what you have available to feed to it, and decide how to proceed from there.

About the code in your post. I still need to see it in action. Try setting up a demo that illustrates the problem. It need not include all that much, in fact it's better if there are no images or ajax involved, just the moving about of elements that you want to accomplish.

bluewalrus
10-07-2010, 09:19 PM
Oh, thanks I think I get what you mean about the local and global now.

I've also made up a simpler version of the page here http://174.120.151.156/~crazychr/move.php

jscheuer1
10-08-2010, 11:07 AM
As I think I indicated at some point, it was easier to rewrite than tweak this. After doing so it became apparent that the main problem with the version in your previous post was that it wasn't keeping adequate track of what got moved where.

I'm not sure about how important it is that these id's get changed, but I've maintained that in case it is for some other function(s) used on this markup later. It's not required for the functionality of this effect.

I made a couple of additions and one change to the stylesheet to aid accessibility cross browser, and one addition for functionality in Opera.

Stylesheet changes (highlighted):


.author_name, .author_email, .author_up, .author_down {
float: left;
position: relative;
z-index: 100;
}
.buttons {
position:relative;
text-align:right;
}
.order {
position: relative;
top: 0;
}

Here's the new code for the page (markup and script have both changed):


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>JoVE Submissions 2</title>
<link type="text/css" rel="stylesheet" href="JOVE/submissions.css" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script type="text/javascript">
jQuery(function($){
var oH = null;
function getHeight(){
oH = $('.order');
oH = oH.eq(1).offset().top - oH.eq(0).offset().top;
getHeight = function(){};
}
function assignData(){
getHeight();
$('.author_up a, .author_down a').each(function(){
var updwn = $(this);
if(!updwn.data('orderdiv')){
updwn.data('orderdiv', updwn.parent().nextAll('.order').eq(0));
}
})
}
$('.author_up a').live('click', function(e){
e.preventDefault();
var up = $(this), upp = up.parent().prevAll('.author_up').eq(0).find('a'), div1, div2, id1, id2;
if(upp.size()){
assignData();
div1 = upp.data('orderdiv');
div2 = up.data('orderdiv');
up.parent().next('p').find('a').data('orderdiv', div1);
upp.parent().next('p').find('a').data('orderdiv', div2);
id1 = div1.attr('id');
id2 = div2.attr('id');
div1.attr('id', id2).animate({top: '+=' + oH}, 'slow');
div2.attr('id', id1).animate({top: '-=' + oH}, 'slow');
upp.data('orderdiv', div2);
up.data('orderdiv', div1);
}
});
$('.author_down a').live('click', function(e){
e.preventDefault();
var dwn = $(this), dwnn = dwn.parent().nextAll('.author_down').eq(0).find('a'), div1, div2, id1, id2;
if(dwnn.size()){
assignData();
div1 = dwnn.data('orderdiv');
div2 = dwn.data('orderdiv');
dwn.parent().prev('p').find('a').data('orderdiv', div1);
dwnn.parent().prev('p').find('a').data('orderdiv', div2);
id1 = div1.attr('id');
id2 = div2.attr('id');
div1.attr('id', id2).animate({top: '-=' + oH}, 'slow');
div2.attr('id', id1).animate({top: '+=' + oH}, 'slow');
dwnn.data('orderdiv', div2);
dwn.data('orderdiv', div1);
}
});
});
</script>
</head>
<body>
<div id="author_box">
<p class="author_up"><a href="javascript:moveUp();"><img src="JOVE/arrow_up.jpg" alt="up" title="up" /></a></p>
<p class="author_down"><a href="javascript:moveDown();"><img src="JOVE/arrow_down.jpg" alt="down" title="down" /></a></p>
<div class="order" id="order_1">
<div id="author_id_1">
<p class="author_name">FirstName LastName</p>
<p class="author_email">author@email.com</p>
<p class="buttons"> <a href="#">edit</a> <a href="#">delete</a></p>
</div>
</div>
<br />
<p class="author_up"><a href="javascript:moveUp();"><img src="JOVE/arrow_up.jpg" alt="up" title="up" /></a></p>
<p class="author_down"><a href="javascript:moveDown();"><img src="JOVE/arrow_down.jpg" alt="down" title="down" /></a></p>
<div class="order" id="order_2">
<div id="author_id_2">
<p class="author_name">ABC 123</p>
<p class="author_email">ME@.</p>
<p class="buttons"> <a href="#">edit</a> <a href="#">delete</a></p>
</div>
</div>
<br />
<p class="author_up"><a href="javascript:moveUp();"><img src="JOVE/arrow_up.jpg" alt="up" title="up" /></a></p>
<p class="author_down"><a href="javascript:moveDown();"><img src="JOVE/arrow_down.jpg" alt="down" title="down" /></a></p>
<div class="order" id="order_3">
<div id="author_id_3">
<p class="author_name">Blue Walrus</p>
<p class="author_email">author@email.com</p>
<p class="buttons"> <a href="#">edit</a> <a href="#">delete</a></p>
</div>
</div>
</div>
</body>
</html>

Notes: I'm using jQuery to attach/add the click events via its live() method. That and how and when things are calculated/set should maintain functionality even when other elements that may be added dynamically qualify for this treatment. Not sure about removed though yet. As a byproduct no global functions or variables are needed, other than the domready for the page, which all pages have anyway.

A possible improvement might be combining the two live('click', . . . calls, if that can be worked out.

jscheuer1
10-10-2010, 06:43 AM
Here's a version that should handle additions and removals well. It uses the same stylesheet modifications as in my last post:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>JoVE Submissions 2</title>
<link type="text/css" rel="stylesheet" href="JOVE/submissions.css" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script type="text/javascript">
/* <![CDATA[ */
jQuery(function($){
var oH, animating;
function getHeight(){
oH = $('.order');
oH = oH.eq(1).offset().top - oH.eq(0).offset().top;
getHeight = function(){};
}
function assignIds(){
getHeight();
var count = 0;
$('.order').each(function(){
$(this).attr('id', 'order_' + (++count)).find('div[id^=author_id_]').attr('id', 'author_id_' + count);
});
}
$('#author_box').click(function(e){e.preventDefault();});
$('.delete, .edit').live('click', function(){
if(this.className === 'delete'){
$(this).parents('.order').prevAll('p:lt(2)').remove().end().next('br').remove().end().remove();
assignIds();
}
});
$('.author_up a').live('click', function(){
var up = $(this), upp = up.parent().prevAll('.author_up').eq(0).find('a'), div1, div2;
if(upp.size() && !animating){
animating = true;
assignIds();
div1 = upp.parent().nextAll('.order').eq(0);
div2 = up.parent().nextAll('.order').eq(0);
div1.animate({top: '+=' + oH}, 'slow');
div2.animate({top: '-=' + oH}, 'slow', function(){
div1.before(div2.clone(true).css({top: 0}));
div2.before(div1.clone(true).css({top: 0}));
div1.remove();
div2.remove();
assignIds();
animating = false;
});
}
});
$('.author_down a').live('click', function(){
$(this).parent().nextAll('.author_up').eq(0).find('a').click();
});
});
/* ]]> */
</script>
</head>
<body>
<div id="author_box">
<p class="author_up"><a href="javascript:moveUp();"><img src="JOVE/arrow_up.jpg" alt="up" title="up" /></a></p>
<p class="author_down"><a href="javascript:moveDown();"><img src="JOVE/arrow_down.jpg" alt="down" title="down" /></a></p>
<div class="order" id="order_1">
<div id="author_id_1">
<p class="author_name">FirstName LastName</p>
<p class="author_email">author@email.com</p>
<p class="buttons"> <a class="edit" href="javascript:edit();">edit</a> <a class="delete" href="javascript:delete();">delete</a></p>
</div>
</div>
<br />
<p class="author_up"><a href="javascript:moveUp();"><img src="JOVE/arrow_up.jpg" alt="up" title="up" /></a></p>
<p class="author_down"><a href="javascript:moveDown();"><img src="JOVE/arrow_down.jpg" alt="down" title="down" /></a></p>
<div class="order" id="order_2">
<div id="author_id_2">
<p class="author_name">ABC 123</p>
<p class="author_email">ME@.</p>
<p class="buttons"> <a class="edit" href="javascript:edit();">edit</a> <a class="delete" href="javascript:delete();">delete</a></p>
</div>
</div>
<br />
<p class="author_up"><a href="javascript:moveUp();"><img src="JOVE/arrow_up.jpg" alt="up" title="up" /></a></p>
<p class="author_down"><a href="javascript:moveDown();"><img src="JOVE/arrow_down.jpg" alt="down" title="down" /></a></p>
<div class="order" id="order_3">
<div id="author_id_3">
<p class="author_name">Blue Walrus</p>
<p class="author_email">author@email.com</p>
<p class="buttons"> <a class="edit" href="javascript:edit();">edit</a> <a class="delete" href="javascript:delete();">delete</a></p>
</div>
</div>
<br />
<p class="author_up"><a href="javascript:moveUp();"><img src="JOVE/arrow_up.jpg" alt="up" title="up" /></a></p>
<p class="author_down"><a href="javascript:moveDown();"><img src="JOVE/arrow_down.jpg" alt="down" title="down" /></a></p>
<div class="order" id="order_4">
<div id="author_id_4">
<p class="author_name">SecondName LastName</p>
<p class="author_email">author@email.com</p>
<p class="buttons"> <a class="edit" href="javascript:edit();">edit</a> <a class="delete" href="javascript:delete();">delete</a></p>
</div>
</div>
<br />
<p class="author_up"><a href="javascript:moveUp();"><img src="JOVE/arrow_up.jpg" alt="up" title="up" /></a></p>
<p class="author_down"><a href="javascript:moveDown();"><img src="JOVE/arrow_down.jpg" alt="down" title="down" /></a></p>
<div class="order" id="order_5">
<div id="author_id_5">
<p class="author_name">DEF 456</p>
<p class="author_email">ME2@.</p>
<p class="buttons"> <a class="edit" href="javascript:edit();">edit</a> <a class="delete" href="javascript:delete();">delete</a></p>
</div>
</div>
<br />
<p class="author_up"><a href="javascript:moveUp();"><img src="JOVE/arrow_up.jpg" alt="up" title="up" /></a></p>
<p class="author_down"><a href="javascript:moveDown();"><img src="JOVE/arrow_down.jpg" alt="down" title="down" /></a></p>
<div class="order" id="order_6">
<div id="author_id_6">
<p class="author_name">Red Walrus</p>
<p class="author_email">author@email.com</p>
<p class="buttons"> <a class="edit" href="javascript:edit();">edit</a> <a class="delete" href="javascript:delete();">delete</a></p>
</div>
</div>
</div>
</body>
</html>

bluewalrus
10-10-2010, 04:54 PM
Wow thanks. I've still been going through the last code you posted and trying to understand it all.

What is the purpose of this at the end of the getHeight function?


getHeight = function(){};

How does this set the 2 variables?


var dwn = $(this), dwnn = dwn.parent().nextAll('.author_down').eq(0).find('a')

Is there a way I can find the id of the div within the moving div.


<div class="order" id="order_2">
<div id="author_id_2"><!--this one-->

EDIT:

I think I figured this one out.


div2[0].childNodes[1].id
div1[0].childNodes[1].id

jscheuer1
10-10-2010, 11:13 PM
1 )
var oH = null;
function getHeight(){
oH = $('.order');
oH = oH.eq(1).offset().top - oH.eq(0).offset().top;
getHeight = function(){};
}

That's a self canceling function. I'm not sure if that's a real term or not, probably not. But it's fairly common practice for a function to modify itself.

When the page first loads there's no guarantee there will be one, let alone the two order divisions required to make this calculation. Once the calculation is made though, it need not be made again.

So even though it's invoked each time that:


$('.author_up a').live('click', function(e){ . . .
. . . if(upp.size()){
assignData();

or its counterpart in the .author_down a element's clicked when either have enough order divs, it only need take up any processing time the first time.



2 ) In this sort of jQuery construct where an event (click in this case) is bound (in this case using the jQuery live() function which will bind it to new content that qualifies that arrives later as well) to one or more elements:


$('.author_down a').live('click', function(e){
e.preventDefault();
var dwn = $(this), dwnn = dwn.parent().nextAll('.author_down').eq(0).find('a'), div1, div2, id1, id2;

the keyword this refers to the DOM element that's clicked. So we snag that one and turn it into a jQuery object with:


dwn = $(this)

Now that it's a jQuery object we can use jQuery methods on it to walk the DOM tree to find its counterpart that controls the other .order div that will also be moved in this operation:


dwnn = dwn.parent().nextAll('.author_down').eq(0).find('a')

to do so we go to dwn's parent (which is a p element), find all of its next siblings (nextAll) filtered by the class we are looking for, and choose the first of those found (.eq(0)). That will be another p element, so all we need now is to find() it's a tag.

3 )
Is there a way I can find the id of the div within the moving div.

Yes, that should work, but to what end? In my previous post, #12 in this thread, I have:


function assignIds(){
getHeight();
var count = 0;
$('.order').each(function(){
$(this).attr('id', 'order_' + (++count)).find('div[id^=author_id_]').attr('id', 'author_id_' + count);
});
}

Which goes through all of the order div's each time it might be required for the purpose of renumbering them and their contained author_id_# to reflect the actual order on the page.

In fact, this newer version is a bit of a departure in that we no longer need to keep track of which order div belongs to which set of movement controls because we actually move the order div. This results in it being in the correct spot in the DOM tree to be easily renumbered and to be easily found the next time it's needed.

This latest (from #12 in this thread) also compresses things quite a bit for greater efficiency.

P.S. I've yet another version that compresses things further and makes the delete function animated.

bluewalrus
10-11-2010, 01:05 AM
Oh, okay thanks for the explanations. I just noticed that the 'author_id_#' is renumbering is there a way to make that static because that # is going to be coming from a DB and should correspond with the name and email?

Nevermind that last question I figured that part out, removed


.find('div[id^=author_id_]').attr('id', 'author_id_' + count)

jscheuer1
10-11-2010, 04:52 AM
From the beginning I wasn't clear what any of these numbered id's were for. I chose to keep the order on the page, as it would express the user's preference.

I could have chosen to leave them alone so that they would follow their elements about as markers. That way they would correspond to whatever they corresponded to before visa vis that element, but not to their order on the page. Their order on the page can always be gotten via javascript anyway, without them needing to have numbers.

So you would like to preserve the author_id_#. That can be done like you say. How about the id=order_# ? That can also be done. Moving these things around doesn't depend upon renumbering any of them.

What, if anything are the id="order_#" attributes used for? If nothing, they should be eliminated. The latest code uses their class attribute, not their id's.

bluewalrus
10-11-2010, 05:07 PM
I think the order_id may not be necessary. The author_id is a static value that comes from the db and shouldn't be changed. The order_id div I created to control the movement. After looking at what you've done this maybe possible to do with the jquery data() utility(if that's what they are called).

jscheuer1
10-11-2010, 06:05 PM
It's not, and neither is the data property of the movement links. Working from the code in post #12 I added two more things to the css:


#author_box {
border: solid 1px #acc8eb;
font-size: 12pt;
padding: 10px 10px 0;
width: 780px;
overflow: hidden;
clear: both;
}

and:


.order {
margin-bottom: 16px;
position: relative;
top: 0;
}

and got rid of the br tags, the id="order_#" attributes and the update function to come up with this:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>JoVE Submissions 2</title>
<link type="text/css" rel="stylesheet" href="JOVE/submissions.css" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script type="text/javascript">
/* <![CDATA[ */
jQuery(function($){
var oH, animating;
function getHeight(){
oH = $('.order').outerHeight(true);
getHeight = function(){};
}
$('#author_box').click(function(e){e.preventDefault();});
$('.delete, .edit').live('click', function(){
if(this.className === 'delete'){
$(this).parents('.order').prevAll('p:lt(2)').remove().end().remove();
}
});
$('.author_up a').live('click', function(){
var up = $(this), upp = up.parent().prevAll('.author_up').eq(0).find('a'), div1, div2;
if(upp.size() && !animating){
getHeight();
animating = true;
div1 = upp.parent().nextAll('.order').eq(0);
div2 = up.parent().nextAll('.order').eq(0);
div1.animate({top: '+=' + oH}, 'slow');
div2.animate({top: '-=' + oH}, 'slow', function(){
div1.before(div2.clone(true).css({top: 0}));
div2.before(div1.clone(true).css({top: 0}));
div1.remove();
div2.remove();
animating = false;
});
}
});
$('.author_down a').live('click', function(){
$(this).parent().nextAll('.author_up').eq(0).find('a').click();
});
});
/* ]]> */
</script>
</head>
<body>
<div id="author_box">
<p class="author_up"><a href="javascript:moveUp();"><img src="JOVE/arrow_up.jpg" alt="up" title="up" /></a></p>
<p class="author_down"><a href="javascript:moveDown();"><img src="JOVE/arrow_down.jpg" alt="down" title="down" /></a></p>
<div class="order">
<div id="author_id_1">
<p class="author_name">FirstName LastName</p>
<p class="author_email">author@email.com</p>
<p class="buttons"> <a class="edit" href="javascript:edit();">edit</a> <a class="delete" href="javascript:delete();">delete</a></p>
</div>
</div>
<p class="author_up"><a href="javascript:moveUp();"><img src="JOVE/arrow_up.jpg" alt="up" title="up" /></a></p>
<p class="author_down"><a href="javascript:moveDown();"><img src="JOVE/arrow_down.jpg" alt="down" title="down" /></a></p>
<div class="order">
<div id="author_id_2">
<p class="author_name">ABC 123</p>
<p class="author_email">ME@.</p>
<p class="buttons"> <a class="edit" href="javascript:edit();">edit</a> <a class="delete" href="javascript:delete();">delete</a></p>
</div>
</div>
<p class="author_up"><a href="javascript:moveUp();"><img src="JOVE/arrow_up.jpg" alt="up" title="up" /></a></p>
<p class="author_down"><a href="javascript:moveDown();"><img src="JOVE/arrow_down.jpg" alt="down" title="down" /></a></p>
<div class="order">
<div id="author_id_3">
<p class="author_name">Blue Walrus</p>
<p class="author_email">author@email.com</p>
<p class="buttons"> <a class="edit" href="javascript:edit();">edit</a> <a class="delete" href="javascript:delete();">delete</a></p>
</div>
</div>
<p class="author_up"><a href="javascript:moveUp();"><img src="JOVE/arrow_up.jpg" alt="up" title="up" /></a></p>
<p class="author_down"><a href="javascript:moveDown();"><img src="JOVE/arrow_down.jpg" alt="down" title="down" /></a></p>
<div class="order">
<div id="author_id_4">
<p class="author_name">SecondName LastName</p>
<p class="author_email">author@email.com</p>
<p class="buttons"> <a class="edit" href="javascript:edit();">edit</a> <a class="delete" href="javascript:delete();">delete</a></p>
</div>
</div>
<p class="author_up"><a href="javascript:moveUp();"><img src="JOVE/arrow_up.jpg" alt="up" title="up" /></a></p>
<p class="author_down"><a href="javascript:moveDown();"><img src="JOVE/arrow_down.jpg" alt="down" title="down" /></a></p>
<div class="order">
<div id="author_id_5">
<p class="author_name">DEF 456</p>
<p class="author_email">ME2@.</p>
<p class="buttons"> <a class="edit" href="javascript:edit();">edit</a> <a class="delete" href="javascript:delete();">delete</a></p>
</div>
</div>
<p class="author_up"><a href="javascript:moveUp();"><img src="JOVE/arrow_up.jpg" alt="up" title="up" /></a></p>
<p class="author_down"><a href="javascript:moveDown();"><img src="JOVE/arrow_down.jpg" alt="down" title="down" /></a></p>
<div class="order">
<div id="author_id_6">
<p class="author_name">Red Walrus</p>
<p class="author_email">author@email.com</p>
<p class="buttons"> <a class="edit" href="javascript:edit();">edit</a> <a class="delete" href="javascript:delete();">delete</a></p>
</div>
</div>
</div>
</body>
</html>

I also have a way of animating the delete (not included here). It fades out and animates to 0 height before removal.

But all of these (including my original version in post #11, and yours in post #10) have some minor but odd and disconcerting layout issues in IE 7. The author email can jump around a little horizontally and is truncated slightly vertically. IE 8 and all others are fine with it. I'll see if I can track that IE 7 layout issue down.