jQuery + Module Pattern: When to declare/query elements? - javascript

Typically, you don't start querying the DOM until the $(document).ready().
In both of the options below, the Widget is declared (and the elements are queried) outside of the $(document).ready().
Is this OK? Can I initialize the jQuery elements (as long as I'm not manipulating anything), OUTSIDE of the ready handler?
Would it be better to put this whole Widget definition inside the $(document).ready()?
Should I wait until the Widget.init() to query the elements?
Note: I'm brand new to JS design patterns, so please note if I'm missing something
Option1
Widget = {
ele : $('#ele'),
init : function(){ ... }
};
$(document).ready(function(){
Widget.init();
});
Option2
Widget = (function(){
var privateEle = $('#privateEle');
return {
publicEle: $('#publicEle'),
init: function(){ ... }
};
}());
$(document).ready(function(){
Widget.init();
});

What I would do:
var Widget = (function(){
var ele;
function init(_ele){
ele = _ele;
};
return {
init: init
};
})();
$(function(){
Widget.init( $('#foo') );
});
If your script is loaded before jquery, you will not see an error "undefined is not a function". But, if you perform a query before domReady, you could get unexpected result, ele = []
EDIT: btw.. put your <script> tags before </body> NOT within <head></head>

It won't work because at the time when you query the element, the element is not there yet, thus your query will return an empty jQuery selection. You can only query for elements when the DOM is ready.
what would work though is on of the following:
create the element outside $(document).ready(). note that you have to provide the full html or work with $(..).attr(x,y) and the likes.
Widget = {
ele : $("<div id='ele'>"),
....
}
or you can query the element on widget initialization.
Widget = {
ele : "#ele",
init : function(){
this.ele = $(this.ele);
...
}
}

You can include script just before body end tag.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Demo</title>
</head>
<body>
<!-- my HTML -->
<script src="../js/vendor/jquery-1.9.1.js"></script>
<script src="../js/vendor/jquery-migrate-1.1.1.js"></script>
<script src="../js/custom.js"></script>
</body>
</html>
DOM is ready (no need for $(document).ready):
/*custom.js */
var Widget = (function($){
var _$element;
return {
init: function(){
_$element = $('#myElementId');
// TODO - element is available from now on
};
};
}(jQuery));
Widget.init();

Related

improve code on updating content inside div

I learned that you can update a content inside div by using jQuery. I want to improve this code as the content is being change after it loads. I want it to be permanent regardless if it's loading or not.
Here's my code.
function changeContent () {
var myelement = document.getElementById("topbarlogin");
myelement.innerHTML= "HELLO";
}
window.onload = changeContent ;
This is my html code
<div class="signuplink" id="topbarlogin">Login</div>
Either call your function at the end of your body tag without window.load in script tag...
It will execute function() faster than the window.load
Stack Snippet
<body>
<div class="signuplink" id="topbarlogin">Login</div>
<script>
function changeContent() {
var myelement = document.getElementById("topbarlogin");
myelement.innerHTML = "HELLO";
}
changeContent();
</script>
</body>
...Or you can use DOMContentLoaded EventListener...it is equivalent to the $(document).ready() jQuery
function changeContent() {
var myelement = document.getElementById("topbarlogin");
myelement.innerHTML = "HELLO";
}
document.addEventListener("DOMContentLoaded", function(event) {
changeContent();
});
<div class="signuplink" id="topbarlogin">Login</div>
On DOM Ready use .html() to set HTML of div.
// This is you DOM Ready
$(function(){
// Set HTML using jQuery
$("#topbarlogin").html("HELLO");
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="signuplink" id="topbarlogin">Login</div>
Please try this
$("#topbarlogin").html("Hello");

Can some tell me where is the error? saying $ not defined, object expected

saying $ not defined, object expected.. actually i want to verify if all set of radio button check when a button is clicked! help plz
<script type="text/javascript">
$(document).on('click', 'form', function () {
var validate = true;
var unanswered = new Array();
// Loop through available sets
$('.qselections').each(function () {
// Question text
var question = $(this).prev().text();
// Validate
if (!$(this).find('input').is(':checked')) {
// Didn't validate ... dispaly alert or do something
unanswered.push(question);
validate = false;
}
});
if (unanswered.length > 0) {
msg = "Please answer the following questions:\n" + unanswered.join('\n');
alert(msg);
}
return validate;
});
</script>
Did you forget to include the jquery.js file in your markup before your code?
A generally accepted way to set up your script references is as follows (there are others, this isn't the be-all-end-all):
<html>
<head>
</head>
<body>
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="MyScriptFile.js"></script>
<script>
$(function() {
$(document).on('click', 'form', function () {
var validate = true;
var unanswered = new Array();
// Loop through available sets
$('.qselections').each(function () {
// Question text
var question = $(this).prev().text();
// Validate
if (!$(this).find('input').is(':checked')) {
// Didn't validate ... dispaly alert or do something
unanswered.push(question);
validate = false;
}
});
if (unanswered.length > 0) {
msg = "Please answer the following questions:\n" + unanswered.join('\n');
alert(msg);
}
return validate;
});
</script>
</body>
</html>
This way you can be sure that (1) your page is loaded before any scripts try to do scripty things and (2) you have included jQuery before other scripts which may want to use it.
This is not foolproof, and you may (eventually) need to use something like Require.js or as a simpler step the defer attribute.
1.Have you included Jquery lib in first script tag in your head section. In that case only your jquery based code will execute.
2.Did you wrap the code into $(document).ready() function.
3 Are you using PHP at your corners. So need to replace $ with Jquery.

How to use jquery in a external .js file?

In my website, there include such 2 files: index.php, script.js
Of course, it is much more complicated in the web site and the above only shows a part of it.
In index.php, there is a div element
<div id="phb29" class="drag ph hour01">Testing</div>
In script.js,which is a pure javascipt file,below show a part that i want to use a jquery function .switchClass() (from http://api.jqueryui.com/switchClass/) to switch the class of div element.
//... other normal js codes
switchClassHour = function(){
$(function (){
$( "#phb29" ).switchClass( "hour01", "hour03", 1000 );
return false;
});
}
//other normal js codes...
I only want to call that jquery when I call the switchClassHour() function but not the web page is loaded(i.e. $(document).ready(function (){...}); )
I have included the source in the in index.php:
<script src="//code.jquery.com/jquery-1.9.1.js"></script>
<script src="//code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
<script type="text/javascript" src="script.js"></script>
But finally, the chrome browser gives me this error occurring at the line $(function (){ when I trigger switchClassHour():
Uncaught TypeError: boolean is not a function
What should I do, thank you !!!!! :):)
The variable toHour does not appear to be defined within the function switchClassHour.
Try this
switchClassHour = function(){
/* `toHour` ? */
if (window.jQuery) {
/* $(function (){ */
$( "#phb29" ).switchClass( "hour01", "hour03", 1000 );
/* `return false;` ? */
/* }); */
};
};
switchClassHour(); /* just noticed, is the function actually called ? */
Edit
Try this
switchClassHour = function(){
/* `toHour` ? */
if (window.jQuery) {
/* $(function (){ */
console.log($.now())
/* `return false;` ? */
/* }); */
};
};
switchClassHour();
Is $.now() return'ed at console?
Is $ utilized in other parts of non-jquery pieces?
See also https://api.jquery.com/jQuery.noConflict/
Edit
Try this
switchClassHour = function() {
jQuery.noConflict();
(function( $ ) {
console.log($.now(), jQuery.now())
})(jQuery);
};switchClassHour();
Hope this helps
function switchClassHour(){
if(document.getElementById('jq')){
//original switchClassHour() code.
}
else{
var jq = document.createElement('script');
jq.src = "WHATEVER SOURCE YOU WANT TO LOAD FROM (PROBABLY GOOGLE)";
jq.id = "jq";
document.getElementsByTagName('head').item(0).appendNode(jq);
//Original switchClassHour() code
}
}
I don't know if this is guaranteed to work since I don't know if you'll be able to load jQuery fast enough to call your function immediately afterwards. If this doesn't work because jQuery isn't loading fast enough then the only outcome I could see is adding a delay but that's ugly. To be honest if you're using jQuery I would just load it from Google normally in the <head> of your page. Most people have it cached already.

$.html renders script as content

For a project i'm dynamically loading content that consist of html and javascript. Until now i was using jquery 1.8.3 but while cleaning up i wanted to update to 1.10.1.
I've narrowed my problem down to the way i use the $.html() function on my content div.
In jquery 1.8.3:
var content = $("#content");
contentDiv.html("<script> alert('Testing'); </script>")
shows a alertbox with the content 'Testing', while in newer jquery versions the same code the string is inserted into the DOM and then the alertbox also appears. I'd wish to not have the tags shown.
context javascript:
this.loadPage = function(page, callback){
$.get(page.ViewFile, function(view){
var content = $("#content");
$("#content").html(view);
}};
The page getting loaded contains, which is stored in the variable view as a string.
<h1>New Content</h1>
<div id="newContent"></div>
<script>
function View(){
this.InitializeView = function(model){
//code
}
this.UpdateView = function (model){
//code
}
}
</script>
Seems that the browser detect the </script> (the end of script tag) that is inside of string as a real closing when we put our code in the head of page.
This is the reason why the error is thrown in the webpage (EXAMPLE):
Uncaught SyntaxError: Unexpected token ILLEGAL fiddle.jshell.net/:22
I guess that you have to move your javascript code into a separate file like main.js, for example.
Tested it locally and it works:
HTML
<html>
<head>
<script src="http://code.jquery.com/jquery-1.10.1.js"></script>
<script src="main.js"></script>
<script type="text/javascript">
setTimeout(function () {
$("body").text("Testing now from HTML: using <script>");
setTimeout(function () {
$("body").html("<script>alert('This alert will fail.')</script>");
}, 1000);
}, 2000);
</script>
</head>
<body></body>
</html>
Javascript (main.js)
$(document).ready(function () {
$("body").html("<h1>Wait one second.</h1>");
setTimeout(function () {
$("body").html("<script>alert('Tested')</script>");
}, 1000);
});
Even the text editors detect it as closing tag:
Solution
1. Create scripts from jQuery
var content = $("#content");
var script = $("<script>");
script.html("alert('Testing');");
content.append(script)
1. Use &
Basically you have to replace < with &lt, > with &gt and & with &amp, as described in this answer:
var tagsToReplace = {
'&': '&',
'<': '<',
'>': '>'
};
function replaceTag(tag) {
return tagsToReplace[tag] || tag;
}
function safe_tags_replace(str) {
return str.replace(/[&<>]/g, replaceTag);
}
For more information see this question.

The difference between using a self invoking function and document ready

How come this doesn't work in loading header content...
(function ($) {
var mheaderwrapper = '<div id="header"></div><div class="header-menu"></div>';
var mheadercontent = '/shop/Pages/global_header.html';
var mmenucontent = '/shop/Pages/global_megamenu.html';
var mjqueryhover = 'js/jquery.hoverIntent.minified.js';
var mjquerymenu = 'js/jquery.custom-menu.js';
$('#wrapper').prepend(mheaderwrapper);
$('#header').load(mheadercontent);
$('.header-menu').load(mmenucontent, function(){
$.getScript(mjqueryhover);
$.getScript(mjquerymenu);
});
})(jQuery);
but this does...
$.mheader = function() {
var mheaderwrapper = '<div id="header"></div><div class="header-menu"></div>';
var mheadercontent = '/shop/Pages/global_header.html';
var mmenucontent = '/shop/Pages/global_megamenu.html';
var mjqueryhover = 'js/jquery.hoverIntent.minified.js';
var mjquerymenu = 'js/jquery.custom-menu.js';
$('#wrapper').prepend(mheaderwrapper);
$('#header').load(mheadercontent);
$('.header-menu').load(mmenucontent, function(){
$.getScript(mjqueryhover);
$.getScript(mjquerymenu);
});
}
$(function() {
$.mheader();
});
This :
(function ($) {....})(jQuery);
executes immediately, and only maps jQuery to $ to make sure the dollar sign really is "jQuery" within the self executing function. It's not a "DOM ready" function.
This:
$(function() {....});
will wait until the DOM is ready before any code is executed.
You can use the second one inside the first one :
(function ($) {
$(function() {
//code here
});
})(jQuery);
to do both!
When you have a function in the <head> section like that, it is executing immediately, and is doing so before your HTML elements have started loading. Your elements #wrapper, #header, and anything with the .header-menu class do not yet exist at the time your code is executing, which is why it fails.
In the second example, using the domready event delays the firing of your code until after the DOM is ready (and your HTML elements exist), so the code works.
By the way,
$(function() {
// executes when DOM is ready
});
is just a shortcut for:
$(document).ready(function() {
// executes when DOM is ready
});
The above examples are specifically functionality provided by jQuery. Don't confuse the former with the immediately-executing function structure, which is pure JavaScript:
(function() {
// executes NOW
})();
See adeneo's answer for how to properly combine the two.
$(document).ready actually runs after the DOM is created.
Self-invoking functions run instantly if inserted into <head> section, before the DOM is constructed.

Categories

Resources