Is there a difference between lauch js functions from same JS file where they declared after page load, or in html template? When both signed into $(document).ready(function () {...}).
I assume that no, but I ran into a problem when replace my ExampleService.init() function from template to separate JS file.
For example i have that construction:
common.js
var ExampleService= {
catalogSpinner: '',
init: function() {
this.initEvents();
},
initEvents: function() {
var self = this;
$('.example-button').on('click', function() {
//do some logic, append spinner...
self.removeSpinner();
});
},
removeSpinner: function() {
$(this.catalogSpinner).fadeOut('slow', function() {
$(this).remove().css({display: 'block'});
});
}
}
index.html
<script src="js/common.js"></script>
<script>
$(document).ready(function () {
ExampleService.catalogSpinner = '<div class="spinner"></div>'; // css3 animation
ExampleService.init();
});
</script>
That way all works perfect, my catalogSpinner overriden from template, and i can use them like DOM element.
But! if i move ExampleService.init(); to common.js file, like that:
common.js
var ExampleService= {
...
// all the same...
...
};
$(document).ready(function () {
'use strict';
ExampleService.init();
});
index.html
<script src="js/common.js"></script>
<script>
$(document).ready(function () {
ExampleService.catalogSpinner = '<div class="spinner"></div>';
});
</script>
That way it wouldn't work. And throw console error Uncaught TypeError: this.catalogSpinner.fadeOut is not a function
Why it's happens? After all in both cases init functions starts only after full page load, and no matters that i override my variable after starting base functions. What im doing wrong?
About orders in which inits will executed. How i understand its no matter. Cause in any case, second document.ready from template file, always ovverride empty catalogSpinner variable from JS file, before click event happens
It's almost certainly a timing issue. What guarantee do you have that $(document).ready in common.js will fire after the same event handler in your html file (which is what needs to happen according to your implementation)?
Or, you need to make sure that when it occurs in common.js, that code can somehow retrieve the catalogSpinner value.
Also, catalogSpinner needs to be a valid jQuery object, not a string.
It will and it does work in both the cases. To use jQuery methods over DOM elements, you must have valid jQuery selectors which will return objects binded with jQuery methods.
Try this:
case 1:
common.js
var ExampleService= {
catalogSpinner: '',
init: function() {
this.initEvents();
},
initEvents: function() {
var self = this;
$('.example-button').on('click', function() {
//do some logic, append spinner...
self.removeSpinner();
});
},
removeSpinner: function() {
this.catalogSpinner.fadeOut('slow', function() {
$(this).remove().css({display: 'block'});
});
}
};
index.html
<!doctype html>
<html>
<head>
<script src="jquery.min.js"></script>
<script src="common.js"></script>
<style>
</style>
</head>
<body>
<div class="spinner">Spinner</div>
<button type="button" class="example-button">Remove</button>
<script type="text/javascript">
$(document).ready(function () {
ExampleService.catalogSpinner = $('.spinner');
ExampleService.init();
});
</script>
</body>
</html>
case 2:
common.js
var ExampleService = {
catalogSpinner: '',
init: function () {
this.initEvents();
},
initEvents: function () {
var self = this;
$('.example-button').on('click', function () {
//do some logic, append spinner...
self.removeSpinner();
});
},
removeSpinner: function () {
this.catalogSpinner.fadeOut('slow', function () {
$(this).remove().css({display: 'block'});
});
}
};
$(document).ready(function () {
'use strict';
ExampleService.init();
});
index.html
<!doctype html>
<html>
<head>
<script src="jquery.min.js"></script>
<script src="common.js"></script>
<style>
</style>
</head>
<body>
<div class="spinner">Spinner</div>
<button type="button" class="example-button">Remove</button>
<script type="text/javascript">
$(document).ready(function () {
ExampleService.catalogSpinner = $('.spinner');
});
</script>
</body>
</html>
Related
I have a huge JS file and want to divide it, for example, I have this one:
page.html
<!-- some tags and jquery include... -->
<script src="example.js"></script>
<!-- externalHandlers only needs for second example, in original working example It's empty -->
<script src="externalHandlers.js"></script>
<script>
$(document).ready(function(){
var something = new Something('someValue');
);
</script>
<!-- some tags... -->
example.js
var Something = (function (document) {
"use strict";
var Something = function(x){
//initialize some stuff
};
Something.prototype.func1 = function(){
//do things
}
Something.prototype.func2 = function(){
//do things
}
//more funcs
$(document).on('click', 'a.some-class', function (e) {
//do things when click
});
$(document).on('click', 'a.some-class-2', function (e) {
//do things when click
});
return Something;
})(document);
Above code works fine, but I want to externalize click handlers in another js file. I tried this:
example.js (new)
var Something = (function (document) {
"use strict";
var Something = function(x){
//initialize some stuff
};
Something.prototype.func1 = function(){
//do things
}
Something.prototype.func2 = function(){
//do things
}
//more funcs
$(document).on('click', 'a.some-class', handlerFunction);
$(document).on('click', 'a.some-class-2', function (e) {
//do things when click
});
return Something;
})(document);
externalHandlers.js
function handlerFunction(){
//do some stuff
}
But browser console show me errors
ReferenceError: handlerFunction is not defined
TypeError: Something is not a constructor
How can I do something like that I want? It's possible?
Make sure externalHandlers runs first, so that handlerFunction is defined when example.js runs, so that example.js can properly reference handlerFunction without an error, and so that Something gets defined properly:
<script src="externalHandlers.js"></script>
<script src="example.js"></script>
try this code..
<script type="text/javascript" src="externalHandlers.js"></script>
<script type="text/javascript" src="example.js"></script>
<script>
$(document).ready(function(){
var something = new Something('someValue');
});
</script>
I'm trying to emulate the module pattern found here:
https://css-tricks.com/how-do-you-structure-javascript-the-module-pattern-edition/
Here is my code:
var RPSLS_UI = {
settings: {
playerSelections: $(".card")
},
init: function() {
this.bindUIActions();
},
bindUIActions: function() {
this.settings.playerSelections.on("click", function() {
console.log($(this));
});
}
};
I have included the dependencies in my HTML in this order:
<script src="https://code.jquery.com/jquery-2.2.3.min.js"></script>
<script type="text/javascript" src="assets/js/rpsls-ui-1.0.js"></script>
<script type="text/javascript" src="assets/js/index.js"></script>
When I load my HTML, I type in console:
RPSLS_UI.init();
Results in:
undefined
Then I type in:
RPSLS_UI.init;
Results in:
function () {
this.bindUIActions();
}
What is happening here? Why is the init() function undefined?
The function isn't undefined. It returns undefined because there is no return statement. If you want it to return something you could add a return statement to it:
init: function() {
this.bindUIActions();
return 'Hi!';
}
It doesn't seem like it is necessary for it to return anything, as it calls another function that binds a click handler to your DOM. The function has side effects, but doesn't return anything.
I am working with Backbone and Jquery. I have a button inside a template and for some reason that button does not trigger any click events. I've tried all the suggested solutions on stackoverflow but none of them worked for me. Below is the code Im working with - I've made it as short as possible.
Any ideas why the YES button does not work?
EditView.html
<section id="EditView">
<button id="button-yes">YES</button>
</section>
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
</head>
<body>
<header id="header"></header>
<div id="content"><div id="content-inner"></div></div>
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="http://underscorejs.org/underscore-min.js"></script>
<script src="http://backbonejs.org/backbone-min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"> </script>
<script type="text/javascript">
var myapp = myapp || {};
myapp.EditView = Backbone.View.extend({
events: {
'click #button-yes': 'buttonClickHandler'
},
initialize: function () {
this.render();
},
render: function () {
this.$el.html(this.template());
return this; // support chaining
},
buttonClickHandler : function(event){
alert( $(event.currentTarget).text() );
return false;
}
});
myapp.utils = {
loadTemplates: function(views, callback) {
var deferreds = [];
$.each(views, function(index, view) {
if (myapp[view]) {
deferreds.push($.get(view + '.html', function(data) {
myapp[view].prototype.template = _.template(data);
}));
} else {
console.log(view + " not found");
}
});
$.when.apply(null, deferreds).done(callback);
}
};
myapp.AppRouter = Backbone.Router.extend({
routes: {
"": "add"
},
initialize: function() {
this.add;
},
add: function() {
if (!this.editView) {
this.editView = new myapp.EditView({el: $("#content-inner")});
};
$('#content').html(this.editView.el);
}
});
myapp.utils.loadTemplates([ 'EditView'], function() {
myapp.router = new myapp.AppRouter();
Backbone.history.start();
});
</script>
</body>
</html>
I'm not entirely sure why you're having a problem, seems to be some race condition where the element doesn't exist when backbone attempts to bind the event to it. It's an interesting case. Anyway, you can solve it for now by adding
myapp.router.editView.delegateEvents();
after Backbone.history.start();
I try to use the Event.observe method which is provided by Prototype JS. To be sure that the DOM is loaded, I use document.observe. This causes the error Uncaught TypeError: undefined is not a function. Prototype JS was loaded as you can see below:
HTML
<!DOCTYPE html>
<html>
<head>
<title>playground</title>
<script language="javascript" type="text/javascript" src="../js/prototype.js"></script>
<script language="javascript" type="text/javascript" src="../js/functions.js"></script>
</head>
<body>
<div>
Hello World
</div>
<input type="button" onclick="changeLinkText()" value="Change link by using Prototype">
</body>
JavaScript
//this works
var changeLinkText = function(){
$("meinLink").innerHTML="prototypeWorks";
};
//this causes the error
Document.observe("dom:loaded", function() {
$("meinLink").observe('click', function(e) {
document.getElementById('meinLink').innerHTML="prototypeDoesntWork";
});
});
Your D in
Document.observe("dom:loaded", function() {
is upper-case, fixing it to it's correct notation
document.observe("dom:loaded", function() {
will probably do the job.
You can also try to invoke an on-click-event listener.
$$('meinLink').invoke('on', 'click', '.item', function(event, el) {
// el is the 'meinLink' element
});
It's even possible that just using on will do the job.
$("meinLink").on("click", function(event) {
document.getElementById('meinLink').innerHTML="prototypeDoesntWork";
});
I've been struggling with exactly what the correct syntax is to make methods available on an object with a plugin. Here's the basic framework:
<!DOCTYPE html>
<html>
<head>
<!-- jQuery -->
<script type="text/javascript" src="http://goo.gl/XQPhA"></script>
<script type="text/javascript">
(function($) {
$.test = function(el, options) {
this.whiten = function() {
$(this).css('background-color', options.bg);
}
};
$.test.settings = {
bg: 'white'
};
$.fn.test = function(options) {
options = $.extend(options, $.test.settings);
return this.each(function() {
$.test(this, options);
});
};
})(jQuery);
$(document).ready(function() {
$('#list').test().css('background-color', 'wheat');
$('#go').click(function() {
$('#list').whiten();
});
});
</script>
</head>
<body>
<button id="go">whiten</button>
<ul id="list">
<li>Aloe</li>
<li>Bergamot</li>
<li>Calendula</li>
<li>Damiana</li>
<li>Elderflower</li>
<li>Feverfew</li>
</ul>
</body>
</html>
and I guess what I'm not sure about is how to make the function assignment. this inside of $.test will refer to the jQuery object wrapped around my list so I would have thought that this.myMethod = function() { would have worked but it doesn't. $(this) would be a double wrapper, el is my list (and I don't want to assign the method directly to the object since I wouldn't be able to call it like this: $('#list').whiten()), and $(el) would be the same as $(this)... so how is this done?
-- update --
I've created a [jsfiddle] to play with the problem
-- update --
I also did try placing the method in the $.fn.test function but to no avail
Try this:
$.fn.test = function(options) {
options = $.extend(options, $.test.settings);
var self = this;
return this.each(function() {
$.test(self, options);
});
};
after much wailing and gnashing of teeth, I figured it out. I'm not sure I understand why it works that way but for now I'm just happy it does!
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://goo.gl/XQPhA"></script>
<script type="text/javascript">
(function($) {
$.test = {
bg: 'white'
};
$.fn.test = function(options) {
options = $.extend({}, $.test, options);
this.whiten = function() {
$(this).css('background-color', options.bg);
};
return this.each(function() {
$.fn.test(options);
});
};
})(jQuery);
$(document).ready(function() {
$('#list').test().css('background-color', 'wheat');
$('#go').click(function() {
$('#list').whiten();
});
});
</script>
</head>
<body>
<button id="go">whiten</button>
<ul id="list">
<li>Aloe</li>
<li>Bergamot</li>
<li>Calendula</li>
<li>Damiana</li>
<li>Elderflower</li>
<li>Feverfew</li>
</ul>
</body>
</html>