2

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?

stevendesu
  • 15,753
  • 22
  • 105
  • 182
  • 1
    Could you show the html please? – RetroCoder Aug 27 '11 at 01:45
  • Can we see some of the markup after draggable has altered it? – orolo Aug 27 '11 at 01:46
  • @RetroCoder @orolo: I added the markup. As you can see it's fairly simple, and everything else is working perfectly. I just don't understand why in the `.each()` clause the `$(this)` object wouldn't have the `.draggable()` method, especially after it did once before – stevendesu Aug 27 '11 at 02:02
  • odd, it works for me http://jsfiddle.net/Litote0707/TjYPX/ – Andrea Aug 27 '11 at 02:07
  • Check out this fiddle http://jsfiddle.net/f6Hx4/ it looks like it works for me – Amin Eshaq Aug 27 '11 at 02:10
  • @Andrea: Strange, because I literally copied/pasted both the HTML and the javascript, as well as the error. The jsfiddle is working for me, too, but it isn't working on my site. What's even weirder is that I commented out EVERYTHING ELSE except for the javascript which was posted here and it still has the same error... – stevendesu Aug 27 '11 at 02:36
  • which browser is giving you this issue? And are you catching the error with firebug or similar debugging tool? – Andrea Aug 27 '11 at 12:16
  • I was getting the error in every browser, although I caught the error with Chrome's built-in debugger (accessed via right+click>"Inspect Element"). Although as I'm about to add to the question, I found the real problem. – stevendesu Aug 28 '11 at 21:13

1 Answers1

0

Have you tried this alternative:

$(".draggable").each(function(index, elem) {
    $(elem).html($(elem).attr('title')).draggable({
        revert: "invalid"
    });
});

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.

Behrang
  • 46,888
  • 25
  • 118
  • 160
  • I've got jQuery 1.6.2 and jQuery-UI 1.8.16, so I don't think it's a version issue... And that alternative isn't working, either. This is driving me insane – stevendesu Aug 27 '11 at 03:06
  • Can you extract the relevant parts and upload them in a zip file so that we can test it? – Behrang Aug 27 '11 at 04:11
  • I would have, but not necessary anymore =) Turns out I had a different issue entirely. Although I would like to figure out a way to handle this error instead of having javascript crash on me. I'm accepting this answer for now, but updating my problem to include the real issue – stevendesu Aug 28 '11 at 21:14
  • Great! Have a look at this question for a way for handling the case where an element does not have a specific attr: http://stackoverflow.com/questions/1318076/jquery-hasattr-checking-to-see-if-there-is-an-attribute-on-an-element – Behrang Aug 28 '11 at 22:54