简体   繁体   中英

Javascript onchange(this.value, that.value) not working on ipad

I have this code which works perfectly on PC but it doesnt work on my iPad ( i assume it doesnt work on any mobile either). I have tried with Safari and with Chrome without any luck.

HTML :

<input name="Service" type="radio" value="110" onchange="update_cart(this.value, Service2.value )" />
<input name="Service" type="radio" value="111" onchange="update_cart(this.value, Service2.value )" />
<input name="Service2" type="radio" value="112" onchange="update_cart(Service.value, this.value)" />
<input name="Service2" type="radio" value="113" onchange="update_cart(Service.value, this.value)" />

JavaScript :

function update_cart(radio1,radio2) {
    if (Service == "" || ID_Service == "") {
        document.getElementById("Cart").innerHTML = "";
        return;
    }
    if (window.XMLHttpRequest) {
        // code for IE7+, Firefox, Chrome, Opera, Safari
        update = new XMLHttpRequest();
    } else { // code for IE6, IE5
        update = new ActiveXObject("Microsoft.XMLHTTP");
    }
    update.onreadystatechange = function() {
        if (update.readyState == 4 && update.status == 200) {
            document.getElementById("Cart").innerHTML = update.responseText;//fills Cart div with result
        }
    }
    update.open("GET", "/new/update_cart.php?radio1=" + radio1 + "&radio2=" + radio2, true);
    update.send();
}

I know that the problem is here because the function update_cart is just receiving the variable that has the "this.value" but not the other one, eg: When click/tap on the first radio the function receives (110,undefined) and vice versa for the second radio (undefined,112)

My questions are: am I doing something wrong here? isn't this supposed to work on mobile? Any workaround for this?

EDIT: now we have 4 options, and the idea is to be able to update the cart with the new item that you checked and everytime you click on another radio it should update the cart.

Never use inline JS (like onchange in your HTML), unless you're using a framework, like Angular, that make sense of it. Otherwise, it's limited, ugly, and potentially buggy.

You could make this lighter and cleaner by using a library or framework. Something like Ractive, Angular, React, etc help quite a bit.

See code comments for explanation.

 // get element references var serviceElems = document.querySelectorAll('[name="Service"]'); var service2Elems = document.querySelectorAll('[name="Service2"]'); // loop through both sets of references and attach "change" listeners [serviceElems, service2Elems].forEach(function(set) { [].forEach.call(set, function(elem) { elem.addEventListener('change', myFn); }); }); // this is fired when any of the elements are clicked function myFn() { // loop over the sets of elements, mapping values back to `vals` var vals = [serviceElems, service2Elems].map(function(set) { // find the checked element (if any) from this set var checkedElem = [].find.call(set, function(elem) { return elem.checked; }); // if one was checked, return its value (maps to vals) if (checkedElem) { return checkedElem.value; } }); updateCart(vals[0], vals[1]); } var result = document.getElementById('result'); function updateCart(radio1, radio2) { result.textContent = 'Service: '+radio1+' Service2: '+radio2; } // SHIM FOR ES6 [].find if (!Array.prototype.find) { Array.prototype.find = function(predicate) { if (this == null) { throw new TypeError('Array.prototype.find called on null or undefined'); } if (typeof predicate !== 'function') { throw new TypeError('predicate must be a function'); } var list = Object(this); var length = list.length >>> 0; var thisArg = arguments[1]; var value; for (var i = 0; i < length; i++) { value = list[i]; if (predicate.call(thisArg, value, i, list)) { return value; } } return undefined; }; } 
 <h3>Set 1</h3> <label>110</label> <input name="Service" type="radio" value="110"> <label>111</label> <input name="Service" type="radio" value="111"> <h3>Set 2</h3> <label>112</label> <input name="Service2" type="radio" value="112"> <label>113</label> <input name="Service2" type="radio" value="113"> <h3>Result</h3> <div id="result"></div> 

Check this out in AngularJS. With Angular, you're encouraged to have logic in your HTML. This doesn't require any direct js except your function call updateCart .

 angular.module('myApp', []) .controller('myCtrl', function($scope) { $scope.updateCart = function(radios) { console.log.apply(console, radios); }; }) ; 
 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <div ng-app="myApp" ng-controller="myCtrl" ng-init="sets = [[110, 111], [112, 113]]; models = []"> <div ng-repeat="set in sets"> <h3>Set {{$index+1}}</h3> <div ng-repeat="item in set"> <label>{{item}}</label> <input name="Service" type="radio" ng-value="item" ng-model="models[$parent.$index]" ng-change="updateCart(models)"> </div> </div> <div id="result"> <p ng-repeat="model in models">Model {{$index+1}}: {{model}}</p> </div> </div> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM