XMLHttpRequest with onclick

I’ve got this far. How do I get the var type into the xmlhttp.onreadystatechange=function() so I can send it to a php script?
Code so far:

<head>
<script type="text/javascript">
function display(el) {
  if (el.innerHTML == 'Send to Cart') {
        el.innerHTML = 'Sent to Cart';
        var type="sent";
  } else {
        el.innerHTML = 'Send to Cart';
        var type="send";
  }
  if (window.XMLHttpRequest) { // code for IE7+, Firefox, Chrome, Opera, Safari
        xmlhttp=new XMLHttpRequest();
  } else { // code for IE6, IE5
        xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
  xmlhttp.onreadystatechange=function() {
        if (xmlhttp.readyState==4 && xmlhttp.status==200) {
        ??????????
        }
  }
  xmlhttp.open("GET","livesearch.php?q="+str,true);
  xmlhttp.send();
}
</script>
</head>
<body>
<button  type="button" onclick="display(this)">Show Date</button>
</body>
</html>

You can use a closure for that, where you pass the variable to a function, and that function returns an inner function. That returned function retains knowledge of the variables from its parent.


function stateChangeHandler(type) {
    return function () {
        if (xmlhttp.readyState==4 && xmlhttp.status==200) {
            // The returned inner function retains knowledge of the variables from its parent, including the type variable
        }
    };
}
...
xmlhttp.onreadystatechange = stateChangeHandler(type);

Thanks. What does " return function () {" mean? This is what I worked out:

<?php
$name = $_GET['name'];
echo $name;
?>
<head>
<script type="text/javascript">
function display(el) {
  var type="";
  if (el.innerHTML == 'Send to Cart') {
    el.innerHTML = 'Sent to Cart';
	type="sent";
  } else {
    el.innerHTML = 'Send to Cart';
	type="send";
  }
  if (window.XMLHttpRequest) { // code for IE7+, Firefox, Chrome, Opera, Safari
    xmlhttp=new XMLHttpRequest();
  } else { // code for IE6, IE5
    xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
  xmlhttp.onreadystatechange=function() {

	if (xmlhttp.readyState==4 && xmlhttp.status==200) {
	 alert(xmlhttp.responseText);
    }
  }
  console.log(el.name);
  xmlhttp.open("GET","test99.php?name="+el.name,true);
  xmlhttp.send();
}
</script>
</head>
<body>
<button  name="jasmine" type="button" onclick="display(this)">Show Date</button>

</body>
</html>

That’s just a way of returning a function, so that anything calling the outer function ends up having returned to it a function that can be used for other things.

do you mean outside the scope of its wrapper function?

That is correct. The returned function also retains with it all of the environment information from that wrapper function.


function foo () {
    var privateVariable = 'some value';
    return function () {
        alert(privateVariable);
    };
}

var bar = foo();

bar();

bar now refers to that inner function, and even though that private variable was local to the outer function, the returned function has a copy of the environment from the outer function.

This also means that function parameters passed to the outer function are retained by the inner function too, so you can pass to the outer function parameters that need to be retained, and the inner function, even though it uses no parameters (or may have a completly different set of parameters), retains the environment information from its parent.


function foo (message) {
    return function () {
        alert(message);
    };
}

var bar = foo('something to say here');

bar();

It’s that last statement that is the main benefit here. You end up with a function that can be assigned to different things, which retains the information from its parent that was provided earlier.

What is the significance of the semicolons after the curly brackets?

Ahh, good catch. I started those as a function statement but then changed them to a function declaration for the sake of simplicity, forgetting to remove the ending semicolon. That shoudn’t be there when using a function declaration. (now fixed)

You do though use a semicolon when defining a function as a function statement.

Here are two examples that demonstrate the same function being defined using each of those methods


function foo() {
    ...
}


var foo = function () {
    ...
};

Then this is correct?:

<head>
<html>
<head>
<script type="text/javascript">
function foo (message) {
  return function () {
    alert(message);
  }
}
var bar = foo('something to say here');
bar();
</script>
</head>
<body>
</body>
</html>

Not quite. JavaScript will use Automatic Semicolon Insertion (ASI) to add a semicolon to the end of the return statement, which is the first closing brace that you have there.

Also to be completely proper, there should be no space between the name of the function and the parenthesis that specify its properties, and since alert is being accessed as a global object, windows.alert is the most proper way of specifying that.

And since we’re attempting to do things the proper way, in light of this it’s time to start using use strict mode article, we can also use “use strict” to tell the interpreter that we want to keep away from using bad parts of the language.

So the most correct way of writing that is:


function foo(message) {
    "use strict";
    return function () {
        window.alert(message);
    };
}
var bar = foo('something to say here');
bar();

www.jslint.com can be used to help you find and fix such issues (turn on the “assume a browser” option though), so that you can then become aware of them and apply such techniques to the rest of your code.

With “use strict” you should not apply it outside of a function, for that then forces it to be applied to all of the scripting code of the page, which can also include scripts from external sources such as ads and other parts.

So the best way to use “use strict” is from a top-level function. Your code for example could be contained within an anonymous closure, which helps to sandbox your code and prevent it from affecting the global namespace.

With the above code, the global namespace will have two new variables added to it, foo and bar. This could cause trouble if some other script also defines those variables, and you try to access them later on.

You can protect yourself from such troubles by wrapping your code in a self-executing anonymous closure.


(function () {
    "use strict";
    function foo(message) {
        return function () {
            window.alert(message);
        };
    }
    var bar = foo('something to say here');
    bar();
}());

Doing things that way now makes the functions local to the anonymous closure, removing them from the global namespace and potential issues thereof.

You may also see code place the function parenthesis outside of the enclosing parenthesis.


(function () {
    ...
})();

That still works, but the problem that now exists is a matter of semantics. The () are executing the enclosing parenthesis, whereas in all other situations the () are used to invoke the function itself. Placing them inside of the enclosing parenthesis connects them to the function itself, which is more semantically correct than if they are outside and separated from it. Some have come to give a derogatory terms to the “outside of the parenthesis” example as looking like dogs balls, because they are hanging off the very end of things.

If you need to access anything inside of the anonymous function from an external position, you can assign the anonymous function to a single global variable that’s unique to yourself, and return anything that you want to be publically accessible.


window.NICHE = (function () {
    "use strict";
    function foo(message) {
        return function () {
            window.alert(message);
        };
    }
    var bar = foo('something to say here');
    return {
        bar: bar,
        otherStuff: 'can be made available too'
    };
}());

// later on
window.NICHE.bar();

That’s about the safest way to treat things. The global namespace is similar to public toilet facilities - you should keep your exposure to it to as much of a minimum as is practical.

Excellent post! Thank-you very much for making this an excellent topic. Is there a way to download this topic other than copy/paste?

There did used to be a way to view a single post, but with the forum upgrade that feature no longer exists.

So aside from that, a potential solution may be to “reply with quote” and then go to preview. That way you can then save that previewed page.