I am trying to create a button in Javascript, that when clicked will send an AJAX Request to some PHP Code.
I have already setup 3 buttons that do the same thing and they are all working fine.
The most bizarre thing is that if I call the method directly it runs fine.
The code for the button:
<button id="toggle-button">Toggle</button>
The Javascript:
var toggleButton = document.getElementById('toggle-button');
...
function init()
{
...
toggleButton.onClick = handleToggleClick;
...
}
function handleToggleClick(event)
{
alert("Sending Request");
var admin_url = "http://localhost/wp-admin/admin-ajax.php";
var data = {
action : 'toggle',
}
$.post(admin_url, data, function(resp) {
alert(resp);
});
}
I have called the following in the Chrome Developer Tools Console:
handleToggleClick(null); // The request is sent
autoScheduleButton.onClick(); // The request is sent
autoScheduleButton.onClick; //It prints out the function
autoScheduleButton; //It displays the HTML of the button.
As I mentioned before there are 3 other buttons which do practically the same thing and work fine, so I really can't see why this isn't working.
Hopefully this is just something really obvious i missed.
EDIT:
Originally I made an error while anonymising the code, the code above is now correct in the init method.
Previous code:
function init()
{
...
toggleButton.onClick() = handleToggleClick;
...
}
In init function you have code like toggleButton.onClick() = handleToggleClick;. This means that you assign to the result of the onClick() function to the handleToggleClick.
You need to assign to onClick and not call it.
Try this instead toggleButton.onClick = handleToggleClick;
function init()
{
...
toggleButton.onClick = handleToggleClick;
...
}
The code toggleButton.onClick() = handleToggleClick; in the init function is not a right assignment. It actually means You are calling onClick function on toggleButton and then assigning to the result handleToggleClick.
change it ti toggleButton.onClick= handleToggleClick meaning you are listening to a click event on toggleButton and then calling function handleToggleClick
Related
I have a function which takes on some parameters and forwards it to print method.
getPrintAction: function () {
return new Ext.Action({
scope : this,
handler : function () {
var printRenderer = new BaseRenderer;
var data = [...];
var printData = [...];
printRenderer.print(printData);
}
});
}
While this works perfectly, when I add an Ajax request, the whole thing breaks.
getPrintAction: function () {
return new Ext.Action({
scope : this,
handler : function () {
var printRenderer = new BaseRenderer;
var data = [...];
Ext.Ajax.request({
scope : this,
params : {...},
success: function (result) {
var printData = [...];
printRenderer.print(printData);
},
failure: callback()
});
}
});
}
I tried to put breakpoints as I thought new printData may be causing errors. But that is not the case, printData parses result from callback and the result is fine. I am getting the right array to forward to print() method.
Ultimately it fails here:
print: function (component) {
var win = window.open('','print');
win.document.write(component); <--- HERE
win.document.close();
}
Where win variable is set to null if I am going there from request.
I suppose this may be a scope issue but I have no idea how to debug it...
Browsers usually blocks asynchronous calls to window.open. You will see at the right of the URL bar a notification about this block.
That is to prevent spam. You now hate it but trust me that you have been saved of spam because of this a lot of times, so don't hate it.
Such methods needs to be called at the very moment of the click event. If you defer a call to window.open in the future, although the callback is created at the moment of the click, it will break.
What you can do is to add another popup that the user will need to click just after the Ajax request. Something like showing a "loading" popup that will change to a "Click here to print" when the load ends.
the code below is used to change the onclick event when pressed, however it only alters the function of the parameter, which it simply will not do.
function addWhere(nameID)
{
document.getElementById('addWhereButton').setAttribute("onclick",addWhere(nameID++), false);
document.getElementById('addWhereButton').onclick = function () {addWhere(nameID++)};
}
neither code works and no one else seems to have asked this specific questions before.
Thanks
EDIT
Further testing shows something complete bizarre, a bit of code to display the nameID like so
document.getElementById('Testing').innerHTML = nameID++;
shows that nameID is actually getting incremented, but the number passed by the onclick never changes.
Like:
function addWhere(nameID) {
console.log(nameID);
};
let nameID = 1;
document.getElementById('addWhereButton').onclick = function () {addWhere(nameID++)};
<button id="addWhereButton">click to increment nameID</button>
A few weeks ago I was painfully able to dynamically add buttons to an HTML DOM object that has its own .on('click'.. handler, and use e.stopPropgation to stop these new child elements from firing the event.
The weird thing I did was call a function without any parenthesis. I have no idea why I did this or why it works, or why it does not work when I do attach parenthesis. I want to know if I am doing something by fluke and not design (and now I will add comments to it).
It goes as such:
//Container is the parent element
// var buttons stores the buttons with class 'buttons'
$('.container').on('click', function(){
$(buttons).appendTo($(this)).fadeIn(500).find('.buttons').click(tableButton);
});
function tableButton(e){
e.stopPropagation();
//do stuff
}
I can't figure out why I wrote the call to tableButton with no arguements or why it works perfectly. I tried to change the syntax to
.find('.buttons').on('click', function(e){
tableButton(e);
});
but then it no longer works.
Any help appreciated!
It works because you're passing a function to the click handler rather than calling the function yourself (the ()) An example of that:
var testFunction = function(msg) {
alert(msg);
}
var functionCaller = function(functionToCall) {
functionToCall('hello!');
}
functionCaller(testFunction);
functionCaller passes the message argument to testFunction(), but we only pass testFunction to functionCaller (without arguments)
For the part which doesn't work, isn't the function name tableButton() instead of tableButtons()?
See http://jsfiddle.net/g2PAn/
You don't actually call it, you just declare it and the arguments it accepts. The click callback is called with an argument indeed, but not by you.
The problem probably comes from the fact that jQuery calls your function with the element clicked bound as this, you could call table button like this:
.find('.buttons').on('click', function(e){
tableButton.call(this, e);
});
How can I return a parent function from a child function on click? Here's an example code:
function returnFunction() {
var output = false;
$('a').click(function() {
output = true;
});
return output;
}
var result = returnFunction();
The result will always be false since the click hasn't happened at the time the code is being run. How could I make this work though?
My intention is to call pop-up dialogs, and I'd like to have all the logic inside one function that can easily be loaded - including the click events of a Confirm dialog box.
Elsewhere in scripts I'd be calling it this way for example:
// Menu click triggers the dialog
$('a').click(function(e) {
// The function displays the dialog and returns the click events of the dialog
var result = returnFunction();
// If result was false, we'll prevent the menu access, for example
if (!result) {
e.preventDefault();
}
});
I'm aware of the jQuery UI dialog plugin. But I'd like to achieve this without it for now.
Thanks.
An over-simplification of it is:
Everything stops (including scrolling and clicking on hyperlinks) while executing javascript. This means you cannot "pause" the script until someone clicks on a link.
The typical way of solving this is a callback function:
function my_callback(some, arguments) {
// you can do whatever in here: an ajax load, set a global variable, change some of the page, ...
console.log(some, arguments);
alert(some + " " + arguments);
}
function returnFunction(callback, param) {
var output = false;
$('a').click(function() {
callback(param, "world");
});
}
returnFunction(my_callback, "hello");
demo at http://jsfiddle.net/UnBj5/
EDIT:
I did mention global variables because they are an option, but they are typically bad style. Try to use other means if possible.
If you want more help with it, provide more details of what you are trying to do.
Try using parameters instead. Send a parameter to a function that shows your alert boxes, show a different pop-up alert depending on the parameter, what you are trying to do won't work because its basically a chicken-egg problem.
I've made a class that, when initialized, starts to download a JSON file.
However, the downloading runs asynchronously.
So after I declare it I start working with it, but it fails because it hasn't loaded the file yet.
I could turn async off, but is there another way without freezing the browser?
I'm currently working around it with a setTimeout option, but that seems like an ugly hack.
var d;
$(document).ready(function() {
d = new Duk('element');
d.getBlueprint('hud.json');
setTimeout(start, '2000');
});
function start(){
test = new d.Dialog(d.blueprint.screens.test);
test.draw();
}
You have to attach event handler to the object load completion event. The library you are working with must supply this event. I don't know what a Duk is, or what getBlueprint() does, but you should check the documentation for whatever that class and method is, and see if there is an oncomplete callback. If there is, you'd do something like this:
$(document).ready(function() {
d = new Duk('element');
d.getBlueprint('hud.json', {
onComplete: function() {
test = new d.Dialog(d.blueprint.screens.test);
test.draw();
}
});
});
Obviously, I just made that up. I don't know if your library has an onComplete method defined like this, but I hope you see what I mean. Without knowing more about the library you are using, I can't give a better example.
Timeouts are not the way to solve this problem.
You want to set up a callback function alongside the request so that the object handling the request knows what to do when the response comes in.
It is unclear from your code what framework you're using (I can't make any sense of getBlueprint, which seems to be the call that initializes the remote request), so if you could provide more information on this, we can provide more customized help.
You want your getBlueprint() method to be able to accept a callback which is run when the file is finished downloading.
function getBlueprint(file, callback)
{
// do whatever to get the file
// ...
// trigger the callback
callback();
}
$(document).ready(function() {
var d;
function start(){
test = new d.Dialog(d.blueprint.screens.test);
test.draw();
}
d = new Duk('element');
d.getBlueprint('hud.json', start);
setTimeout(start, '2000');
});
I agree that a callback function is the proper way. If this is code you cannot modify, you can do something like this, but seriously, use a callback!
function wait_for_load(expr, func)
{
var interval = window.setInterval(function()
{
if(eval(expr))
{
window.clearInterval(interval);
func();
}
}, 20);
}
var d;
$(document).ready(function() {
d = new Duk('element');
d.getBlueprint('hud.json');
wait_for_load('d.blueprint', start);
});