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?
Have you tried this alternative:
Also which version of jQuery and jQuery UI are you using? It might be the version of jQuery and jQuery UI that you are using are not compatible with each other.