How to show callback function's parameter in javascript? - javascript

How to show callback function's parameter to user?
I'm writing a pagination component for table by javascript.
And this is my component code. (not finished yet)
function ComponentPagination(paginationAreaID, pageViewDataCount ,
totalDataCount, ajaxUrl)
{
//div
var paginationArea = document.getElementById(paginationAreaID);
//prev button
var prevBtn = document.createElement("a");
prevBtn.textContent = "Prev";
paginationArea.appendChild(prevBtn);
//page buttons
var pageCount = (totalDataCount / pageviewDataCount);
for (var i = 0; i < pageCount; ++i) {
var pageBtn = document.createElement("a");
pageBtn.textContent = (i + 1) + "";
paginationArea.appendChild(pageBtn);
}
//next button
var nextBtn = document.createElement("a");
nextBtn.textContent = "Next"
paginationArea.appendChild(nextBtn);
//Use this method to set callback function
//The call back function called when user click page button <a> or
//next or prev button.
this.addCallBack = function(onUpdatePagingMethod)
{
// (example)
var clickedButton;// = clickedButtonIndex;
this.onUpdatePagingMethodCallBack = onUpdatePagingMethod;
//and then it will call when update will neccessay
//like this.onUpdatePagingMethodCallBack(clickedButton, ajaxUrl);
}
}
User will use this like..
<script>
windows.onload = function()
{
//the total data is 105 and the page will show each 10 items
var pagination = new ComponentPagination("pageArea", 10,
105,"/API/FileList");
//Register CallBack
pagination.addCallBack( onPageUpdate );
}
And then the user will design the callback function which name is on PageUpdate.
But, user can't know the callback function's parameter info which
addCallBack() method want. Like This.
function onPageUpdate(/* hum? how should i know the parameter? */)
{
}
well.. In c or c++ have function pointer(maybe they use typedef), so it can limit the parametes numberand each type and user can infer how to design callback function and parameters meaning.
I have no ideas how to limit or invoke parameter info to user in javascript.
Is there have any ideas about this? The comment is only way to solve this problem?
p.s : Not like ts, i want only js.

Javascript doesn't have any way to declare the signature of callback functions in code. You should put it in the documentation of your component, e.g.
onPageUpdate: function(string argName1, object argName2, ...)
For an example, see how jQuery describes the callback function in jQuery.each

Well if you want the parameters you can use arguments:
function onPageUpdate()
{
for (var i = 0; i < arguments.length; i++) {
console.log(arguments[i]);
}
}

All function parameters are present in the Arguments Scope
you do console.log(arguments) inside any function and it'll log all the parameters on your console.
Edit:
predefining a signature of a callback isn't possible in JavaScript except via the usual way of documentation by a comment.
This is possible in TypeScript though, in a similar format.
public myCallback: (name: type) => returntype;

Related

addEventListener not working in Javascript but jQuery Click is working

