I have a method that calls another method (on ajax load, but that's irrelevant for this question). I'd like to pass parameters to this method. How is this possible?
The below page should scroll to id 25 on button click (the scrollable area is dynamically added in codebehind. this is just an example of what I'm attempting to accomplish)
JS
<%# Page Language="C#" Inherits="APTEIT.scrolltest" %>
<html>
<head>
</head>
<body>
<script type="text/javascript">
function callHandler(handler) {
handler();
}
function scroll(id) {
alert("scrolling");
$("#divy").scrollTop($("#"+id).position().top);
}
</script>
<input type="button" value="scroll" onclick='var scroll={param1: "25"};callHandler(scroll)' />
</body>
</html>
You don't seem to pass the parameter into the handler in the callHandler method - instead, you try to invoke the scroll parameter (which is var scroll={param1: "25"}) as a function.
You use the same name scroll both for a config object and a function name. Please use different names :) Moreover, your declared and used function signatures do not agree. The scroll function accepts a string id while you are trying to pass in an object instead.
Unless I misunderstood, if handler is a function then pass arguments to it like any normal scenario.
function callHandler(handler){
var passme = "test";
handler(passme);
}
Update 1
I think what you might be able to do in this instance is the use the this keyword in the context of the input element. What this will ultimately do in your instance is replace id with this. This will also remove the additional select. Try this:
function callHandler(handler)
{
handler();
}
function scroll()
{
$("#divy").scrollTop($(this).position().top);
}
this might not work, as I'm not sure if the context will be that of input, or callHandler, give it a go! :)
Original
You should just be able to pass the parameters into the handler like so:
function callHandler(handler)
{
var param = 'Hello world';
handler(param);
}
callHandler(function(phrase)
{
alert(phrase);
});
put the parameters into an object like so:
var handler = {
param1: 'val1',
param2: 'val2' //ect...
}
handler(handler);
EDIT:
changing:
$("#divy").scrollTop($("#"+id).position().top);
to:
$("#divy").scrollTop($("#"+id.param1).position().top);
should work for your edited question.
Related
Im doing a project right now where certain elements of the page change depending on the mouse positioning and made some code basing myself off an explanation I saw in Mozilla. I understand most of it, but there is still one part that is bothering me, which is the function parameter. Throughout my learning of basic Javascript, I have never understood parameters despite the countless explanations. What does a parameter do? How does the page know its purpose? To give an example here is the code:
<!doctype html>
<html>
<head>
<title>Change</title>
</head>
<body>
<p id="hurb"></p>
<script>
document.addEventListener('mousemove', movee);
function movee(a) {
var eub = a.clientX;
document.getElementById("hurb").innerHTML = eub;
}
</script>
</body>
</html>
What does a do here? How does the page know what it does?
Can someone please explain this in a way that can be understandable for a beginner? All the other explanations in pages dont really help me out.
Thanks!
The parameter, as its name suggests, is something upon which usually the function's return value depends. Hence, your function can have a parameter that is not used throughout the function. Here is an example:
function foo() {
console.log("foo");
}
function bar(par1, par2, par3) {
console.log("bar");
}
foo(); // foo
bar(); // bar
bar(45,100); // bar
Note that however you call bar() it logs "bar", since the parameter is never used inside the function and hence never contributes to the return value of the function.
In your case, the function is an event handler function, i.e. is called when some event (mousemove in your case) is fired. When an event is fired, the browser passes an Event object (particularly a MouseEvent object in your case) to the event handler function. This event object is a typical JS object, with properties such as clientX, clientY, pageX, pageY, etc.... By defining your function with a parameter, that parameter is going to take the value of the Event object. To access the Event object's properties, you do not need to define a parameter for your function. Hence, this function:
function movee(a) {
var eub = a.clientX;
document.getElementById("hurb").innerHTML = eub;
}
and this one:
function movee() {
var a = event;
var eub = a.clientX;
document.getElementById("hurb").innerHTML = eub;
}
are typical of each other.
How does the page know its purpose?
The page doesn't. All the page does is that it executes your function. If it encounters the parameter, it uses its value. Otherwise, it just continues execution.
I have this code inside a iframe:
window.addEventListener('message', function(e){
if(e.data == 'test')
console.log(e);
}, false);
and this inside the parent document:
$('#the_iframe').get(0).contentWindow.postMessage('test', 'http://localhost/');
So the parent document sends a "test" message to the iframe and it works.
But how can I define a function in the parent document, and somehow send this function through postMessage to the iframe, which will execute the function locally?
The function does some changes to the document like this:
var func = function(){
$("#some_div").addClass('sss');
}
(#some_div exists in the iframe, not the parent document)
There's nothing that would prevent you from passing a stringified function as postmessage event data. Implementation is trivial, for any function declaration like
function doSomething(){
alert("hello world!");
}
You could encodeURI its string interpretation:
console.log(encodeURI(doSomething.toString()));
//function%20doSomething()%20%7B%0A%20%20%20%20alert(%22hello%20world!%22);%0A%7D
It can then be executed as part of a closure - something not overly imaginative like
eval('('+decodeURI(strCallback)+')();');
There's a fiddle'd proof of concept without the cross-frame architecture - I'll see if I can put together a postMessage version, but it would be non-trivial to host w/jsfiddle
Update
As promised, a full mockup that works (links below). With correct event.origin checks this would be sufficiently inpenetrable, but I know for the fact that our security team would never let eval into production like this :)
Given the option I'd suggest the functionality be normalized across the two pages so that only a parametric message would need to be passed (i.e. pass arguments not functions); however there are definitely a few scenarios where this is a preferred approach.
Parent code:
document.domain = "fiddle.jshell.net";//sync the domains
window.addEventListener("message", receiveMessage, false);//set up the listener
function receiveMessage(e) {
try {
//attempt to deserialize function and execute as closure
eval('(' + decodeURI(e.data) + ')();');
} catch(e) {}
}
Iframe code:
document.domain = "fiddle.jshell.net";//sync the domains
window.addEventListener("message", receiveMessage, false);//set up the listener
function receiveMessage(e) {
//"reply" with a serialized function
e.source.postMessage(serializeFunction(doSomething), "http://fiddle.jshell.net");
}
function serializeFunction(f) {
return encodeURI(f.toString());
}
function doSomething() {
alert("hello world!");
}
Prototype mockup: parent code and iframe code.
You can't really. Although the (draft) spec for postMessage talks about structured objects, e.g. nested objects and arrays, [...] JavaScript values (strings, numbers, Dates, etc) and [...] certain data objects such as File Blob, FileList, and ArrayBuffer objects most browsers only allow strings (including JSON, of course). Read more at MDN or dev.opera. Yet I'm quite sure that it won't be possible to send function objects, at least not as closures preserving their scope.
So you'll end in stringifying the function and eval() it in the iframe, if you really want to execute some code from the parent window. However, I can see no reason for any application to allow evaluation of arbitrary code (even if from registered domains); it would be better to build an message API which can receive (JSON-)string commands and invoke its own methods.
In this case I'd try different approach. Why? Bergi already explained why it won't work the way you want it.
You can define (and redefine your functions) in parent page:
<html>
<head>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript">
var fun = function() { alert('I am a function!'); };
$(function() {
// use this function to change div background color
fun = function() {
// get desired div
var theDiv = $('#frame').contents().find('#some_div');
theDiv.css('background', '#ff0000');
};
// or override it, if you want to change div font color
fun = function() {
var theDiv = $('#frame').contents().find('#some_div');
theDiv.css('color', '#ff0000');
};
// in this example second (font color changing) function will be executed
});
</script>
</head>
<body>
<iframe id="frame" src="frame.htm"></iframe>
</body>
</html>
and call your function from within frame-page:
<html>
<head>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript">
$(function() {
parent.fun();
});
</script>
</head>
<body>
<div id="some_div">I am a div (but inside frame)!</div>
</body>
</html>
It may be inconvenient, but it works.
Expanding upon the following question you can stringify a function, use postMessage to send the function body over, and then use eval to execute it.
Essentially what you are doing is marshalling the function so that it can be sent to the iframe and then unmarshalling it on the other end. To do so use the following code:
Iframe:
window.addEventListener("message", function (event) {
var data = JSON.parse(event.data);
var callback = window[data.callback];
var value = data.value;
if (data.type === "function")
value = eval(value);
var callback = window[data.callback];
if (typeof callback === "function")
callback(value);
}, false);
function callFunction(funct) {
funct();
}
Parent:
var iframe = $("#the_iframe").get(0).contentWindow;
postMessage(function () {
$("#some_div").addClass("sss");
}, "callFunction");
function postMessage(value, callback) {
var type = typeof value;
if (type === "function")
value = String(value);
iframe.postMessage({
type: type,
value: value,
callback: callback
}, "http://localhost");
}
Once you get the function body in your iframe and eval it you can use it like a normal function. You can assign it to a variable, pass it around, use call or apply on it, bind it, and so on.
Note however that the scope of the function is dynamic (i.e. any non-local variables in the function must be already defined in your iframe window).
In your case the jquery $ variable which you are using in your function is non-local. Hence the iframe must already have jquery loaded. It won't use the jquery $ variable from the parent window.
You can always send postMessage back to the iframe and let iframe handle the message. Of course you must count that it wont get executed before next command in iframe.
<!doctype html>
<html>
<body>
<div id = 'div' style = 'width:100px;height:100px;background:#000000;'></div>
<script type = 'text/javascript'>
document.getElementById('div').addEventListener('click',happen(),true);
function happen()
{
alert(1)
}
</script>
</body>
</html>
In the above code why the event is triggered when the page loads and not triggered when i click on the div...Also which is the correct event name click or onclick....
It's because you've immediately called the function, and passed its null result to addEventListener().
It should be:
document.getElementById('div').addEventListener('click',happen,true);
If you want to pass arguments to happen, you'd have to write this:
document.getElementById('div').addEventListener('click', function() {
happen(args_here, ...);
}, true);
You're calling the function immediately and passing its return value to addEventListener, just like any other function call.
Take out the ().
This should work:
document.getElementById('div').addEventListener('click',happen,true);
The problem is with this line:
document.getElementById('div').addEventListener('click',happen(),true);
You should should only be passing the name of the function happen but since you added the parentheses, you are passing the result.
Try this instead:
document.getElementById('div').addEventListener('click',happen,true);
As the other answerers have said, taking out the () will fix the problem.
An alternative, and a good practice for OO Javascript, is to wrap the function inside a function(){ }, like so:
document.getElementById('div').addEventListener('click',function(){happen()},true);
That will retain scope if the callback needs to execute within an object (in this case it does not).
The event handler does not need parenthesis
document.getElementById('div1').addEventListener('click',happen,true);
I'm trying to use:
<script type="text/javascript">
function myfunc() {
var param = 4;
alert("OK");
}
</script>
I call the function like this:
<a4j:jsFunction name="myfunc">
<a4j:actionparam name="param" assignTo="#{MyBean.myfield}"/>
</a4j:jsFunction>
But it does not work. In what may be the reason?
You misunderstood the purpose of <a4j:jsFunction>. It autogenerates a JavaScript function which you can then call from any JavaScript code in your view.
Your example,
<a4j:jsFunction name="myfunc">
<a4j:actionparam name="param" assignTo="#{MyBean.myfield}"/>
</a4j:jsFunction>
will autogenerate the following function
<script>
function myfunc(param) {
// Here some specific JSF Ajax script which assigns "param"
// to a managed bean property #{MyBean.myfield}
}
</script>
You do not need to define it yourself. You only need to invoke it yourself from some JavaScript code elsewhere. For example,
<span onclick="myfunc(4)">click here to set 4 in MyBean.myfield</span>
or
<script>
function someOtherFunction() {
var param = 4;
myfunc(param);
}
</script>
which is in turn to be used like
<span onclick="someOtherFunction()">click here to call someOtherFunction() which will in turn set 4 in MyBean.myfield</span>
See also:
<a4j:jsFunction> component reference
<a4j:jsFunction> showcase example
<a4j:jsFunction
is not used to call an function, it is used to define an function.
So, if MyBean.myfield is an int-field you can set the value 2 using:
<script>myfunc(2);</sript>
There's a bunch of different ways to call that function.
Two you will find particularly useful are:
This:
<body onload="myfunc();">
Example: http://ultimatemmo.webege.com/Test.html
and this:
Click here to execute function
Example: http://ultimatemmo.webege.com/Test2.html
Edit: added examples.
According you snippet of code, you have never called your function. Add myfunc(); within your script tag.
I am trying to call a function with parameters using jQuery's .click, but I can't get it to work.
This is how I want it to work:
$('.leadtoscore').click(add_event('shot'));
which calls
function add_event(event) {
blah blah blah }
It works if I don't use parameters, like this:
$('.leadtoscore').click(add_event);
function add_event() {
blah blah blah }
But I need to be able to pass a parameter through to my add_event function.
How can I do this specific thing?
I know I can use .click(function() { blah }, but I call the add_event function from multiple places and want to do it this way.
For thoroughness, I came across another solution which was part of the functionality introduced in version 1.4.3 of the jQuery click event handler.
It allows you to pass a data map to the event object that automatically gets fed back to the event handler function by jQuery as the first parameter. The data map would be handed to the .click() function as the first parameter, followed by the event handler function.
Here's some code to illustrate what I mean:
// say your selector and click handler looks something like this...
$("some selector").click({param1: "Hello", param2: "World"}, cool_function);
// in your function, just grab the event object and go crazy...
function cool_function(event){
alert(event.data.param1);
alert(event.data.param2);
}
You need to use an anonymous function like this:
$('.leadtoscore').click(function() {
add_event('shot')
});
You can call it like you have in the example, just a function name without parameters, like this:
$('.leadtoscore').click(add_event);
But the add_event method won't get 'shot' as it's parameter, but rather whatever click passes to it's callback, which is the event object itself...so it's not applicable in this case, but works for many others. If you need to pass parameters, use an anonymous function...or, there's one other option, use .bind() and pass data, like this:
$('.leadtoscore').bind('click', { param: 'shot' }, add_event);
And access it in add_event, like this:
function add_event(event) {
//event.data.param == "shot", use as needed
}
If you call it the way you had it...
$('.leadtoscore').click(add_event('shot'));
...you would need to have add_event() return a function, like...
function add_event(param) {
return function() {
// your code that does something with param
alert( param );
};
}
The function is returned and used as the argument for .click().
I had success using .on() like so:
$('.leadtoscore').on('click', {event_type: 'shot'}, add_event);
Then inside the add_event function you get access to 'shot' like this:
event.data.event_type
See the .on() documentation for more info, where they provide the following example:
function myHandler( event ) {
alert( event.data.foo );
}
$( "p" ).on( "click", { foo: "bar" }, myHandler );
Yes, this is an old post. Regardless, someone may find it useful. Here is another way to send parameters to event handlers.
//click handler
function add_event(event, paramA, paramB)
{
//do something with your parameters
alert(paramA ? 'paramA:' + paramA : '' + paramB ? ' paramB:' + paramB : '');
}
//bind handler to click event
$('.leadtoscore').click(add_event);
...
//once you've processed some data and know your parameters, trigger a click event.
//In this case, we will send 'myfirst' and 'mysecond' as parameters
$('.leadtoscore').trigger('click', {'myfirst', 'mysecond'});
//or use variables
var a = 'first',
b = 'second';
$('.leadtoscore').trigger('click', {a, b});
$('.leadtoscore').trigger('click', {a});
$imgReload.data('self', $self);
$imgReload.click(function (e) {
var $p = $(this).data('self');
$p._reloadTable();
});
Set javaScript object to onclick element:
$imgReload.data('self', $self);
get Object from "this" element:
var $p = $(this).data('self');
I get the simple solution:
<button id="btn1" onclick="sendData(20)">ClickMe</button>
<script>
var id; // global variable
function sendData(valueId){
id = valueId;
}
$("#btn1").click(function(){
alert(id);
});
</script>
My mean is that pass the value onclick event to the javascript function sendData(), initialize to the variable and take it by the jquery event handler method.
This is possible since at first sendData(valueid) gets called and initialize the value. Then after jquery event get's executed and use that value.
This is the straight forward solution and For Detail solution go Here.
Since nobody pointed it out (surprisingly). Your problem is, that $('.leadtoscore').click(add_event); is not the same as $('.leadtoscore').click(add_event('shot'));. The first one passes a function, the second a function invocation so the result of that function is passed to .click() instead. That's not what you want. Here's what you want in vanilla JavaScript terms:
$('.leadtoscore').click(add_event.bind(this, 'shot'));
Function.prototype.bind() passes the function to .click() just like in the first example but with bound this and arguments that will be accessible on invocation.