Reprocess code for a dynamically loaded "widget"? - javascript

I have the following code that loads a tile, or "widget", in my UI. Occasionally (like on orientation change) I have to redraw the tiles. Some of the content is generated by a script load event. During the redraw, this event is not getting loaded again. How can I accomplish this?
//html
let $elTile = $('<div/>').appendTo($elContainer);
$elTile.load('tiles/' + tile.name + '/' + tile.name + '.html #' + tile.name + '-content');
//javascript
$.getScript('tiles/' + tile.name + '/' + tile.name + '.js');
//css
$('head').append( $('<link rel="stylesheet" type="text/css" />')
.attr('href', 'tiles/' + tile.name + '/' + tile.name + '.css'));
And here is what one of the tile script files looks like:
window.addEventListener("load", function() {
//do some stuff that may need to be called again on orientation change
});
I see from questions like this and this that I probably can't just "unload and reload" the script, so is there another way to process the "tile initialization" script again?
Orientation Change was just an example, I'd like to be able to call the tile init script arbitrarily if possible.

Depending on your device support and requirements, you could do a few things.
One would be to deal with this by also adding orientationchange to your event listener.
$(window).on('load orientationchange', function(){ /* run your code for both*/});
Another option would be to use the resize event.
The former would be device specific as all browsers act differently, as mentioned in this post.
UPDATE:
You can also create an anonymous event based function that you can call at will using your event as the trigger. For example.
$(window).on('myCustomEvent', function(){ /*whatever code you want to run at any time*/});
Then you can trigger such event from any logic point you need:
if ($(window).width() < 1024){
$(window).trigger('myCustomEvent');
}

You can use other events, like "orientationchange"
https://developer.mozilla.org/en-US/docs/Web/Events/orientationchange
Or you can recall the load function like this:
var myFunction = function () {
//do some stuff that may need to be called again on orientation change
};
window.addEventListener("load", myFunction);
window.addEventListener("orientationchange", myFunction);
...
And you can call it again anytime just using myFunction();

Related

Add CSS to DIV in an Iframe

