JavaScript Prototypes and jQuery Selectors - javascript

I am creating the following code in JavaScript (inside file1.js)
function ABC () {
this.property01 = true;
}
ABC.prototype.doSomething = function () {
if (this.property01 == true) {
// Do something
}
}
Then later in a separate file in my project (lets call it file2.js), I have the following jQuery:
$(document).ready(function() {
var abc = new ABC();
// Some code here
abc.doSomething();
// continue with code
});
So far, everything is correct.
Now, what I would like to do is inside the prototype definition of doSomething() in file1.js, I want to use jQuery. Something along the lines
function ABC () {
this.property01 = true;
}
ABC.prototype.doSomething = function () {
if (this.property01 == true) {
$('#find-element'). .... // ... Do Something
}
}
But I am not sure how to do this. If I wrap the code of file1.js with a jQuery document-ready wrapper, then the line var abc = new ABC(); inside file2.js will throw an error because it no longer recognizes the function definition in file1.js.
Can I use jQuery inside a prototype the way I explained above? How can I do that? How can I structure my files to allow for this to happen?

This should work just fine just as long as jQuery has fully loaded before file1.js and file1.js have. If you explicitly load them in the correct order, the $ will be available globally, and the other files shouldn't have an issue recognizing that object. In fact, if you load things correctly, you shouldn't even need a document-ready setup to gain access to $.
<script src="../jquery.js"></script>
<script src="../file1.js"></script>
<script src="../file2.js"></script>
If, for some reason, you're having conflicts with the $ object, you could also just use the word jQuery to make your calls: jQuery('#find-something')

Related

how to call a javascript function within a function

I have javascript file called screener.js
function ScreenerPage() {
function onScreenListChange() {
do stuff
};
}
from the index.html file I include the javascript file like this:
<script type="text/javascript" src="./js/screener.js"></script>
Then later in the head section of index.html I instantiate the screenerPage object like this:
<script type="text/javascript">
$(document).ready(function () {
screenerPage = new ScreenerPage();
}
</script>
Then down in the body section there is a select with onchange event that calls
<select id="screenList" onchange="screenerPage.onScreenListChange()">
but the browser shows error:
Uncaught TypeError: screenerPage.onScreenListChange is not a function
What am I doing wrong?
The way javascript works is it has objects and the way of which they are created matter!
Here is the way i've found that works for this kind of thing
screener.js
var ScreenerPage = function() {
this.onScreenListChange = function() {
//do stuff
console.log("test")
}
}
Later on
var a = new ScreenerPage();
a.onScreenListChange();
if you have any questions on how it works feel free to try to message me!
The reason it does not work is that you're having a scope issue.
The function ScreenerPage is defined in the global scope, meaning it is accessible anywhere. Now inside that function you define a local function called onScreenListChange.
You are able to do that, but that function only exists within the scope of the function you defined it in.
When I look at your function, I think you want to use classes. A class is a single name that can have multiple variables / methods to do a specific task.
class ScreenerPage {
constructor(text){
this.onScreenListChange(text) // Call this "method" on object creation.
}
onScreenListChange(text) {
console.log(text ? text : 'do stuff');
};
}
var a = new ScreenerPage('hi'); // now watch your console log.
a.onScreenListChange();

Javascript Library Quickstart

I'm trying to build a Javascript library that will provide some functionality for a JQuery Plugin I'm putting together.
I got the following skeleton code from searching online although I'm not quite sure how it all works (I do know it's a closure). I've added my functions via declarations.
(function(window, document, $) {
function func_1(){
return 1;
}
function func_2(){
return 2;
}
})(window, document, jQuery);
So I put the above code in a separate JS file and then source it in my HTML page, then I run try to run the function like so (Note: I have JQuery set up as well):
<script type="text/javascript">
$(document).ready(function() {
console.log(func_1());
});
</script>
However, I seem to be getting some errors in Firebug (ReferenceError: func_1 is not defined).
I have two questions:
How do I call my functions?!
I'd like to be able to call the functions in the following format: className.functionName(). How do I restructure the skeleton code to enable me do this and, say, call my function like this: Device.func_1()?
Thanks for your anticipated assistance.
The closure is used to hide internal functions from the rest of the code. You need to explicitly expose the public functions of the library:
var Device = (function(window, document, $) {
function func_1(){
return 1;
}
function func_2(){
return 2;
}
var internalDevice = {
func_1: func_1,
func_2: func_2
};
return internalDevice; // expose functionality to the rest of the code
})(window, document, jQuery);
The (function(window, document, $) {})(window, document, jQuery); part is called an immediately invoked function expression (IIFE). It's used to avoid leaking all the library functions into the global scope. Otherwise, if some other library had a func_1 function it would either be overwritten or overwrite your library's func_1.
The arguments to the function are used to control how the library can affect other parts of the code and relies on it. For example, someone might overwrite the window.$ library so that $ is no longer available everywhere in the code. But since you have a local reference in the closure you can still access it.
Alternatively to using the code above - returning an object - you could also assign your library directly to the global scope:
(function(window, document, $) {
...
window.Device = internalDevice; // expose functionality to the rest of the code
})(window, document, jQuery);
I can only answer question number two, but you can create that by doing this:
var Device = {
function func_1()
{
// your first function
},
function func_2()
{
// your second function
}
};
That way you can just call:
Device.func_1();
Hop that helps :)
When something is inside a closure the scope of it is changed to that closure. func_1 and func_2 can only be seen inside the anonymous function calling them and below.

encapsulating javascript inside a namespace

