2

I am working on a project that imports some javascript rules from a file myjs.js, which is called (on all the web page of the project) in the header. This files manages the behavior of checkboxes, and in fact toggling the checks of every checkbox pairs. The problem is that in some case, this behavior is wrong but I can't change anything in this js file because it is too complex. So, on some page, I decided to listen to the click event on some checkbox to correct the behavior : the problem is that there is a conflict of script and I can't trigger my script (put on this very page). How can I force it to make my java script listened first ?

In fact the checkbox are constructed by myjs.js, applying to the html sequece

<div class="left">
          <input type="radio" name="isPubOk" id="pubOk" checked="checked" />
           <label for="pubOk"><?php echo _("Oui"); ?></label>
</div>
<div class="left">
          <input type ="radio" name="isPubNok" id="pubNok" checked="" />
          <label for="pubNok"><?php echo _("Non"); ?></label>
</div>

Here's a sample of the js file :

function initCustomForms() {
    getElements();
    separateElements();
    replaceRadios();
    replaceCheckboxes();
    replaceSelects();
    // hide drop when scrolling or resizing window
    if (window.addEventListener) {
        window.addEventListener("scroll", hideActiveSelectDrop, false);
        window.addEventListener("resize", hideActiveSelectDrop, false);
    }
    else if (window.attachEvent) {
        window.attachEvent("onscroll", hideActiveSelectDrop);
        window.attachEvent("onresize", hideActiveSelectDrop);
    }
}

function refreshCustomForms() {
    // remove prevously created elements
    if(window.inputs) {
        for(var i = 0; i < checkboxes.length; i++) {
            if(checkboxes[i].checked) {checkboxes[i]._ca.className = "checkboxAreaChecked";}
            else {checkboxes[i]._ca.className = "checkboxArea";}
        }
        for(var i = 0; i < radios.length; i++) {
            if(radios[i].checked) {radios[i]._ra.className = "radioAreaChecked";}
            else {radios[i]._ra.className = "radioArea";}
        }
        for(var i = 0; i < selects.length; i++) {
            var newText = document.createElement('div');
            if (selects[i].options[selects[i].selectedIndex].title.indexOf('image') != -1) {
                newText.innerHTML = '<img src="'+selects[i].options[selects[i].selectedIndex].title+'" alt="" />';
                newText.innerHTML += '<span>'+selects[i].options[selects[i].selectedIndex].text+'</span>';
            } else {
                newText.innerHTML = selects[i].options[selects[i].selectedIndex].text;
            }
            document.getElementById("mySelectText"+i).innerHTML = newText.innerHTML;
        }
    }
}

// getting all the required elements
function getElements() {
    // remove prevously created elements
    if(window.inputs) {
        for(var i = 0; i < inputs.length; i++) {
            inputs[i].className = inputs[i].className.replace('outtaHere','');
            if(inputs[i]._ca) inputs[i]._ca.parentNode.removeChild(inputs[i]._ca);
            else if(inputs[i]._ra) inputs[i]._ra.parentNode.removeChild(inputs[i]._ra);
        }
        for(i = 0; i < selects.length; i++) {
            selects[i].replaced = null;
            selects[i].className = selects[i].className.replace('outtaHere','');
            selects[i]._optionsDiv._parent.parentNode.removeChild(selects[i]._optionsDiv._parent);
            selects[i]._optionsDiv.parentNode.removeChild(selects[i]._optionsDiv);
        }
    }

    // reset state
    inputs = new Array();
    selects = new Array();
    labels = new Array();
    radios = new Array();
    radioLabels = new Array();
    checkboxes = new Array();
    checkboxLabels = new Array();
    for (var nf = 0; nf < document.getElementsByTagName("form").length; nf++) {
        if(document.forms[nf].className.indexOf("default") < 0) {
            for(var nfi = 0; nfi < document.forms[nf].getElementsByTagName("input").length; nfi++) {inputs.push(document.forms[nf].getElementsByTagName("input")[nfi]);
            }
            for(var nfl = 0; nfl < document.forms[nf].getElementsByTagName("label").length; nfl++) {labels.push(document.forms[nf].getElementsByTagName("label")[nfl]);}
            for(var nfs = 0; nfs < document.forms[nf].getElementsByTagName("select").length; nfs++) {selects.push(document.forms[nf].getElementsByTagName("select")[nfs]);}
        }
    }
}

// separating all the elements in their respective arrays
function separateElements() {

    var r = 0; var c = 0; var t = 0; var rl = 0; var cl = 0; var tl = 0; var b = 0;
    for (var q = 0; q < inputs.length; q++) {
        if(inputs[q].type == "radio") {
            radios[r] = inputs[q]; ++r;
            for(var w = 0; w < labels.length; w++) {
                if((inputs[q].id) && labels[w].htmlFor == inputs[q].id)
                {
                    radioLabels[rl] = labels[w];
                    ++rl;
                }
            }
        }
        if(inputs[q].type == "checkbox") {
            checkboxes[c] = inputs[q]; ++c;
            for(var w = 0; w < labels.length; w++) {
                if((inputs[q].id) && (labels[w].htmlFor == inputs[q].id))
                {
                    checkboxLabels[cl] = labels[w];
                    ++cl;
                }
            }
        }
    }
}

//replacing radio buttons
function replaceRadios() {


    for (var q = 0; q < radios.length; q++) {

        radios[q].className += " outtaHere";
        var radioArea = document.createElement("div");
        if(radios[q].checked) {
            radioArea.className = "radioAreaChecked";
        }
        else
        {
            radioArea.className = "radioArea";
        }
        radioArea.id = "myRadio" + q;
        radios[q].parentNode.insertBefore(radioArea, radios[q]);
        radios[q]._ra = radioArea;

        radioArea.onclick = new Function('rechangeRadios('+q+')');
        if (radioLabels[q]) {
            if(radios[q].checked) {
                radioLabels[q].className += "radioAreaCheckedLabel";
            }
            radioLabels[q].onclick = new Function('rechangeRadios('+q+')');
        }
    }
    return true;
}

//checking radios
function checkRadios(who) {
    var what = radios[who]._ra;
    for(var q = 0; q < radios.length; q++) {
        if((radios[q]._ra.className == "radioAreaChecked") && (radios[q]._ra.nextSibling.name == radios[who].name))
        {
            radios[q]._ra.className = "radioArea";
        }
    }
    what.className = "radioAreaChecked";
}

//changing radios
function changeRadios(who) {
    if(radios[who].checked) {
        for(var q = 0; q < radios.length; q++) {
            if(radios[q].name == radios[who].name) {
                radios[q].checked = false;
            }
            radios[who].checked = true;
            checkRadios(who);
        }
    }
}

//rechanging radios
function rechangeRadios(who) {
    if(!radios[who].checked) {
        for(var q = 0; q < radios.length; q++) {
            if(radios[q].name == radios[who].name) {
                radios[q].checked = false;
            }
            if(radioLabels[q]) {
                radioLabels[q].className = radioLabels[q].className.replace("radioAreaCheckedLabel","");
            }
        }
        radios[who].checked = true;
        if(radioLabels[who] && radioLabels[who].className.indexOf("radioAreaCheckedLabel") < 0) {
            radioLabels[who].className += " radioAreaCheckedLabel";
        }
        checkRadios(who);

        if(window.$ && window.$.fn) {
            $(radios[who]).trigger('change');
        }
    }
}

