Where should I place my custom javascript object? - javascript

Let's say I have the following script
<script type="text/javascript">
$(function($, d) {
var custom = {
settings: { news: $('div.news') },
init: function() { this.settings.news.html('new'); }
}
}(jQuery, $(document)))
</script>
You can assume that the object has more functionality, but my question is where should I place it?
I know two approaches:
Place the script in the <head> tag. That way I will have to make sure the object is called only after document.ready, so the settings jQuery objects ($('div.news')) won't be empty.
The second way is less semantically correct in my opinion, but I can give up the document.ready function: I can just "physically" place the script after the html.
What solution would you prefer and why? Thanks from advance!

Any script that doesn't assist in rendering the layout of the page should be placed at the bottom of the body, preferrably as a reference to a script file (not the script itself). This allows the CSS + HTML to render the page visually, and then the JavaScript (or jQuery, in your case) is applied to the rendered elements.
It does not increase the performance of the page perse, but it does speed up the visual rendering, appearing to provide a faster experience for the end user.
See here for more details.

I place my code like this just before the closing body tag, and run init():
var custom: {
settings: { news: null },
init: function() {
this.settings.news = $('#news');
this.settings.news.html('new');
}
}
custom.init();
Something like that.
Edited to reflect Anthony's comment.

Related

How to print an iFrame with stylesheet?

I've created this code to print data from an iFrame
function (data) {
var frame = $("<iframe>", {
name: "iFrame",
class: "printFrame"
});
frame.appendTo("body");
var head = $("<head></head>");
_.each($("head link[rel=stylesheet]"), function (link) {
var csslink = $("<link/>", { rel: "stylesheet", href: $(link).prop("href") })
head.append(csslink);
;});
frame.contents().find("head")
.replaceWith(head);
frame.contents().find("body")
.append(this.html());
window.frames["iFrame"].focus();
window.frames["iFrame"].print();
}
This creates an iFrame, adds a head to where it sets all the css links that are needed for this website. Then it creates the body.
Trouble is, the styling won't get applied to the print, unless I break at line frame.contents().find("head").replaceWith(head), which means that something in that part is running asynchronously.
Question is, can I somehow get the code to wait for a short while before running that line, or is there perhaps another way to do this? Unfortunately I'm not all that familiar with iFrames, so I have no clue what it's trying to do there.
This turned out to be a real hassle. I've always been reluctant to using iframes, but since there are many resources saying that using an iframe for printing more stuff than what's on the screen, we figured we'd give it a try.
This was instead solved by putting the data inside a hidden div which then was shown before a window.print(). At the same time, all other elements on the page were given a "hidden-print" class which is a class we're already using to hide elements for prints.
This might not be as elegant for the user (The div will show briefly before the user exits the print dialogue), but it's a way more simpler code to use and manage.
I think you could / should move the last focus() and print() calls to a onload handler for the iframe, to get it to happen after styles are loaded and applied.
I've just run into the same issue and did the following:
setTimeout(() => {
window.frames["iFrame"].focus();
window.frames["iFrame"].print();
}, 500)
This appears to have sorted it for me. I hate using timeout and the length is guess work at best but as it's not system critical it's something I can run with for now.

Rerun Jquery function onclick

I have a simple jquery script that changes the url path of the images. The only problem is the doesn't apply after I click the load more button. So I'm trying to do a workaround where it calls the script again after clicking the button.
<script type='text/javascript'>
$(document).ready(function ReplaceImage() {
$(".galleryItem img").each(function() {
$(this).attr("src", function(a, b) {
return b.replace("s72-c", "s300")
})
})
});
</script>
HTML
Load More
While Keith's answer will get you what you are looking for, I really can't recommend that approach. You are much better off with something like this.
<script type="text/javascript">
$(function() {
var replaceImage = function() {
$('.galleryItem img').each(function() {
$(this).attr('src', function(index, value) {
return value.replace('s72-c', 's300');
});
});
};
replaceImage();
$('.js-replace-image').on('click', replaceImage);
});
</script>
Using this html
<button class="js-replace-image">Load More</button>
By taking this approach, you do not expose any global variables onto the window object, which can be a point of issue if you work with other libraries (or developers) that don't manage their globals well.
Also, by moving to a class name and binding an event handler to the DOM node via JavaScript, you future proof yourself much more. Also allows yourself to easily add this functionality to more buttons very easily but just adding a class to it.
I updated the anchor tag to a button because of the semantics of what you need to do - it doesn't link out anywhere, it's just dynamic functionality on the page. This is what buttons are best served for.
I'd also recommend putting this in the footer of your site, because then, depending on your situation, you will already have the images updated properly without having to click the button. The only need for the button would be if you are dynamically inserting more images on the page after load, or if this script was in the head of your document (meaning jQuery couldn't know about the images yet).
I hope this helps, reach out if you have questions.

