4

I have the following code that is working fine in jsfiddle - http://jsfiddle.net/darkajax/FHZBy/

I've transferred the code in to the page I need to use the code in and assigned the correct ID numbers to the functions, this is the page where it should be working:

http://mtpassemblies.com/cs-cart/index.php?dispatch=products.view&product_id=29821

The part number box should be being filled out as the user makes a selection across the options, this isn't happening on the live version and I don't appear to be getting any error messages. As I'm getting no eror messages I'm not sure where I should be starting to look to see where the problem is coming from.

Further to my original message it seems CS Cart is built on the Smarty framework, I'm not sure if this has a bearing on the problem?

Here's the jQuery from the site:

<script type="text/javascript">// <![CDATA[
$(function() {
var sku1 = sku2 = sku3 = sku4 = sku5 = sku6 = length = '';
$("#opt_29821_746").change(function(){

    switch($(this).val()){
        case "3134":
             sku1 = 'TB';
        break;
        case "3135":
             sku1 = 'LT';
        break;
        case "3154":
            sku1 = 'LTR';
        break;
        case "3136":
             sku1 = 'BO';
        break;
        case "3138":
             sku1 = 'MC';
        break;
        case "3139":
             sku1 = 'NC';
        break;
        case "3183":
              sku1 = 'STA';
        break;
    }
    $('#option_29821_798').val(sku1+sku2+sku3+sku4+sku5+sku6+length);
});
$("#opt_29821_742").change(function(){
    switch($(this).val()){
        case "3111":
              sku2 = 'LC';
        break;
        case "3110":
             sku2 ='LCA';
        break;
        case "3112":
             sku2 ='E2000';
        break;
        case "3113":
             sku2 ='E2A';
        break;
        case "3114":
             sku2 ='FC';
        break;
        case "3115":
             sku2 ='FCA';
        break;
        case "3116":
             sku2 ='ST';
        break;
        case "3117":
             sku2 ='SC';
        break;
        case "3118":
             sku2 ='SCA';
        break;
    }
    $('#option_29821_798').val(sku1+sku2+sku3+sku4+sku5+sku6+length);
});
$("#opt_29821_744").change(function(){
    switch($(this).val()){
        case "3175":
              sku3 = '2';
        break;
        case "3121":
             sku3 ='4';
        break;
        case "3122":
             sku3 ='6';
        break;
        case "3123":
             sku3 ='8';
        break;
        case "3124":
             sku3 ='12';
        break;
        case "3125":
             sku3 ='16';
        break;
        case "3126":
             sku3 ='24';
        break;
        case "3176":
             sku3 ='48';
        break;
    }
    $('#option_29821_798').val(sku1+sku2+sku3+sku4+sku5+sku6+length);
});

$("#opt_29821_745").change(function(){
    switch($(this).val()){
        case "3127":
              sku4 = 'OS12';
        break;
        case "3182":
             sku4 ='G657A1';
        break;
        case "3128":
             sku4 ='OM1';
        break;
        case "3129":
             sku4 ='OM2';
        break;
        case "3130":
             sku4 ='OM3';
        break;
        case "3131":
             sku4 ='OM4';
        break;
    }
    $('#option_29821_798').val(sku1+sku2+sku3+sku4+sku5+sku6+length);
});

$("#opt_29821_748").change(function(){
    switch($(this).val()){
        case "3142":
              sku5 = 'LC';
        break;
        case "3143":
             sku5 ='LCA';
        break;
        case "3144":
             sku5 ='E2000';
        break;
        case "3145":
             sku5 ='E2A';
        break;
        case "3146":
             sku5 ='FC';
        break;
        case "3147":
             sku5 ='FCA';
        break;
        case "3148":
             sku5 ='ST';
        break;
        case "3149":
             sku5 ='SC';
        break;
        case "3150":
             sku5 ='SCA';
        break;
    }
    $('#option_29821_798').val(sku1+sku2+sku3+sku4+sku5+sku6+length);
});

$("#opt_29821_749").change(function(){
    switch($(this).val()){
        case "3151":
              sku5 = 'LZSH';
        break;
        case "3177":
             sku5 ='PE';
        break;
    }
    $('#option_29821_798').val(sku1+sku2+sku3+sku4+sku5+sku6+length);
});

$('#opt_29821_753').change(function(){
    length = $(this).val();
    $('#option_29821_798').val(sku1+sku2+sku3+sku4+sku5+sku6+length);
});
});
// ]]></script>