I am using modular pattern of javascript and trying to do things in Javascript way rather than Jquery
myapp.module1 = (function($){
"use strict";
var _config = {
backgroundImages : document.getElementsByClassName('img_paste'),
}
for(var i = 0;i < _config.backgroundImages.length; i++){
var imageElement = _config.backgroundImages[i];
imageElement.addEventListener('click',myapp.module2.addBackgroundImage(imageElement),false);
}
// $('.img_paste').click(function(){
// var img = this;
// console.log(this);
// console.log($(this));
// myapp.module2.addBackgroundImage(img);
// });
})(jQuery);
In the above code, the Jquery click function works but not the Javacript one.
When I tried to debug, I tried to console out the image in addBackgroundImage() function.
var addBackgroundImage = function(imageToBeAdded){
console.log(imageToBeAdded);//
_addImageToCanvas(imageToBeAdded);
}
The function seems to be executing even before onclick. Why is that happening?
First, the images elements appear to be empty in the console, then after some some the image elements are displayed in console.
Take a look at this simple code example:
function describeTheParameter(p) {
console.log("describeTheParameter invoked. p is of type " + typeof(p));
}
function stringFunction() {
return "Hello World!";
}
describeTheParameter(stringFunction());
describeTheParameter(stringFunction);
This results in
describeTheParameter invoked. p is of type string
describeTheParameter invoked. p is of type function
In the first call, we are calling stringFunction, and then passing the result to describeTheParameter.
In the second call, we are actually passing the function to describeTheParameter.
When you call addEventListener you must follow the pattern of the second call: pass the function without invoking it:
In the following line of code, you are invoking addBackgroundImage, and then passing the result (which will be undefined) to addEventListener.
imageElement.addEventListener('click',myapp.module2.addBackgroundImage(imageElement),false);
You need to pass a yet-to-be-called function into addEventListener.
The smallest step to make your code work is to employ a currying function:
function addImage(imageElement) {
return function() {
myapp.module2.addBackgroundImage(imageElement);
}
}
for(var i = 0;i < _config.backgroundImages.length; i++){
var imageElement = _config.backgroundImages[i];
imageElement.addEventListener('click', addImage(imageElement), false);
}
For much simpler code, make use of the this keyword. In this case, this will point to the element that's firing the event.
function imageClickHandler() {
var imageElement = this;
myapp.module2.addBackgroundImage(imageElement);
}
for(var i = 0;i < _config.backgroundImages.length; i++){
var imageElement = _config.backgroundImages[i];
imageElement.addEventListener('click', imageClickHandler, false);
}
The function seems to be executing even before onclick. Why is that happening?
Look at the statement you wrote:
myapp.module2.addBackgroundImage(imageElement)
You are calling the function and then passing its return value as the function argument.
You want something more along the lines of:
myapp.module2.addBackgroundImage.bind(myapp.module2, imageElement)
(or the function expression that you used in the commented out code)

Accessing a JavaScript / jQuery Instance only once

I have a jQuery function which is called on several events (button click, change etc.)
This function is called in the documentReadyFunction and is feeded with start values..
everytime I call this function, parameters will be passed to the function.
My problem is: I don't want to create a new Object each time I call the function, because if I set a variable which decides if a part of the function is beeing executed or not, will be always overwritten..
What do I have to do, to access the first created instance instead of creating always a new one with every function call..
Down below is a simplyfied version of my function.. Maybe you understand my problem better then.
$.fn.doSomething = function(param1) {
var localParam = param1;
var amIcalledMoreThanOnce = parseInt(0, 10);
if (param1 == 1) {
amIcalledMoreThanOnce = amIcalledMoreThanOnce + 1;
if (amIcalledMoreThanOnce == 1) {
$('#run').val(amIcalledMoreThanOnce);
// fill form fields with URL parameters
// This shall be executed only once after getting the URL vals
} else {
// set the localParam to 0 to exit this loop and reach the outter else..
localParam = 0;
$.fn.doSomething(localParam);
}
} else {
$('#run').val(amIcalledMoreThanOnce);
// use the User Input Data not the URL Params
}
};
$.fn.doSomething(1);
$.fn.doSomething(1);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<input type="number" id="run">
you can use this pattern:
var nameOfYourFunction = (function() {
var initializedOnlyOnce = {};
return function() {
//use initializedOnlyOnce here.
}
})();
here what you see is; you create and run a function immediately when the code is run. The outer function immediately returns the inner function and it's assigned to nameOfYourFunction. Then you can use the nameOfYourFunction(); just as any other function. However any varible declared in the outer function will be available to the nameOfYourFunction() and initializedOnlyOnce will never be initialized again.

Calling a javascript function that contains dynamic parameters

