views:

21

answers:

1

I'm trying to dynamically add elements to an accordion. Each added element contains a form with radio buttons styled with Custom Form Elements. Here is the code I'm using to add the element to the accordion.

$("#addpage").click(function(){
  $.get("addpage.php", function(data){
    $(data).insertAfter(".accordion div#[id^=element]:last");
  });
  $(".accordion").accordion('destroy');
  callAccordion();
});

The code is added without issue, however, the accordion never completes and the buttons aren't styled. The error says Uncaught TypeError: Cannot read property 'style' of null. When I remove the radio button, the accordion works without issue.

Here is the code for callAccordion

function callAccordion(){
$(".accordion").accordion({
   active: false,
   autoheight: false,
   collapsible: true,
   alwaysOpen: false,
   header: '> div >h3'
   }).sortable({
    axis: "y",
    handle: "h3",
    stop: function(event, ui){
    stop = true;
    },
        update: function(event, ui){
    var result = $(".accordion").sortable('toArray');
    stop = true;
    $.ajax({
    type: 'post',
    data: "element=" + result,
    url: 'modules/updatepageorder.php',
    success: function(data){
       if(data != "true"){
         alert("Unable to update page order!");
            }
    }
     });
   }
 });
 }
+1  A: 

Put the accordion code inside the callback..

$("#addpage").click(function(){
  $.get("addpage.php", function(data){
  $(data).insertAfter(".accordion div#[id^=element]:last");
  $(".accordion").accordion('destroy');
  callAccordion();
    });
});

otherwise, it gets called before the ajax call adds the new form in the accordion .. (it happens because the ajax .get() call is asynchronous)

The specific error you mention could be caused by whatever happens inside the callAccordion() method, which we cannot see.. so no help there unless you post the code of that as well..

[Update]

I have created a small update for the plugin (untested) that might cover your needs..

update: function() {

        var inputs = document.getElementsByTagName("input"), span = Array(), textnode, option, active;
        for(a = 0; a < inputs.length; a++) {
            if((inputs[a].type == "checkbox" || inputs[a].type == "radio") && inputs[a].className == "styled") {
                if((!inputs[a].previousSibling) || (inputs[a].previousSibling && inputs[a].previousSibling.className != inputs[a].type)){
                    span[a] = document.createElement("span");
                    span[a].className = inputs[a].type;

                    if(inputs[a].checked == true) {
                        if(inputs[a].type == "checkbox") {
                            position = "0 -" + (checkboxHeight*2) + "px";
                            span[a].style.backgroundPosition = position;
                        } else {
                            position = "0 -" + (radioHeight*2) + "px";
                            span[a].style.backgroundPosition = position;
                        }
                    }
                    inputs[a].parentNode.insertBefore(span[a], inputs[a]);
                    inputs[a].onchange = Custom.clear;
                    if(!inputs[a].getAttribute("disabled")) {
                        span[a].onmousedown = Custom.pushed;
                        span[a].onmouseup = Custom.check;
                    } else {
                        span[a].className = span[a].className += " disabled";
                    }
                }
            }
        }
},

Add this method in the plugin, and call Custom.update() right after you insert the new contents in your page, right after $(data).insertAfter(".accordion div#[id^=element]:last");

Gaby
Ok. The accordion part works now, but I still receive a javascript error and the styled buttons do not display. The error is listed above, and the line follows. inputs[b].previousSibling.style.backgroundPosition = "0 0";
Gene
@Gene, where is that line ? It does not show in your updated answer.. Is it from the plugin you use? and where is that code called from ?
Gaby
Yeah, I linked to the plugin, but I wasn't sure if I should post all of the code there.
Gene
@Gene, ok the problem lies with the plugin. It is not made to support updates to the DOM. When run the first time, the plugin creates an additional DOM element right before each `input` element. Then every time you click on the document it runs some code to reset those created elements, but it assumes that nothing has changed in the DOM. When you introduce new elements in the DOM through Ajax, it fails because it does not find the plugin elements corresponding to your additions..
Gaby
Not the answer I was hoping for, back to the drawing board. Thanks for all of your help!
Gene
@Gene, no worries. I have updated my answer to provide a possible solution after inspecting the plugin.. try it and let me know if it worked..
Gaby
That was incredible, and works perfectly. Thank you so much!
Gene
@Gene, :) glad i could help.. keep in mind that most of it was copy paste from parts of the plugin. It does not handle select elements.. just `checkboxes` and `radio` buttons..
Gaby