I'm looking to encapsulate my javascript inside a namespace like this:
MySpace = {
SomeGlobal : 1,
A: function () { ... },
B: function () { ....; MySpace.A(); .... },
C: function () { MySpace.SomeGlobal = 2;.... }
}
Now imagine that instead of a few lines of code, I have about 12K lines of javascript with hundreds of functions and about 60 globals. I already know how to convert my code into a namespace but I'm wondering if there's a quicker way of doing it than going down 12K lines of code and adding MySpace. all over the place.
Please let me know if there's a faster way of doing this.
Thanks for your suggestions.
I like to wrap up the namespace like so. The flexibility is huge, and we can even separate different modules of the MySpace namespace in separate wrappers if we wanted too. You will still have to add some sort of _self. reference infront of everything, but at least this way you can change the entire name of the namespace very quickly if need be.
You can see how with this method you can even call _self.anotherFunc() from the 1st module, and you'll get to the second one.
(function (MySpace, $, undefined) {
var _self = MySpace; // create a self-reference
_self.test = function () {
alert('we got here!');
_self.anotherFunc(); // testing to see if we can get the 2nd module
};
_self = MySpace; // reassign everything just incase
}(window.MySpace = window.MySpace || {}, jQuery));
$(function () {
MySpace.test(); // call module 1
MySpace.callOtherModule(); // call module 2
});
// Here we will create a seperate Module to the MySpace namespace
(function (MySpace, $, undefined) {
var _self = MySpace; // create a self-reference
_self.callOtherModule = function () {
alert('we called the 2nd module!');
};
_self.anotherFunc = function () {
alert('We got to anotherFunc from the first module, even by using _self.anotherFunc()!');
};
_self = MySpace; // reassign everything just incase
}(window.MySpace = window.MySpace || {}, jQuery));​
jsFiddle DEMO
Wrap a function body around your existing code to use as scope, hiding everything from global - this will allow you to do internal calls without pasting Namespace. prefix everywhere, neatly hide things you don't want everyone else to see, and will require minimal changes as well.
After that, decide what functions you want to "export" for everyone and assign them to properties of object you want to use as "namespace".

Scope of my jQuery function?

I have a file called function.js which has all my jQuery for my aplication which looks like this
$(document).ready(function(){
insert_initial(); //first time to the page, insert into cart and set the subtotal originally
function update_gallery(product_id){
...
}
function update_prices(product_selector){
...
...
}
function insert_initial(){
...
}
$('.trigger').click(function(){
$('.stations').find(".drop-down").slideToggle();
return false;
});
...
...
On the top of the file i have my function call insert_initial(); which gets run on the initial load....and this works great..My problem is that i now need to include this js file on my php pages say 1.php and 2.php and 3.php and 1.php is the only one that needs the insert_initial(); ....so i was thinking of the best way to do this. I assumed taking out the function call out of the functions file and putting it into a separate file
<script src="/someting/js/functions.js" type="text/javascript"></script>
<script src="/someting/js/functions_insert.js" type="text/javascript"></script>
and in my functions_insert.js file i would have only
$(document).ready(function(){
insert_initial(); //first time to the page, insert into cart and set the subtotal originally
});
but that didnt work either...any ideas on how to fix this
This checks to make sure that the location of the current page includes "1.php" before calling insert_initial():
if(window.location.href.indexOf('1.php') != -1)
insert_initial();
I would recommend having your definitions and executions separate in this instance. You don't need to define your functions inside of jQuery's DOM ready event. But it is also good to namespace them as mentioned. A common paradigm I follow is like so:
functions.js
(function($, window, undefined) {
function update_gallery(product_id){
...
}
function update_prices(product_selector){
...
...
}
function insert_initial(){
...
}
window.MyApp = {
update_gallery: update_gallery,
update_prices: update_prices,
insert_initial: insert_initial
};
})(jQuery, window);
1.php
<script src="functions.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function(){
MyApp.insert_initial();
});
</script>
Now you can include your definitions as needed, and call them as necessary.
Try namespacing your functions and attaching them to a nice global object.
window.MyApp = {};
MyApp.insert_initial = function(){
};
Then you can access it from wherever you need, provided it's included earlier in the page.
Edit:
If this doesn't work, you've got an error elsewhere in your code - load order, perhaps? Either method you've described to invoke the function is fine, just make sure it's defined when you invoke it.
Your functions defined in functions.js are only visible in the scope of that document ready function. A simple case where it doesn't work:
(function() {
function square(x) {
return x*x;
}
})();
alert(square(2)); //Fails, since square is not in scope
The easiest way to fix this is to declare your functions in the global namespace:
function square(x) {
return x*x;
};
alert(square(2)); //4

Loading multiple scripts with same variables/functions

Is it possible to load multiple scripts with same variables/functions in JS, without overriding the old value of the variable. For example to create an own scope/sandbox or object for each loaded script.
Files to load:
script1:
<script>
function init() {
do something...
}
</script>
script2:
<script>
function init() {
do something...
}
</script>
And after loading call script1.init() or script2.init(), is this possible?
You could wrap each section of code with a self invoking anonymous function, which will effectively namespace that section.
(function() {
function init() {
// do something...
}
})();
init(); // ReferenceError
However, if you can't change the code, the second init will overwrite the first definition.
However...
And after loading call script1.init() or script2.init(), is this possible?
...is confusing. Do you already have the init() as methods of an object? If so, they won't overwrite each other.
Unfortunately, no. There is a single global scope on a single page.
However, by using something like the module pattern, you can make a fake namespace:
For example:
var script1 = (function() {
var that = {};
that.init = function() {
do something...
};
more functions...
return that;
})();
And then call it by using script1.init();
You can find out more about the module pattern here.

Categories

Resources