Reputation: 33715
Hey everyone, take a look at the code below and appreciate how messy the id attributes are
View File
<?php foreach($array_project as $prj) : ?>
<div id="prj-p<?=$item['project_id'] ?>">
<?php foreach($arr_skill as $skill) : ?>
<h2><?=$skill['name'] ?></h2>
<a class="view" id="skill-p<?=$prj['project_id'] ?>-s<?=skill['skill_id'] ?>">view</a>
<a class="edit" id="edit-p<?=$prj['project_id'] ?>-s<?=skill['skill_id'] ?>">edit</a>
<a class="delete" id="delete-p<?=$prj['project_id'] ?>-s<?=skill['skill_id'] ?>">delete</a>
<?php endforeach; ?>
</div>
<?php endforeach; ?>
Javascript File (using Jquery)
$('.view').live('click', onClick);
$('.edit').live('click', onClick);
$('.delete').live('click', onClick);
function onClick()
{
// prjId and skillId are effectively arguments that are
// traditionally passed via onClick(prjId, skillId), but here
// we've attached them to element ids
prjId = this.id.replace(/(skill\-p)|(\-s\d+)/g, '')
skillId = this.id.replace(/(skill\-p\d+)|(\-s)/,'');
// do stuff with the prjId and skillId
}
So my issue with the above code is that doing something like this in the view file
<a class="view" id="skill-p<?=$prj['project_id'] ?>-s<?=skill['skill_id'] ?>">view</a>
is effectively the same as
<a onclick="onClick(<?=$prj['project_id'] ?>,<?=skill['skill_id'] ?>)">view</a>
With the latter actually being more readable to the programmer. In the former, I don't like how I have to derive my own id naming convention to keep track of database entity ids: for example, -p prefix denotes project id, and -s prefix denotes skill_id. And then I have to use regular expression to parse it. I don't liek the latter of inline js event handlers, because that's intrusive javascript.
I thought about simplifying the code like this:
View File
<?php foreach($array_project as $prj) : ?>
<div id="prj-p<?=$item['project_id'] ?>">
<?php foreach($arr_skill as $skill) : ?>
<h2><?=$skill['name'] ?></h2>
<input type="hidden" class="project_id" value="<?=$prj['project_id'] ?>" />
<input type="hidden" class="skill_id" value="<?=$prj['skill_id'] ?>" />
<a class="view">view</a>
<a class="edit">edit</a>
<a class="delete">delete</a>
<?php endforeach; ?>
</div>
<?php endforeach; ?>
Javascript File (using Jquery)
$('.view').live('click', onClick);
$('.edit').live('click', onClick);
$('.delete').live('click', onClick);
function onClick()
{
prjId = this.parentNode.childNodes[1].value;
skillId = this.parentNode.childNodes[2].value;
// do stuff with the prjId and skillId
}
This is much easier less coding when I have A LOT of db entity ids to reference between the js and view files (eg. i only have to print the project_id and skill_id ONCE). But the problem with this solution is that as soon as my designer changes the xhtml schema, I have to update my javascript file to re-reference the hidden input fields.
Is there an easier and less code-redundant way for html elements to pass data to javascript functions?
Upvotes: 0
Views: 190
Reputation: 4567
This is a little less sensitive too, though I like @Nick's a little better.
function onClick()
{
prjId = $(this).parent().find(".project_id").attr("value");
skillId = $(this).parent().find(".skill_id").attr("value");
// do stuff with the prjId and skillId
}
Upvotes: 1
Reputation: 630549
You could use data attributes, like this:
<?php foreach($array_project as $prj) : ?>
<div id="prj-p<?=$item['project_id'] ?>" data-pid="<?=$prj['project_id'] ?>" data-sid="<?=$prj['skill_id'] ?>">
<?php foreach($arr_skill as $skill) : ?>
<h2><?=$skill['name'] ?></h2>
<a class="view">view</a>
<a class="edit">edit</a>
<a class="delete">delete</a>
<?php endforeach; ?>
</div>
<?php endforeach; ?>
Then access them in jQuery:
$('.view, .edit, .delete').live('click', onClick);
function onClick()
{
var div = $(this).closest("div"),
prjId = div.attr("data-pid"),
skillId = div.attr("data-did");
// do stuff with the prjId and skillId
}
This work in HTML4 and is a part of the HTML5 standard, so no conflicts now, completely compliant HTML later. with this approach you may not even needs the id
on the <div>
, if that's the case you can remove the attribute, since it's not needed, only the data-
ones are used in the onClick()
function above. You may also want to give that container <div>
a class, like class="project"
and change the call to find it to .closest(".project")
to make it a bit more resilient.
Upvotes: 3