I've got a (hopefully) quick question this time, although it's been troubling me for a little while now.
I'm trying to create a progressively enhanced form so that without javascript enabled (or on devices which do not support javascript) you are still capable of all functionality, but with javascript it's easier/prettier/more intuitive.
As part of this setup I have the following code:
$( ".draggable" ).each( function(){
$(this)
.html( $(this).attr('title') )
.draggable({
revert: "invalid"
});
});
Each .draggable
is actually an <li>
element which contains, originally, three radio boxes to assign a field to one of three unique categories. Using jQuery-UI I replace these 30 sets of 3 radio boxes with a list of draggable elements and 3 droppable lists, one for each of the three unique categories. I had to use the .each()
method in order to properly set the this
variable, that way I could use $(this).attr('title')
.
My problem is the fourth line: .draggable({
. The first <li>
element is properly becoming a draggable element, however after this javascript dies with the following error:
Uncaught TypeError: Object field2 has no method 'draggable'
Any reason that one element would have the method but all subsequent elements wouldn't?
EDIT -
As per request, here's the HTML before and after it has been modified by my javascript...
before:
<ul id="form-fields">
<li class="draggable" title="field1">
<input type="radio" name="form-field-1" value="criteria" />
Criteria
<input type="radio" name="form-field-1" value="entry" />
Entry
<input type="radio" name="form-field-1" value="default" />
Default
</li>
<li class="draggable" title="field2">
<input type="radio" name="form-field-2" value="criteria" />
Criteria
<input type="radio" name="form-field-2" value="entry" />
Entry
<input type="radio" name="form-field-2" value="default" />
Default
</li>
<li class="draggable" title="field3">
...
</li>
...
<div style="clear:both;"></div>
</ul>
<div class="droppable no-js">
<h4>Criteria:</h4>
<ul id="form-field-criteria">
</ul>
</div>
<div class="droppable no-js">
<h4>Entries:</h4>
<ul id="form-field-entry">
</ul>
</div>
<div class="droppable no-js">
<h4>Defaults:</h4>
<ul id="form-field-default">
</ul>
</div>
<div style="clear:both;"></div>
(Note that the no-js
class is set to display:none;
in my CSS, and at the very top of my javascript I have the following: $( ".no-js" ).removeClass("no-js");
)
after:
<ul id="form-fields">
<li class="draggable" title="field1">field1</li>
<li class="draggable" title="field2">field2</li>
<li class="draggable" title="field3">...</li>
...
<div style="clear:both;"></div>
</ul>
<div class="droppable ">
<h4>Criteria:</h4>
<ul id="form-field-criteria">
</ul>
</div>
<div class="droppable ">
<h4>Entries:</h4>
<ul id="form-field-entry">
</ul>
</div>
<div class="droppable ">
<h4>Defaults:</h4>
<ul id="form-field-default">
</ul>
</div>
<div style="clear:both;"></div>
So the HTML markup is working perfectly. The radio boxes are removed and replaced with the field name (as found in the title
attribute). However only field1 becomes draggable before I receive an error.
EDIT -
I determined the source of the real error. It turns out that field2 didn't have a title, so it got really confused at the $(this).attr('title')
line. Although I believe this is probably a fault with jQuery (not having a title should cause $(this).attr('title')
to return null or an empty string, not break my entire script), I would like to find a way to handle this error without destroying my entire script.
Would something as simple as:
if( $(this).attr('title').len > 0 ) {
$(this).html( $(this).attr('title') );
} else {
$(this).html('');
}
be feasible?