//replacing checkboxes
function replaceCheckboxes() {
  if (replaceCheckBoxes == 0)
    return;
    for (var q = 0; q < checkboxes.length; q++) {
        // checkboxes[q].className += " outtaHere";
        var checkboxArea = document.createElement("div");
        if(checkboxes[q].checked) {
            checkboxArea.className = "checkboxAreaChecked";
            if(checkboxLabels[q]) {
                checkboxLabels[q].className += " checkboxAreaCheckedLabel"
            }
        }
        else {
            checkboxArea.className = "checkboxArea";
        }
        checkboxArea.id = "myCheckbox" + q;
        checkboxes[q].parentNode.insertBefore(checkboxArea, checkboxes[q]);
        checkboxes[q]._ca = checkboxArea;
        checkboxArea.onclick = new Function('rechangeCheckboxes('+q+')');
        if (checkboxLabels[q]) {
            checkboxLabels[q].onclick = new Function('changeCheckboxes('+q+')');
        }
        checkboxes[q].onkeydown = checkEvent;
    }
    return true;
}

//checking checkboxes
function checkCheckboxes(who, action) {
    var what = checkboxes[who]._ca;
    if(action == true) {
        what.className = "checkboxAreaChecked";
        what.checked = true;
    }
    if(action == false) {
        what.className = "checkboxArea";
        what.checked = false;
    }
    if(checkboxLabels[who]) {
        if(checkboxes[who].checked) {
            if(checkboxLabels[who].className.indexOf("checkboxAreaCheckedLabel") < 0) {
                checkboxLabels[who].className += " checkboxAreaCheckedLabel";
            }
        } else {
            checkboxLabels[who].className = checkboxLabels[who].className.replace("checkboxAreaCheckedLabel", "");
        }
    }

}

//changing checkboxes
function changeCheckboxes(who) {
    setTimeout(function(){
        if(checkboxes[who].checked) {
            checkCheckboxes(who, true);
        } else {
            checkCheckboxes(who, false);
        }
    },10);
}
4
  • 1
    Let me guess, someone's code isn't attaching events through addEventListener/attachEvent Commented Nov 19, 2012 at 19:05
  • Do you have any code you could post? The question is a little vague to be able to provide any decent answer. Commented Nov 19, 2012 at 19:06
  • You cannot rely on the order of events, they are not guaranteed. Also question without are less likely to get answers, don't keep it a secret Commented Nov 19, 2012 at 19:07
  • I have edited some part of the code : the js file construct the checkbox and the handles the toggling of pair of checkboxes Commented Nov 19, 2012 at 19:15

1 Answer 1

2

Please see the jquery stopImmediatePropagation() function here: http://docs.jquery.com/Types/Event#event.stopImmediatePropagation.28.29

I believe this will achieve what you are looking to do.

Edit: With more detail I may be able to provide a better answer.

Edit 2: It appears that there is no guarantee'd order of execution in Javascript, so inline code may not run before dynamically added code. In addition this particular function may only work if the other handlers are added using jQuery.

Edit 3:

A quick and dirty fix would be to add

<script type="text/javascript">var executeHandlers = false;</script>

to the top of the one html file.

Then edit the javascript file such that the event handlers have

if (executeHandlers !== false) { ... do the logic you normally would here ... }

as the body

This would add one line to the html file that needs to be treated differently, and should not impact the execution on the other pages.

Please note that this is a quick and dirty fix, and there are better ways to do this. Working with the constraints of an existing .js file, and only one file that needs to be treated differently, this seems to be the fastest / easiest way to the desired outcome, not necessarily the best.

Sign up to request clarification or add additional context in comments.

18 Comments

Only if there's a node deeper in the hierarchy than the node the handler was originally on. Otherwiser, there's no guarantee your handler would be called before their handler. OP also didn't ask for jQuery and this assumes every one installing handlers did it with jQuery
@Juan: good call, however I believe that inline javascript should be higher in the hierarchy than script added dynamically. Based upon his description of the problem, his code is directly inline with the page. Please correct me if I am wrong, and I will update the answer.
There is no guarantee that inline script will run first. Even if it were, it would not stop other handlers on the same node unless they were also set with jQuery
in fact, the myjs file is first called when the click event is triggered
@newben What is the behavior that you are looking to have happen? (In what case should the js file behavior fire, in what case shouldn't it, and what should it do instead)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.