jquery not quick enough to take effect

I have a need to add a class to certain pages - ones that contain an ID of #hero. For all other pages, the class must not be added.
Because I'm using asp.net with a few layered master pages, its not as simple as just adding a class directly to the html becuase the body tag sits a couple of pages above the aspx page.
I could locate the body tag, but so far I've tried to avoid that due to the added complexity, and instead tried to use jquery.
Here's the code:
$(document).ready(function () {
updateBodyClasses();
});
function updateBodyClasses() {
if($("#hero")) {
$("html, body").addClass("hero");
}
}
Nothing complicated, but here's the rub. By the time the class has been appended, the page has been rendered and the class doesn't seem to have any effect. However, if I test it by adding the class directly to the html, it works - so I know the CSS works and that its a timing issue.
I suppose I could add the code higher up the page - jquery is deferred, so I would need to know the equivalent javascript to try it out.
Would appreciate any thoughts on this potential solution, or perhaps and other ideas.
/* UPDATE */
For clarity, it seems to be the HTML related class that isn't being applied.
You can alter the DOM without waiting for it to be ready.
You need to:
load jQuery in a synchronous way(without defer or async).
Put #hero element i above the script.
Please consider this example:
.red {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="hero">I don't care about DOM being ready</div>
<script>
var $el = $('#hero');
if ($el.length) {
$el.addClass('red');
}
</script>
You can use IIFE(Immidiately Invocked Function Expression):
like:
(function()
{
if($("#hero")) {
$("html, body").addClass("hero");
}
})();
just put your function in document ready like
$(function(){
if($("#hero")) {
$("html, body").addClass("hero");
}
});
No real solution provided.
Not reasitic to change the whole site infrastructure - from one that defers jquery to loading it synchronously.
The two other jquery answers are as per the current setup and don't work.
The only working solution was provided by Tushar, although it would still require selective loading of the script, which was not included in the answer.
In the end, I used a workaround, which bypassed the need for any javascript. Instead of selectively adding a class to html tag, I added the css permanently to the html tag, affecting all pages. I then added an inner div, which reverses it out. This means that any page can now manipulate its own functionality directly without having to add classes to the html tag.

Call function anytime a link is moused over on an arbitrary page?

I apologize for the possibly naive nature of this question but I am not a web developer by day.
Is it possible to write a script such that, for any arbitrary web page, a function that I have written will be called if a URL is moused over? I was initially thinking that I could use document.links to assemble an array of all of the hrefs in a document and add an onmouseover event attribute to each of them but, unless I'm mistaken, that would overwrite any existing onmouseover attributes already present in the page. Not ideal.
I'm not sure if by arbitrary web page you mean any pages on any domains or any pages of your own domain, but for the latter you could put something like the following in your pages:
$(function () {
$(document).on('mouseenter', 'a', function () {
console.log(this, 'hovered');
});
});
If you mean any page your browse to on the net, then you will have to write a browser extension for the browser your are using. For Chrome have a look at this.
You could try getting everything with the a tag and inject an onmouseover.
window.onload = function(){
for(m=0;m<document.getElementsByTagName('a');m++){
if(document.getElementsByTagName('a')[m].className == 'someclass'){
document.getElementsByTagName('a')[m].onmouseover = function(){
Your Code
}
}
}
}

JQuery load() will break facebook like button/comment box. How to workaround?

I am coding a big website but I have cut down my problem into the following tiny html file:
http://dl.dropbox.com/u/3224566/test.html
The problem is that if I (re)load with JQuery a content that features a facebook code, the latter won't appear, even if I reload the script (leading to a duplication of that all.js script, which is another issue).
How can I fix this?
Regards,
Quentin
Use the FB.XFBML.parse() docs after you load the new content
function loadPage() {
$('#test').load('test.html #test', function() {
FB.XFBML.parse( );
}).fadeOut('slow').fadeIn('slow');
}
Note, that loading a fragment with id test in a div with id test will create multiple (two) elements with the same id (nested in each other) in the page, which should never happen as it is invalid.
To avoid this use the more verbose $.get method
$.get('test.html',
function(data) {
var temp = $('<div>').html(data).find('#test');
$('#test').html(temp.html());
}
);

Categories