I have an Iframe with id="scorm_object".
<iframe id="scorm_object">...</iframe>
Inside this iframe i have a class called framewrap.
I am trying to add CSS to this class like so:
$(document).ready(function() {
$('#scorm_object').contents().find('.framewrap').css('opacity','.2');
});
but I can't seem to get it to work.
I know there are multiple iframe examples on here, but I am really looking for something nice and simple.
Thanks!
Update: Apologies, I have to make this work without jquery.
I have now tried the following:
var iframe = document.getElementsByTagName('iframe')[0];
iframe.addEventListener("load", function() {
window.frames[0].document.body.style.backgroundColor = "#fff";
});
but I get the :
iframe is undefined
error.
Your are firing the JavaScript when the DOM of the parent document is ready. This is likely to happen before the document in the frame is ready.
Waiting for the load event to fire fixed that when I tested it.
Use $(window).on("load", function() { instead of $(document).ready(function() {.
I think this one will work. Change the CSS after iframe loaded
$('#scorm_object').load(function() {
$('#scorm_object').contents().find('.framewrap').css('opacity','.2');
});
If you want to do it in pure javascript you should do something like this. Create an style element and add necessary styles using textContent property and add that style to the of iframe.
var iFrame = document.getElementById("scorm_object");
var style = document.createElement("style");
style.textContent =
'#framewrap{' +
' opacity: 0.2;' +
'}' +
'h1 {' +
' color: green;' +
'}'
;
iFrame.addEventListener ("load", function () {
iframe.contentDocument.head.appendChild(style);
});
The above method doesn't work with cross-domain.
You check this out window.postMessage

append content, scrollTo it, hide old content

I would like to implement the following animation effect;
http://jsfiddle.net/YKmu2/37/
This is the core code;
$("#c1").on( "click", function(event) {
event.preventDefault();
new_site = 'content1';
if(site == new_site) { $('[name="' + new_site + '"]').show(); }
else {
$('[name="' + new_site + '"]').insertAfter('[name="' + site + '"]');
$('[name="' + new_site + '"]').show();
$.scrollTo('[name="' + new_site + '"]', 1000);
}
setTimeout(function() {
$('[name="' + site + '"]').hide();
$.scrollTo('[name="' + new_site + '"]');
site = new_site;
}, 1005);
});
When you click on one of the links, the content associated with this link is appended to the current content and a scroll animation is executed using the scrollTo plugin.
After the scroll animation is finished, the old content is removed/hidden.
That works all fine as long as the user is clicking on a link and is waiting until everything is finished.
However when you start to click on multiple links while the animation is not finished a lot of weird things are happening.
Does someone have an idea how to fix this / make it reliable and error-proven?
Or does somebody know a jquery plugin that already implements such an effect?
Thank you!
This is a relatively common problem of animation queueing and only triggering the action if there are no animations already happening, however in this case you need to be checking if the page is scrolling or not, which is a little more abstract in a sense.
UPDATED BELOW TO FIX SCROLLING ISSUE:
I've updated your fiddle here: http://jsfiddle.net/andyface/77fr6/ to demonstrate checking to see if the page has scrolled to the top before triggering a change in content.
Current working fiddle: http://jsfiddle.net/andyface/77fr6/1/
I've also taken some liberties with making your code a little easier to manage, which I hope is actually helpful. Essentially I've made things work based on classes instead of individual IDs, so you only have to maintain one bit of code and if you need to expand it, you don't have to add more blocks of code, just a few extra lines to get the ID, however this could be made to do it all cleverly enough to not even need that.
The main changes I've made are as follows:
The links now have a class of link and content a class of content.
The IDs of the links are then used to extrapolate the content they are meant to be triggering.
I've also removed the timeout and used the scrollTo() callback feature as this will be more reliable.
Finally I added a check to see if the page had scrolled to the top before allowing the action to trigger
Hope this helps, but let me know if you need anything more explaining
UPDATE:
Seeing I missed the fact that by limiting the action by scroll position this would stop them working if the user scrolled down, I've changed how the action blocking works.
$(document).ready(function() {
// HIDE CONTENT
$('.content').hide();
var site = '',
scrolling = false;
$(".link").on( "click", function(event) {
// THIS IS JUST USED FOR TESTING TO SEE WHAT THE scrollTop() POSTION IS WHEN CONTENT IS SCROLLED - REMOVE console.log() WHEN IN PRODUCTION
console.log($(window).scrollTop());
event.preventDefault();
// ONLY RUN THE SCRIPT IF THE PAGE HAS SCROLLED TO IT'S FINAL POSITION
if( ! scrolling)
{
var new_site = null;
switch($(this).attr('id')) {
case 'c1':
new_site = 'content1';
break;
case 'c2':
new_site = 'content2';
break;
case 'c3':
new_site = 'content3';
break;
}
if(site != new_site) {
// KEEP A TRACK OF IF THE PAGE IS SCROLLING OR NOT
scrolling = true;
$('#' + new_site).insertAfter('#' + site);
$('#' + new_site).show();
$.scrollTo('#' + new_site, 1000, function() {
// CALLBACK TRIGGERED WHEN SCROLLING HAS FINISHED
$('#' + site).hide();
$.scrollTo('#' + new_site);
site = new_site;
// TELL THE PAGE IT'S OK TO DO STUFF COS WE'RE NOT SCROLLING IT ANYMORE
scrolling = false;
});
}
}
});
});
http://jsfiddle.net/andyface/77fr6/1/

'Overlay transparent image' jQuery breaks when new class is added

I found this script HERE to overlay a transparent image over photos that I would like to 'protect' on my site. On images that have hyperlinks, I would like be able to give them a special class and make them accessible.
Here is the original script:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript">
$(function() {
var pixelSource = 'http://static.squarespace.com/static/51c351f0e4b0c89ff2b61cb8/t/52cc3905e4b0167d33cd524e/1389115653884/Transparent.gif';
var useOnAllImages = true;
// Preload the pixel
var preload = new Image();
preload.src = pixelSource;
$('img').live('mouseenter touchstart', function(e) {
// Only execute if this is not an overlay or skipped
var img = $(this);
if (img.hasClass('protectionOverlay')) return;
if (!useOnAllImages && !img.hasClass('protectMe')) return;
// Get the real image's position, add an overlay
var pos = img.offset();
var overlay = $('<img class="protectionOverlay" src="' + pixelSource + '" width="' + img.width() + '" height="' + img.height() + '" />').css({position: 'absolute', zIndex: 9999999, left: pos.left, top: pos.top}).appendTo('body').bind('mouseleave', function() {
setTimeout(function(){ overlay.remove(); }, 0, $(this));
});
if ('ontouchstart' in window) $(document).one('touchend', function(){ setTimeout(function(){ overlay.remove(); }, 0, overlay); });
});
});
</script>
I was told to change this line:
$('img').live('mouseenter touchstart', function(e) {
To this:
$('img').not('.FreeMe').live('mouseenter touchstart', function(e) {
... and give the images I want to be clickable the class of '.FreeMe'.
When I run the script with no changes, the transparent overlays work great. Once I change that line of code and add the special class, all of the images become accessible again and the script no longer works.
HERE is a link to the page I've been working on. The Photographers information at the bottom of the screen is the image I would like to add a hyperlink to.
I have been searching high and low in order to make this work but was unable to find a solution to the problem. I'm very new to Javascript and jQuery, but know just enough in CSS and HTML to be dangerous.
I appreciate any help you all could provide.
You should use the .on() method instead of .live(), since the .live() method can't be chained like other jQuery methods (the params are just the same).
Quoting jQuery's doc on .live():
Use of the .live() method is no longer recommended since later
versions of jQuery offer better methods that do not have its
drawbacks. In particular, the following issues arise with the use of
.live():
• Chaining methods is not supported. For example, $( "a" ).find(
".offsite, .external" ).live( ... ); is not valid and does not work
as expected.
Plus, as said in the comments, as of jQuery 1.7, the .live() method is deprecated.
You an see a working demo with adorable kittens here.

How to detect when -webkit-mask-box-image has downloaded

I generate an mask image on a web server programmatically, then apply it to a HTML element with the following code:
imageToMask.style["-webkit-mask-box-image"] = "url('" + featherURL +"') 100 stretch";
How can I find out when the image comes back and has finished downloading, so that it doesn't just pop onto the page?
You can probably do something similar to what #lonesomeday did in:
jQuery .on() not bound when script inserted into the DOM
Something along these lines:
$('button').click(function() {
var imageToMask = document.createElement('img');
imageToMask.style["-webkit-mask-box-image"] = "url('" + featherURL +"') 100 stretch";
imageToMask.onload = function() {
//Custom behaviour
};
document.body.appendChild(imageToMask);
});

jQuery ATTR funk in IE

I am dynamically creating javascript and attaching it to the onclick event of links on my page using $(document).ready()
My onclick javascript is used to generate event functions that I am passing to Google Analytics to track events on my page, such as clicks on banners and downloaded PDFs. I am getting stats in Google Analytics for these events from every browser except for IE. So, something is wrong with my code in IE (I have searched and searched for errors on my page, there are none).
Normally I would just do something like $("a").click ... do stuff ... but for whatever reason, the only way I could get the Google Analytics event tracking to work was by putting the tracking event function directly on my links. So I'm using the following code to inject the tracking event function into my link's onclick once the page loads....
// Tracks favorites on the home page.
$("._gatHomePageFavorites").each
(
function(index)
{
var description = "Content ID: " + getParameterNamedID($(this).attr("href")) + " - " + $(this).children().first().attr("alt");
$(this).attr("onclick","alert('1');_gaq.push(['_trackEvent', 'Favorites - Home Page', 'Icon Click','" + _gatCleanString(description) + "']);alert('2');");
}
);
I think my problem is that IE is not putting my code on the onclick. But I don't know of a good way to view the generated source in IE. I have tried a couple of javascript functions in the address bar to bring up the generated source, assuming they work, then my code is not injecting the tracking event function into my link's onclick for IE. I see the tracking event function in the onclick in Firefox's view generated source.
As another test, you can see I added alerts around my tracking event funciton. In FF both alerts trigger, In IE neither alert triggers.
One more piece of info. My Google Analytics is not recording events for any IE browser. As far as I can tell, my issue is not specific to one version of IE.
How can I tell if my dynamic javascript is getting into the onclick for IE, and then what can I do to get it into the onclick for IE?
UPDATE
To simplify the problem and to focus the direction of the answers, I removed the Google Analytics event function. Now, all I am doing is injecting alert() into the onlick. IE won't even trigger the alert(). I have tried the following...
// Tracks favorites on the home page.
$("._gatHomePageFavorites").each
(
function(index)
{
$(this).attr("onclick","alert('1')");
}
);
and
// Tracks favorites on the home page.
$("._gatHomePageFavorites").each
(
function(index)
{
$(this).attr("onclick","setTimeout(\"alert('1')\", 1000);return false");
}
);
So I'm still leaning towards my javascript is not being injected into the onclick in IE.
What is the most reliable way to view generated source in IE?
If I can confirm that my code is not being injected into the onclick attribute of the link, then I can at least have an answer as to why Google Analytics isn't tracking events for IE. It would be because my injected code does not exist in IE.
You should not be adding the 'onclick' attr, but rather using this using jQuery .click() event.
function(index){
var description = "Content ID: " + getParameterNamedID($(this).attr("href")) + " - " + $(this).children().first().attr("alt");
$(this).click(function() {
alert('1');
_gaq.push(['_trackEvent', 'Favorites - Home Page', 'Icon Click', _gatCleanString(description)]);
alert('2');
});
}
something like above, sorry wrote this quick, so might have a typo.
Slim chance, but if you have any VBScript on your page then you should prepend your onclick string with "javascript:"
You could just use the time-honoured DOM0 onclick property, though there's really no decent reason why jQuery's click() method wouldn't work.
$("._gatHomePageFavorites").each
(
function(index)
{
var $this = $(this);
var description = "Content ID: "
+ getParameterNamedID($this.attr("href")) + " - "
+ $this.children().first().attr("alt");
this.onclick = function() {
alert('1');
_gaq.push(['_trackEvent', 'Favorites - Home Page', 'Icon Click',
_gatCleanString(description)]);
alert('2');
};
}
);
jQuery's attr() method is generally not useful, but that's a whole different rant.
Something to be aware of tracking links is that if the browser leaves the page before the tracking pixel is fetched, the event may not be recorded, depending on the browser, computer, & network speed. I've had good luck with the following (modified from #Tim Down's code):
$("._gatHomePageFavorites").each
(
function(index)
{
var $this = $(this);
var description = "Content ID: "
+ getParameterNamedID($this.attr("href")) + " - "
+ $this.children().first().attr("alt");
$this.click(function(e) {
alert('1');
_gaq.push(['_trackEvent', 'Favorites - Home Page', 'Icon Click',
_gatCleanString(description)]);
if ($this.attr('target') != '_blank') {
e.preventDefault();
setTimeout('document.location = "' + $this.attr('href') + '"', 150);
}
});
}
);
Essentially, if the link isn't opening in a new window, wait and follow it ourselves.
It turns out that my problem had nothing to do with Google Analytics or it's tracking event. After a lot of testing, I finally determined that in IE, jQuery's $().attr() was not working.
The odd thing was that it didn't break or throw an error. IE just ignored it somehow and would not add my dynamic javascript to the onclick parameter of the anchor tag.
Solutions...
The obvious one is to bind to the event like everyone suggested. If you can use $().click() then I agree, use it, always. Never use $().attr("onclick","do something");
However other circumstances in my project prevented me from using $().click(). I was unable to get stats into Google Analytics using it's event tracking function unless the event tracking function was inline on the anchor tag.
Went old school...
$(".obj").each
(
function (index) {
this.setAttribute("onclick", "alert('It is Working');");
}
);
Thanks for everyone's help.

Categories