UPDATE

After further investigation and talking with various people it would seem the problem would be caused by the inline onchange event that is built in to CS Cart clashing with the jQuery that I have written.

So the question seems to be more is it possible to get the code working alongside the functions that are being fired by the inline coding?

Vince P
  • 1,781
  • 7
  • 29
  • 67
  • On your website seems to work ? What are you expecting ? that the images changes or a hidden input ? – user1040899 Mar 26 '12 at 08:30
  • leave out the `// <![CDATA[` junk, thats a relic of the 90s and not needed anymore. – Christoph Mar 26 '12 at 09:42
  • I would leave it out but it is a function that is added in automatically via CS Cart – Vince P Mar 26 '12 at 10:36
  • As for what I expect to happen - "The part number box should be being filled out as the user makes a selection across the options," (as in the jsfiddle example) – Vince P Mar 26 '12 at 10:43

4 Answers4

4

The .change() event would get fired only for static content. In your case you should use jQuery's .on() event like:

 $("#opt_29821_745").on('change', function() {
 ....
Codrin Eugeniu
  • 1,365
  • 8
  • 14
  • I receive the error `Uncaught TypeError: Object [object Object] has no method 'on'` by adding the `.on` event – Vince P Mar 26 '12 at 10:34
  • 1
    Yes, that's because you are using jQuery 1.5.2 which doesn't support the `.on` method. Use `.live('change', function() { ... }` instead or upgrade your jQuery if it is an option. – Codrin Eugeniu Mar 26 '12 at 11:16
  • I have `` in my header - Does that not fetch the latest version of jQuery - in this case 1.7.2 ? – Vince P Mar 26 '12 at 11:20
  • 1
    Yes you have that, but on line 34 when I view-source you have ` – Codrin Eugeniu Mar 26 '12 at 11:22
  • I've tracked down the offending jquery on line 34 and removed, not getting the object error now but the script is still not working (no errors messages either to point out where to look) – Vince P Mar 26 '12 at 13:08
  • The select is named `option_29821_754` yet in jQuery you bind events to `opt_29821_745` which doesn't exist. – Codrin Eugeniu Mar 26 '12 at 13:15
  • All the select boxes (with the exception of one) are used to build up the product numbers, #option_29821_798 is the text box where it should be being added too all the others reference the different select boxes – Vince P Mar 26 '12 at 13:36
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/9322/discussion-between-codrin-eugeniu-and-vince-pettit) – Codrin Eugeniu Mar 26 '12 at 13:42
1

Try add this before your javascript code.

jQuery.noConflict();

Or wrap your jquery code with this:

jQuery(document).ready(function($){
   // your code here
});

Or replace all $ with jQuery

Rafał Wójcik
  • 591
  • 3
  • 13
  • wrapping the dollar sign works too (function($){ $(document).ready(function(){}; }(jQuery)); – rroche Apr 03 '12 at 23:23
0

i had a similar problem - a textbox that was connected to a javascript date picker. i wanted to use the onchange event to compare the date picked with the date on another field (it was a start date / end date kind of thing and i wanted to make sure start date was before end date - switching them if otherwise)

Only the onchange wouldn't fire. The solution is to use both the onchange and onproperty change events.

on the control i have:

<input id='mytext' name='mytext' type='text' onchange='doSomething();' onpropertychange='isDoSomething(event);' />

my isDoSomething looks like:

function isDoSomething(eventobj) {
if ("propertyName" in eventobj) { // Older browsers might not have this property
    if (eventobj.propertyName == 'value') // Check if the property that was changed was the value
        dosSomething();
}
else // on older browsers can't  check what property was changed so just do your thing
    doSomething();
}

This is what ended up working for me - hope it helps

using your example: not only set .change function but also .propertychange

537mfb
  • 1,374
  • 1
  • 16
  • 32
0

I think it's because you're setting the events on the <div/> rather than the <select/>.

$("#opt_29821_746").live('change', function(){

should be

$("#option_29821_746").live('change', function(){

Additionally, you have a problem that your AJAX callback resets all the fields, because it simply sets the HTML returned once a field was filled in, so even if the code works, it'd be reset each time. Consider returning a simple list (JSON would be my choice) and setting up the options on the client side rather than rendering on the server-side. Alternatively, if you insist using AJAX as-is, consider postponing the AJAX request until you have filled in the field (fill in field first, then AJAX request). I assume it's the inline onclick which does the AJAX call. Since this is ugly as it is, I won't be afraid to make it uglier - you can save the onclick aside as jQuery data and put it next in line:

$('select[onchange]').each(function(i, el) { 
    el=$(el); 
    el.data('onchange', el.attr('onchange'));   // save previous event code aside
    el.attr("onchange",null);  // delete previous event code
    el.change(function() { 
        // you can actually add more code here to invoke before regular 'onchange' event
        var target=$(this);
        if (target.data("onchange")) {
            (new Function(target.data("onchange"))).apply(this, arguments);  }
    });
});

However, you'll need to do this after each AJAX call as your elements are being replaced. You might be able to use jQuery live() here as well, but that's too ugly for me to write up.

As to the first point, I think using named variables would have saved you the trouble. For brevity, here's how I recommend you go:

(function() { 

    // this isn't really ids but css selector; but for lack of a better name
    var el_id_map = {
        sku1: "#option_29821_746",
        sku2: "#option_29821_754",
        length: "#option_29821_753"
    };
    var el_ids = []; var sku_id="#option_29821_798";
    var sku1_map = { "3134": "TB", "3135": "LT" },
        sku2_map = { "3111": "LC", "3110": "LCA" };

    // map ids to array
    for (var key in el_id_map) { 
        if (el_id_map.hasOwnProperty(key)) el_ids.push(el_id_map[key]); 
    }

    $(el_ids.join(",")).live("change", function(){

        $(sku_id).val([
            sku1_map[$(el_id_map["sku1"]).val()],
            sku2_map[$(el_id_map["sku2"]).val()],
            $(el_id_map["length"]).val()].join(""));
    });

})()

You can place the code inside the live() handler here in the first code I made where I placed the comment add more code here etc. But remember then you have to make sure the code runs after each AJAX request to update the event handlers.

Again, I would just return JSON from the server.

Edit since I already went to the effort I decided to make up a complete, working example. Should work as-is on your page, but you need to debug it :)

(function() {
    // you might want to generate the list using the same
    // server-side data that generates the elements
    var el_id_map = {
        sku1: "#option_29821_746",
        sku2: "#option_29821_754",
        // put rest of skus here
        length: "#option_29821_753"
    };
    var sku_id = "#option_29821_798";
    var sku1_map = { "3134": "TB", "3135": "LT" },
        sku2_map = { "3111": "LC", "3110": "LCA" };
    // put rest of skus here

    var el_ids = []; 
    for (var key in el_id_map) { 
        if (el_id_map.hasOwnProperty(key)) {
            el_ids.push(el_id_map[key]); 
        }
    }
    function change_handler() {
        $(sku_id).val([
            sku1_map[$(el_id_map["sku1"]).val()],
            sku2_map[$(el_id_map["sku2"]).val()],
            $(el_id_map["length"]).val()].join(""));
    }
    function hijack_changes(change_handler) {
        $(el_ids).each(function(i, el) { 
            el = $(el); 
            el.data('onchange', el.attr('onchange')); // save inline event
            el.attr("onchange", null); // remove inline event
            el.change(function() { 
                change_handler.apply(this, arguments);

                var target=$(this);  
                if (target.data("onchange")) {
                    var handler = new Function(target.data("onchange"));
                    handler.apply(this, arguments);  
                }
            }); 
        });
    }

    function hijack_ajax() {
        var old_fn_post_process_form_files = window.fn_post_process_form_files;
        window.fn_post_process_form_files = function() {
            hijack_changes(change_handler);
            old_fn_post_process_form_files.apply(this, arguments);
        }
    }
    hijack_ajax();
    hijack_changes(change_handler);

})();
Yuval
  • 3,207
  • 32
  • 45