How best to overwrite a Javascript object method - javascript

I'm using a framework that allows the include of JS files. At the top of my JS file I have something like:
<import resource="classpath:/templates/webscripts/org/mycompany/projects/library/utils.lib.js">
I want to override a fairly small method that is defined in the very large utils.lib.js file. Rather than make the change directly in utils.lib.js, a file that's part of the framework, I want to overwrite just one method. The utils.lib.js file has something that looks like:
var Evaluator =
{
/**
* Data evaluator
*/
getData: function Evaluator_getData(input)
{
var ans;
return ans;
},
...
}
I want to change just what the method getData does. Sorry for the basic question, but after importing the file which copies the JS contents into the top of my JS file, can I just do something like:
Evaluator.getData = function Mine_getData(input)
{
...
};

Yes, you can just reassign that method to your own function as you have proposed with:
Evaluator.getData = function Mine_getData(input)
{
...
};
This will successfully change what happens when the .getData(input) property is called.

Yes you can.
However Evaluator is not a proper 'class'. You can't write var x = new Evaluator();
So you are not overriding, but just changing the variable getData. That's why we say that in JavaScript, functions are first-class citizen, treated like any variable.

Related

Lightswitch HTML global JS file to pass variable

I know how this works in C#, however not so much in javascript so I am hoping it is similar.
With Javascript can I create say a master.js, with a variable (var defaultValue = "1234"), which I can reference in all other javascript files associated with the project?
so in terms of Lightswitch HTML, each screen has the ability to have a js file, and on the screen I want to be able to retrieve this defaultValue.
Can this be done?
If yes, how can I get this value onto the current screen?
so far I have created a main.js file, added this function:
function getDefaultValue(value) {
var value = "1234";
return value;
}
and declared the js file in the default.htm file:
<script type="text/javascript" src="Scripts/main.js"></script>
I know this is how i am using other JavaScript files like blob.js, lsWires.js etc...
using this method in by screen.js doesn't work so one of these stages is causing an error...
window.alert(main.getDefaultValue(value));
ideally i would like to use this defaultvalue for setting a value, i.e. var test = main.getDefaultValue(value)
This is certainly possible, and the script declaration you've used in your default.htm appears correct.
However, as the approach you've described creates a global getDefaultValue function (added to the global window object context) you wouldn't specify a main 'namespace' prefix like you would in c#.
Instead, rather than calling the function using main.getDefaultValue, you'd use the the following approach within your LightSwitch screens:
myapp.BrowseProducts.created = function (screen) {
window.alert(window.getDefaultValue("123")); // This will display 1234
// As window is a global object, its window prefix can be omitted e.g.
alert(getDefaultValue("123")); // This will display 1234
};
Or, if you want to define a global defaultValue variable in your main.js (probably the approach you're looking to implement) you would have the following code in your main.js file:
var defaultValue = "5678";
Then you'd access it as follows in your LightSwitch screens:
myapp.BrowseProducts.created = function (screen) {
alert(defaultValue); // This will display 5678
defaultValue = "Hello World";
alert(defaultValue); // This will now display Hello World
};
Also, if you'd like to organise your functions/properties in a main 'namespace', you could use the following type of approach in your main.js file: -
var main = (function (ns) {
ns.getDefaultValue = function (value) {
var value = "1234";
return value;
};
ns.defaultValue = "5678";
return ns;
})(main || {});
These would then be called as follows in your LightSwitch screens: -
myapp.BrowseProducts.created = function (screen) {
alert(main.getDefaultValue("123")); // This will display 1234
alert(main.defaultValue); // This will display 5678
main.defaultValue = "Hello World";
alert(main.defaultValue); // This will now display Hello World
};
This type of approach is covered in the following posts: -
How to span javascript namespace across multiple files?
JavaScript Module Pattern: In-Depth

Razor Syntax in External Javascript

So as you might know, Razor Syntax in ASP.NET MVC does not work in external JavaScript files.
My current solution is to put the Razor Syntax in a a global variable and set the value of that variable from the mvc view that is making use of that .js file.
JavaScript file:
function myFunc() {
alert(myValue);
}
MVC View file:
<script language="text/javascript">
myValue = #myValueFromModel;
</script>
I want to know how I can pass myValue directly as a parameter to the function ? I prefer to have explicit calling with param than relying on globals, however I'm not so keen on javascript.
How would I implement this with javascript parameters? Thanks!
Just have your function accept an argument and use that in the alert (or wherever).
external.js
function myFunc(value) {
alert(value);
}
someview.cshtml
<script>
myFunc(#myValueFromModel);
</script>
One thing to keep in mind though, is that if myValueFromModel is a string then it is going to come through as myFunc(hello) so you need to wrap that in quotes so it becomes myFunc('hello') like this
myFunc('#(myValueFromModel)');
Note the extra () used with razor. This helps the engine distinguish where the break between the razor code is so nothing odd happens. It can be useful when there are nested ( or " around.
edit
If this is going to be done multiple times, then some changes may need to take place in the JavaScript end of things. Mainly that the shown example doesn't properly depict the scenario. It will need to be modified. You may want to use a simple structure like this.
jsFiddle Demo
external.js
var myFunc= new function(){
var func = this,
myFunc = function(){
alert(func.value);
};
myFunc.set = function(value){
func.value = value;
}
return myFunc;
};
someview.cshtml
<script>
myFunc.set('#(myValueFromModel)');
myFunc();//can be called repeatedly now
</script>
I often find that JavaScript in the browser is typically conceptually tied to a specific element. If that's the case for you, you may want to associate the value with that element in your Razor code, and then use JavaScript to extract that value and use it in some way.
For example:
<div class="my-class" data-func-arg="#myValueFromModel"></div>
Static JavaScript:
$(function() {
$('.my-class').click(function() {
var arg = $(this).data('func-arg');
myFunc(arg);
});
});
Do you want to execute your function immediately? Or want to call the funcion with the parameter?
You could add a wrapper function with no parameter and inside call your function with the global var as a parameter. And when you need to call myFunc() you call it trough myFuncWrapper();
function myFuncWrapper(){
myFunc(myValue);
}
function myFunc(myParam){
//function code here;
}

Override/Rewrite a javascript library function

I am using an open source javascript library timeline.verite.co
It's a timeline library which works great on page load. But when I try to repaint the timeline on certain condition, it starts giving out weird errors
I would like to modify the init function in the library. But instead of changing it in the original library itself, I would like to rewrite/override this function in another separate .js file so that when this function is called, instead of going to the original function, it must use my modified function.
I'm not sure whether to use prototype/ inheritance and how to use it to solve this problem?
You only need to assign the new value for it. Here is an example:
obj = {
myFunction : function() {
alert('originalValue');
}
}
obj.myFunction();
obj.myFunction = function() {
alert('newValue');
}
obj.myFunction();

How to generate global, named javascript functions in coffeescript, for Google Apps Script

I'd like to write Javascript scripts for Google Apps Script using CoffeeScript, and I'm having trouble generating functions in the expected form.
Google Apps Script expects a script to contain top-level, named functions. (I may be using the wrong terminology, so I'll illustrate what I mean with examples...)
For example, this function is happily recognised by Google Apps Script:
function triggerableFunction() {
// ...
}
... while this function is not (it will parse, but won't you won't be able to trigger it):
var nonTriggerableFunction;
nonTriggerableFunction = function() {
// ...
};
I've found that with CoffeeScript, the closest I'm able to get is the nonTriggerableFunction form above. What's the best approach to generating a named function like triggerableFunction above?
I'm already using the 'bare' option (the -b switch), to compile
without the top-level function safety wrapper.
The one project I've found on the web which combines CoffeeScript and Google App Script is Gmail GTD Bot, which appears to do this using a combination of back-ticks, and by asking the user to manually remove some lines from the resulting code. (See the end of the script, and the 'Installation' section of the README). I'm hoping for a simpler and cleaner solution.
CoffeeScript does not allow you to create anything in the global namespace implicitly; but, you can do this by directly specifying the global namespace.
window.someFunc = (someParam) ->
alert(someParam)
Turns out this can be done using a single line of embedded Javascript for each function.
E.g. this CoffeeScript:
myNonTriggerableFunction = ->
Logger.log("Hello World!")
`function myTriggerableFunction() { myNonTriggerableFunction(); }`
... will produce this JavaScript, when invoking the coffee compiler with the 'bare' option (the -b switch):
var myNonTriggerableFunction;
myNonTriggerableFunction = function() {
return Logger.log("Hello World!");
};
function myTriggerableFunction() { myNonTriggerableFunction(); };
With the example above, Google Apps Script is able to trigger myTriggerableFunction directly.
This should give you a global named function (yes, it's a little hacky, but far less that using backticks):
# wrap in a self invoking function to capture global context
do ->
# use a class to create named function
class #triggerableFunction
# the constructor is invoked at instantiation, this should be the function body
constructor: (arg1, arg2) ->
# whatever
juste use # in script, exemple of my code :
#isArray = (o)->
Array.isArray(o)
it will be compiled in :
(function() {
this.isArray = function(o) {
return Array.isArray(o);
};
}).call(this);
this = window in this case, so it's global function

Is it possible to call a Javascript function (that's private) inside the object A from an object that inherits from A?

I want to be able to test some inner functions that I have without putting the Javascript test code in the same file. I've been trying to inherit the class that has the inner functions, and then adding wrapper functions to make them public, like this:
copyPrototype(TrafficChartCanvas_test, TrafficChartCanvas);
function TrafficChartCanvas_test() {
TrafficChartCanvas_test.prototype.test_getYScale = function(reach) {
return getYScale(reach);
}
}
Assume copyPrototype successfully assigns the prototype of TrafficChartCanvas to that of TrafficChartCanvas_test. Here's part of the file I'm attempting to test:
function TrafficChartCanvas(...) {
// some other stuff here... public functions, etc.
function getYScale(reach) {
...
}
}
However, this doesn't work for me. Is there any other way I can do this?
getYScale isn't part of TrafficChartCanvas's prototype, it's within its closure. They're two very different things.
You could change the way you create TrafficChartCanvas and restructure your code something like:
TrafficChartCanvas.prototype = {
// (... Other functions ...)
getYScale: function() {
...
}
}
This puts the function in the prototype and allows it to be tested using tests written and included in another file. You can't keep functions private within a closure and make the accesible for external testing; you'll have to go the prototype route.
The "TrafficChartCanvas" function can arrange for a way to explicitly export the function, but short of that, no there's no way to do it.

Categories