In ASP.NET we are calling defined js-functions with the:
Page.ClientScript.RegisterStartupScript(GetType(), "", "JSFuncNameHere();", true);
I wonder:
Why there isn't any method, which has a name like: Page.ClientScript.CallJSScript("someJSFunc");
Why does the upper-method require the reflection method GetType() ? Something isn't defined at runtime, is it?
Why do I need the 2nd argument key? As I have tested, I can left it empty and the existed JS-function shall be called.
Why there isn't any method, which has a name like: Page.ClientScript.CallJSScript("someJSFunc");
Probably because this is more generic solution, since by just adding 2 characters you get the same result and if you need you can add arguments and anything else.
Why does the upper-method require the reflection method GetType() ? Something isn't defined at runtime, is it?
Why do I need the 2nd argument key? As I have tested, I can left it empty and the existed JS-function shall be called.
For both of these the same reason - the method will detect if you run the same script multiple times and in such case, call it just once. The two arguments are the means how it identifies duplicates - a key is not sufficient since another class in a different library might be using the same key - so you need to pass in the type of your own class to ensure that the script is executed when you want it to.
Related
I have a page where users can choose to book a ticket for a concert. First, they click on a artist which launches them into the booking process (and passes "artist" to the starting function).
The program then loads the venues for the artists. When the user changes the venue (and the value isn't blank) it tried to load the dates available in another select drop down menu by calling another function.
The original code was like:
<select onchange="loadDates(artist)">...</select>
However for some reason this wasn't passing the parameter from the starting function to the next function.
So I changed it too:
<select onchange="loadDates.call(this, artist)">..</select>
However the next function still gives me the error "artist is not defined" when I try to run it. Can anyone see what I'm doing wrong here as I read online that this works perfectly. I can give more information if need be. Thanks
Code in onXyz attributes is run at global scope, so both of your examples require that there be a global variable called artist. If there isn't one, then you'll get a ReferenceError because you're trying to take the value of a symbol that isn't defined.
If you meant to pass a string, put quotes around it. If you meant to pass something else, you'll need to say what that was. But the fundamental issue is that artist is not a defined symbol at global scope, which is where you're trying to use it.
If you have artist defined in some non-global location (good! globals are a bad thing), then you'll want to hook up your event handler via modern techniques rather than using the onXyz attributes.
The simplest way if you're not using a DOM library (like jQuery or similar) is to assign to the onXyz property of the select box element:
(function() { // Something to keep the stuff inside from being globals
var artist = "Joe Cocker";
var selectBox = document.querySelector("selector for the select box");
selectBox.onchange = function() {
loadDates(artist); // `artist` is in scope now
};
})();
In general, though, I avoid the onXyz properties because they only allow a single handler per event per element, preferring the DOM method addEventListener (and its Microsoft-specific predecessor, attachEvent). I didn't use them above for simplicity. If you don't use a DOM library, you might want this hookEvent function given in another answer which uses addEventListener if it's there, or attachEvent if it isn't, and supplies some missing bits for the attachEvent browsers.
If you are in the console of Dev Tools, and you have an object, lets say x, and it has three methods/functions, let's say a(), b(), and c(i, j, k), why doesn't it auto insert the parens, let alone the parens with the correct spaces for the parameters (like eclipse for java) when you use the auto-complete tab or enter?
It currently will only print once selected x.a, x.b, or x.c without the function parens.
I'm assuming that it doesn't know about the parameters because it is JS, and in Java, you can only call a constructor of a fixed order and types, where JS can be overloaded, and error out, but Im just wondering if it is possible.
I don't see why DevTools should assume that I would call a method from autocomplete. Maybe I want to add another . after the method name and see all these apply, bind, call, name etc. methods and properties that I can call? What I mean, is that someObject.someMethod() is not the end of the road in JavaScript.
there is no guarantee that function wants to see only one parameter even if it was declared as a function with one argument because the function could use arguments local variable.
function func(a,b) {
alert(arguments[0])
alert(arguments[1])
alert(arguments[2])
}
func(1,2,3)
Also sometimes you could just pass the function as a callback.
I am investigating a bug in some software that has uses an in-house developed Javascript library. The error that I am dealing with appears on the line below:
GetVal1("dispLetter")(GetVal1("dispLetter").selectedIndex).value + '~' + (bFinal == true ? '1' : '0');
I initially wasn't sure if this line was even valid, however, according to source control this line was around since this file was created while the error is relatively recent. When I debugged I discovered that this line throws an error that says GetVal1(...) is not a function. I double checked to confirm that the Javascript file with the function definition is included, the header looks like this:
function GetVal1(strHTMLId)
So, I guess my question is, is this line valid Javascript code? Is there anything you can tell that could be throwing the error? Thank you.
GetVal1("dispLetter")(GetVal1("dispLetter").selectedIndex).value + ...
does the following:
calls GetVal1 with the argument "dispLetter".
calls GetVal1 with the argument "dispLetter", again.
retrieves the property selectedIndex of the return value of the second invocation of GetVal1
Calls the return value of the first invocation of GetVal1, with one argument, the value of selectedIndex. This fails your case, and complains the value is not callable.
The return value's value property is dereferenced. String concatenation follows.
In other words, this code seems to assume that the first invocation of GetVal1("dispLetter") returns a function (which is unusual), and the second invocation returns an object with the property selectedIndex (which is unusual, given the first invocation returns a function).
Some ideas:
If there used to be a new keyword before the line. Then the first invocation would be a constructor call. It is unexpected that a constructor call would return a function while a non-constructor call would not, though.
If there used to be a trailing period on the previous line (or is now), GetVal1 would refer (or refers now) to a property of some object. I smell a violation of naming conventions, though, if GetVal1 is meant to be an object property.
The global GetVal1 is (or recently ceased to be) shadowed by a function of the same name. Once again, I smell a violation of naming conventions.
Most likely, GetVal1 itself has changed. Verify GetVal1 can return a function when given this string as the first argument.
Perhaps the state bound to the GetVal1 function has changed (say, one more extra call somewhere before the code. This most likely a design error, though, if this function returns a different type of object on each invocation with the same arguments. But then again, there likely is a design error or naming violation somewhere in the code.
Another plausible explanation is that this line was there from the beginning, but it was never reached before. In this case, it could have been wrong the whole time.
Is there ANY way of monitoring primitive String declaration in NodeJS?
For example, when I do "test"; is there any way of triggering a special event with "test" as a parameter?
I am not sure what you mean by do "test;"; but if you want to trigger an event whenever a variable is assigned a new value, no, there is no way to trigger an event for variable changes.
If you want to watch a variable, it is better to re-design your system to make a call instead of assigning a variable. Instead of doing:
running_mode = "test";
require
switch_mode("test");
and call whatever event handlers you want to trigger on this update.
If you really want to watch the value of a global variable, you can do it by checking the value once in every turn of the main loop:
function is_mode_changed() {
if (running_mode=="test") event_handler();
process.nextTick(is_mode_changed);
}
Once you call this function, it will continue running once each turn of the main loop. If it what you want to do is something like following a variable to do some specific tasks time to time, like following a global counter and doing some cleanup tasks everytime counter reaches 1000, this is a good way to do. If what you want to do something immediately after a variable is changed, it is not possible.
I hope I could understand your question correctly.
UPDATE
[I am adding this in regards to the comment below which rendered everything above unrelated to question because I had misunderstood it.]
As you mentioned yourself, a string literal like "test" is a primitive value which is not an object. So, it is handled by the interpreter in a way we cannot alter.
From Ecma-262:
4.3.2 primitive value
member of one of the types Undefined, Null, Boolean, Number, or String as defined in Clause 8
NOTE: A primitive value is a datum that is represented directly at the lowest level of the language implementation.
To prevent confusion, Clause 8 is the section of standard on Types as listed above.
Since you specified V8, and not per-spec-ECMAScript, you have more concrete options at your disposal. In the V8 API there is classes/templates or primitives that are separate from those of object wrappers for primitives. In order to be able to hook in a way to know when this actually happens would likely require modifying v8 in a custom manner, but it is doable.
http://code.google.com/p/v8/source/browse/branches/bleeding_edge/include/v8.h#1017
Also much of the action takes place in js itself. Perhaps not the very constructor itself, but everything that happens thereafter. String.prototype.toString/valueOf.
http://code.google.com/p/v8/source/browse/branches/bleeding_edge/src/string.js
I have a gallery that I am trying to integrate in my site. I am replacing a and then I want to call the galleries function "function loadGal($)" so the gallery will be rebuilt. But I don't know what kind of parameter to send to it.
Before I changed it, it was called inside "jQuery(document).ready(function($) {"
I just tried to do something like this:
jQuery(document).ready(function($) {
loadGal($);
});
it works fine but I don't know what is the dollar...
The $ is just the name of the parameter. It is nothing special. $ is a valid character of variable names in JavaScript.
However it is often used by libraries such as jQuery or Prototype as it is probably the most characteristic one-letter variable (j or p don't stand out that much) (meaning it is easy to spot and easy to use as you only have to type one character).
The value passed to the ready handler, is the jQuery object (emphasis is mine):
When using another JavaScript library, we may wish to call $.noConflict() to avoid namespace difficulties. When this function is called, the $ shortcut is no longer available, forcing us to write jQuery each time we would normally write $. However, the handler passed to the .ready() method can take an argument, which is passed the global jQuery object. This means we can rename the object within the context of our .ready() handler without affecting other code
but you can name the parameter however you want. You could also write:
jQuery(document).ready(function(foobar) {
loadGal(foobar);
});
Update: And now that I understood the real question ;)
$ is the jQuery object, so you can write:
loadGal(jQuery);
But note that loadGal might not work if it has to work on the DOM elements and you call it outside the ready handler.