fanfavorite
fanfavorite

Reputation: 5199

PrototypeJS Element.prototype.appendChild issue

Due to Ajax loaded content, I had to change a function from:

document.observe('dom:loaded',function() {    
    $$('.userListHeaderCell').invoke('observe', 'click', function() {       
        this.toggleClassName('desc');        
        var colnumber = this.up().childElements().indexOf(this);        
        var content = this.up(2); 
        sortColumn(content, colnumber, this.hasClassName('desc'));    
    });
});

TO:

document.observe('click', function(e, el) {  
    if (el = e.findElement('.userListHeaderCell.sortable')) { 
        el.toggleClassName('desc');        
        var colnumber = el.up().childElements().indexOf(el);        
        var content = el.up(2); 
        sortColumn(content, colnumber, el.hasClassName('desc'));   
    }
});

The sortColumn looks like:

function sortColumn(content, colnumber, desc) {    
    content.select('.userListRow').sort(function(a,b){        
        var atext = a.down(colnumber).innerHTML.stripTags().toLowerCase();        
        var btext = b.down(colnumber).innerHTML.stripTags().toLowerCase();        
        return atext.localeCompare(btext) * (desc ? -1 : 1);    
    }).each(Element.prototype.appendChild, content);
}

The toggle and colnumber work and content is an object HTMLDivElement, but it seems that I need to convert the content variable or use another function, but not sure what in the sortColumn. The error I get is:

"Could not convert JavaScript argument" nsresult: "0x80570009 (NS_ERROR_XPC_BAD_CONVERT_JS)" location: "JS frame :: https://www.someurl.com/scripts/prototype.js :: :: line 804" data: no]

What do I need to change in order to make this work?

Thanks.

EDIT:

Error in IE shows: Unable to get value of the property 'call': object is null or undefined prototype.js, line 804 character 9

I believe the issue is with Element.prototype.appendChild

Tried adding Element.extend(content), but doesn't seem to help.

Example data:

<div id="contentbox_Users" class="userList">
    <div class="userListHeader">
        <div class="userListHeaderCell col1 sortable">First Name</div>
        <div class="userListHeaderCell col2 sortable">Last Name</div>
    </div>
    <div id="contentbox_People">
        <div class="userListRow">
            <div class="userListCell col1">John</div>
            <div class="userListCell col2">Smith</div>
        </div>
        <div class="userListRow">
            <div class="userListCell col1">Bob</div>
            <div class="userListCell col2">Ray</div>
        </div>
        <div class="userListRow">
            <div class="userListCell col1">Fred</div>
            <div class="userListCell col2">Jones</div>
        </div>
    </div>
</div>

Upvotes: 0

Views: 2796

Answers (1)

clockworkgeek
clockworkgeek

Reputation: 37700

Since it is my code that is failing I should have a go.

The line,

}).each(Element.prototype.appendChild, content);

is a shorthand way of saying,

}).each(function(row) {
    content.appendChild(row);
});

You can try it that way to see if things are better. I don't recognise the error but a quick google suggests it is from Firefox and relates to passing a non-element to a native function that expects one. In situations such as this I tend to stick lots of console.log(...) calls everywhere (and press F12 in Firefox) and see what happens. Logging the array should show all the rows as HTML elements.

Upvotes: 1

Related Questions