I am trying to call a javascript function that contains dynamic variable as a parameter. I think i am failing in the syntax to get this particular function executed. I have tried a few combinations and none of them seem to work. Please can someone advise..
for( i=0; i<succeedList.length; i++){
var file_uniq_id = succeedList[i].filename_uniq;
//Creating dynamic button
var subm_btn = document.createElement("INPUT");
subm_btn.setAttribute("onclick", "UploadMyScript.submitTitle(this.id,'+file_uniq_id+')");
p_titleBtn.appendChild(subm_btn);
}
UploadMyScript.submitTitle = function(id, uniqID){
// Does something ....
}
My problem is I cannot appear to pass on the 'file_uniq_id' value to UploadMyScript.submitTitle().
Why not use an event listener ?
subm_btn.addEventListener('click', function () {
UploadMyScript.submitTitle(subm_btn.id, file_uniq_id); },
false);

Call JavaScript function at Jquery.load

I've a javascript function setErrorImages(), which searches all img tags and and gives them an onerror function. This works great.
I also have a division content with dynamic content by calling de jquery .load function like this, which also works:
$("#content").load("http://example.com/otherpage.php");
But when the new content (otherpage.php) was loaded into the division, the setErrorImages() function doesn't work on the img'es within the new content.
I can call the setErrorImages() function on the otherpage.php, and everything works perfectly, but this way I have to do this on every otherpage, which are a lot.
Is there a way to send a javascript file or function with the jquery .load,
or maybe there is a way to re-execute the javascript function right after the jquery .load.
Kind regards,
Liontack
function setErrorImages(){
var images = document.getElementsByTagName("img");
for (var i = 0; i < images.length; i++) {
images[i].onerror = function(){ setErrorImage(this); };
}
}
function setErrorImage(image){
image.onerror = null;
image.src = 'http://tanuri.eu/images/error.png';
}
$("#content").load("http://example.com/otherpage.php", setErrorImages);
.load() accepts a "complete" parameter:
A callback function that is executed when the request completes.
Firstly, I suggest using the this context instead of a parameter for your error handler:
function setErrorImage() {
this.onerror = null;
this.src = 'http://tanuri.eu/images/error.png';
}
Secondly, change setErrorImages to use this too:
function setErrorImages() {
var images = this.getElementsByTagName('img');
for (var i = 0, n = images.length; i < n; ++i) {
images[i].onerror = setErrorImage; // parameter is now implict
}
}
Note how there's now no need for a function wrapper for the onerror call - the browser automatically sets this to be the element of interest.
For simpler code you could also just use jQuery to do this job for you since you already have it loaded:
function setErrorImages() {
$('img', this).error(setErrorImage);
}
Thirdly, use the complete handler of .load, taking advantage of the fact that it sets this to be the parent of the part of the DOM that just got replaced. This avoids setting the onerror handler on elements in the page that you already looked at.
$('#content').load(url, setErrorImages);
The only other change is that on your initial invocation you'll need to pass document to setErrorImages using .call:
setErrorImages.call(document);

Can I call a namespaced function with jquery contentWindow?

I am working with some legacy code and I'm looking for a safe way to handle the following scenario:
I have an iframe showing a product selection page. I need to pass this iframe the name of a callback function with a query string.
In the iframe I get the callback name from the query string and execute it like so:
$("iframe#content:first", window.top.document)[0].contentWindow[callbackName]();
But this only works if the callback is a globally exposed function. That's lame.
This callback should live in a nested object.
Is there any way I can specify a callback like :
'myNamespace.nestedNamespace.myCallbackFunction'
and execute it off of the contentWindow object ?
In that case, if I understand correctly, something like the following should do the trick:
// Your callback "path".
var callbackPath = 'myNamespace.nestedNamespace.myCallbackFunction';
if (callbackPath != '') {
// We will need to walk our way to the actual callback.
var parts = callbackPath.split('.');
var callback = $("iframe#content:first", window.top.document)[0].contentWindow;
for (var i = 0; i < parts.length; ++i) {
callback = callback[ parts[i] ];
// Was unable to find callback, bail!
if (!callback)
break;
}
if (typeof callback === 'function')
callback();
}

Categories

Resources