Safari print with Javascript produces blank when printing an Iframe - javascript

I have read up on all issues regarding Safari and blank printing. It seems that a white flash happens, re-rendering the page, and content of the iframe is lost before a print dialog can grab it.
Here is my javascript - It works in all browsers except safari. It brings up the dialog, but prints a blank page.
function PrintPopupCode(id) {
framedoc = document;
var popupFrame = $(framedoc).find("#" + id + '\\!PopupFrame');
var icontentWindow = popupFrame[0].contentWindow || popupFrame[0].contentDocument;
icontentWindow.focus();
icontentWindow.print();
}
function PrintPopup(id) {
setTimeout(function () { PrintPopupCode(id) }, 3000);
}
I have set a timeout, i previously read it would help if the transfer of content took sometime, but it has not helped.
I have also tried with printElement() function on the icontentWindow variable, but it does not support this method.
Print Element Method
This is all in a .js file, and not on the page. I have tried on the page, but the same thing happens.
Help?

Maybe you should try this:
function PrintPopupCode(id) {
framedoc = document;
var popupFrame = $(framedoc).find("#" + id + '\\!PopupFrame');
var icontentWindow = popupFrame[0].contentWindow || popupFrame[0].contentDocument;
icontentWindow.focus();
setTimeout(icontentWindow.print, 3000);
}
function PrintPopup(id) {
PrintPopupCode(id);
}

Related

How to detect page loading error from extension?

Is there a way to detect if tab shows 'error page'?
I mean, for example, if user enters any http://non-existing-url.com or just site is unavailable.
Anything similar to Chrome's webNavigation.onErrorOccured event.
If there is no similar event, perhaps there is a way to check Tab http status (200, 404, 502, 0, etc...)?
Whoops didn't see this topic. Here is how you can do it look for about:neterror load
from: mozillaZine :: Detecting “problem loading page” in firefox
have to read the docuri through the webNavigation of the browser. because the window.location is different
anyways the docuri is real nice when an error it happens. it clearly tells you whats wrong with it in the e parameter.
theese are examples of some docuris that load:
about:neterror?e=dnsNotFound&u=http%3A//www.cu.reporterror%28%27afew/&c=UTF-8&d=Firefox%20can%27t%20find%20the%20server%20at%20www.cu.reporterror%28%27afew.
about:neterror?e=malformedURI&u=about%3Abalk&c=&d=The%20URL%20is%20not%20valid%20and%20cannot%
you can see the first one is dnsNotFound and the second one is malformedURI
var listenToPageLoad_IfProblemLoadingPage = function(event) {
var win = event.originalTarget.defaultView;
var webnav = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation);
//console.log('webnav:', webnav, 'webnav of selectedtab:', window.gBrowser.webNavigation);
var docuri = webnav.document.documentURI; //can also try event.originalTarget.linkedBrowser.webNavigation.document.documentURI <<i didnt test this linkedBrowser theory but its gotta be something like that
var location = win.location + ''; //I add a " + ''" at the end so it makes it a string so we can use string functions like location.indexOf etc
if (win.frameElement) {
// Frame within a tab was loaded. win should be the top window of
// the frameset. If you don't want do anything when frames/iframes
// are loaded in this web page, uncomment the following line:
// return;
// Find the root document:
//win = win.top;
if (docuri.indexOf('about:neterror') == 0) {
Components.utils.reportError('IN FRAME - PROBLEM LOADING PAGE LOADED docuri = "' + docuri + '"');
}
} else {
if (docuri.indexOf('about:neterror') == 0) {
Components.utils.reportError('IN TAB - PROBLEM LOADING PAGE LOADED docuri = "' + docuri + '"');
}
}
}
window.gBrowser.addEventListener('DOMContentLoaded', listenToPageLoad_IfProblemLoadingPage, false);

How to combine ContentFlow and ColorBox

I am trying to combine ContentFlow (http://jacksasylum.eu/ContentFlow/) and ColorBox (http://www.jacklmoore.com/colorbox/): when the user clicks on an image in ContentFlow I want an HTML page to be displayed in ColorBox.
I have tried using the code provided by the ColorBox examples' section to no avail. The HTML page is loaded by the browser as a normal link (not in ColorBox.)
I have even tried creating a ContentFlow addon (using the LightBox addon as an example) without any luck - nothing is displayed, not even simple images:
onclickActiveItem: function (item) {
var content = item.content;
if (content.getAttribute('src')) {
if (item.content.getAttribute('href')) {
item.element.href = item.content.getAttribute('href');
}
else if (! item.element.getAttribute('href')) {
item.element.href = content.getAttribute('src');
}
if (item.caption)
item.element.setAttribute ('title', item.caption.innerHTML);
colorbox.show(item.element);
}
}
Edited on 01/Oct/2013
The problem only manifests itself when an item contains an href. To prove this I changed the code above to show a static web page:
$.colorbox({open:true, href:"http://mysite.gr/colorbox/content/static.html"});
It the item is just a simple image the static web page is displayed in ColorBox. But if the item contains an href to the web page I want displayed in ColorBox the browser follows the link and loads the specified page. Any ideas on how to stop this from happening?
Thank you in advance for your help!
I have finally solved the problem I have described in my question. The solution involves creating a ContentFlow addon as follows:
new ContentFlowAddOn ('colorbox', {
init: function () {
var colorboxBaseDir = this.scriptpath+"../colorbox/";
var colorboxCSSBaseDir = colorboxBaseDir;
var colorboxImageBaseDir = colorboxBaseDir;
this.addScript(colorboxBaseDir+"jquery.colorbox.js");
this.addStylesheet(colorboxCSSBaseDir+"example3/colorbox.css");
},
ContentFlowConf: {
onclickInactiveItem: function (item) {
this.conf.onclickActiveItem(item);
},
onclickActiveItem: function (item) {
var content = item.content; // ContentFlow's content class
var theItem = item.item; // ContentFlow's item class - if you need access to it
var hrefToDisplay = '';
if (content.getAttribute('src')) {
if (content.getAttribute('href')) {
hrefToDisplay = item.content.getAttribute('href');
}
else if (!item.element.getAttribute('href')) {
hrefToDisplay = content.getAttribute('src');
}
$.colorbox({iframe:true, href:hrefToDisplay, title:item.caption});
}
}
}
});
The secret is to open the HTML page in an iframe.
Hope this helps!

Why does this "loading message" script not work in FF?(javascript)

I have this script which should show the text "Loading..." while images are loading, then change the text to "loaded" when all images are loaded. I added a button to load new images to make sure that it works for dynamically loaded images as well.
This works perfectly in Chrome but in Firefox the "Loading..." text never appears. I have no idea why this would be. The page begins loading and not all images are loaded so it should create the text "Loading.." but it doesn't. Then when all images are done loading the text "Loading" appears.
I just don't get why one message would appear and the other wouldn't. Especially because there are no qualifications that have to be met before creating the "Loading..." text, it should just fire automatically.
jsfiddle Example | Full Page Example
$(document).ready(function() {
var checkComplete = function() {
if($('img').filter(function() {return $('img').prop('complete');}).length == $('img').length) {
$('.status').text('Loaded');
} else {
$('.status').text('Loading...');
}
};
$('img').on('load',function() {
checkComplete();
});
$('#button').click(function() {
$('img.a').attr('src' , 'http://farm9.staticflickr.com/8545/8675107979_ee12611e6e_o.jpg');
$('img.b').attr( 'src' , 'http://farm9.staticflickr.com/8382/8677371836_651f586c99_o.jpg');
checkComplete();
});
checkComplete();
});
You have several issues in the code.
First off, the checkComplete() function is not written correctly. It should be this:
var checkComplete = function() {
var imgs = $('img');
if(imgs.filter(function() {return this.complete;}).length == imgs.length) {
$('.status').text('Loaded');
} else {
$('.status').text('Loading...');
}
};
The main fix here is that the filter callback needs to refer to this.complete, not to $('img').prop('complete') because you are trying to filter a single item at a time.
Second off, you are relying on both .complete and .load working correctly AFTER you've changed the .src value. This is explicitly one of the cases where they do not work properly in all browsers.
The bulletproof way to work around this is to create a new image object for the new images, set the onload handler before you set the .src value and when both onload handlers have fired, you will know that both new images are loaded and you can replace the once you have in the DOM with the new ones.
Here is a version that works in FF:
$(document).ready(function() {
$('#button').click(function() {
var imgA = new Image();
var imgB = new Image();
imgA.className = "a";
imgB.className = "b";
var loaded = 0;
imgA.onload = imgB.onload = function() {
++loaded;
if (loaded == 2) {
$("img.a").replaceWith(imgA);
$("img.b").replaceWith(imgB);
$('.status').text('Loaded');
}
}
// the part with adding now to the end of the URL here is just for testing purposes to break the cache
// remove that part for deployment
var now = new Date().getTime();
imgA.src = 'http://farm9.staticflickr.com/8545/8675107979_ee12611e6e_o.jpg?' + now;
imgB.src = 'http://farm9.staticflickr.com/8382/8677371836_651f586c99_o.jpg?' + now;
$('.status').text('Loading...');
});
});
Working demo: http://jsfiddle.net/jfriend00/yy7GX/
If you want to preserve the original objects, you can use the newly created objects only for preloading the new images and then change .src after they've been preloaded like this:
$(document).ready(function() {
$('#button').click(function() {
var imgA = new Image();
var imgB = new Image();
var loaded = 0;
imgA.onload = imgB.onload = function() {
++loaded;
if (loaded == 2) {
$("img.a")[0].src = imgA.src;
$("img.b")[0].src = imgB.src;
$('.status').text('Loaded');
}
}
// the part with adding now to the end of the URL here is just for testing purposes to break the cache
// remove that part for deployment
var now = new Date().getTime();
imgA.src = 'http://farm9.staticflickr.com/8545/8675107979_ee12611e6e_o.jpg?' + now;
imgB.src = 'http://farm9.staticflickr.com/8382/8677371836_651f586c99_o.jpg?' + now;
$('.status').text('Loading...');
});
});
Working demo of this version: http://jsfiddle.net/jfriend00/ChSQ5/
From the jQuery API .load method
Caveats of the load event when used with images
A common challenge developers attempt to solve using the `.load()` shortcut is to execute a function when an image (or collection of images) have completely loaded. There are several known caveats with this that should be noted. These are:
It doesn't work consistently nor reliably cross-browser
It doesn't fire correctly in WebKit if the image src is set to the same src as before
It doesn't correctly bubble up the DOM tree
Can cease to fire for images that already live in the browser's cache

Javascript from file gives Uncaught ReferenceError

I am trying to dynamically adjust the height of an iFrame on a web page depending on the content within the iFrame via some JavaScript.
My problem is when I have the script directly on the page in a <script> tag it works fine. When I stuff the code in to a separate js file and link to it- it doesn't work!
<iframe id='StatusModule' onload='FrameManager.registerFrame(this)' src='http://randomdomain.dk/StatusModule.aspx'></iframe>
<script type='text/javascript' src='http://randomdomain.dk/FrameManager.js'></script>
It gives me the error:
Uncaught ReferenceError: FrameManager is not defined
Can this really be true? Has it something to do with the page life cycle?
Ps. I guess the JavaScript code is irrelevant, as we not it works.
UPDATE: I think this might have something to do with secure http (https) and the different browsers in some weird way. I noticed that the script actually worked in Firefox. Or rather I'm not sure if its the script, or just Firefox's functionality that resizes iframes automatically depending on the content. It doesn't give me any error though.
If I then add https to the script url reference, the scripts work in IE and Chrome - but not in Firefox. Function reference error! This just got weird!
UPDATE #2: Its not a Firefox function that resizes the iframe. Its the actual script that works (without https).
UPDATE #3: The JavaScript. Works fine if I put it directly into a script tag.
var FrameManager = {
currentFrameId: '',
currentFrameHeight: 0,
lastFrameId: '',
lastFrameHeight: 0,
resizeTimerId: null,
init: function () {
if (FrameManager.resizeTimerId == null) {
FrameManager.resizeTimerId = window.setInterval(FrameManager.resizeFrames, 0);
}
},
resizeFrames: function () {
FrameManager.retrieveFrameIdAndHeight();
if ((FrameManager.currentFrameId != FrameManager.lastFrameId) || (FrameManager.currentFrameHeight != FrameManager.lastFrameHeight)) {
var iframe = document.getElementById(FrameManager.currentFrameId.toString());
if (iframe == null) return;
iframe.style.height = FrameManager.currentFrameHeight.toString() + "px";
FrameManager.lastFrameId = FrameManager.currentFrameId;
FrameManager.lastFrameHeight = FrameManager.currentFrameHeight;
window.location.hash = '';
}
},
retrieveFrameIdAndHeight: function () {
if (window.location.hash.length == 0) return;
var hashValue = window.location.hash.substring(1);
if ((hashValue == null) || (hashValue.length == 0)) return;
var pairs = hashValue.split('&');
if ((pairs != null) && (pairs.length > 0)) {
for (var i = 0; i < pairs.length; i++) {
var pair = pairs[i].split('=');
if ((pair != null) && (pair.length > 0)) {
if (pair[0] == 'frameId') {
if ((pair[1] != null) && (pair[1].length > 0)) {
FrameManager.currentFrameId = pair[1];
}
} else if (pair[0] == 'height') {
var height = parseInt(pair[1]);
if (!isNaN(height)) {
FrameManager.currentFrameHeight = height;
//FrameManager.currentFrameHeight += 5;
}
}
}
}
}
},
registerFrame: function (frame) {
var currentLocation = location.href;
var hashIndex = currentLocation.indexOf('#');
if (hashIndex > -1) {
currentLocation = currentLocation.substring(0, hashIndex);
}
frame.contentWindow.location = frame.src + '&frameId=' + frame.id + '#' + currentLocation;
}
};
window.setTimeout(FrameManager.init, 0);
UPDATE #4: Alright I did as ShadowWizard and TheZuck suggested:
<script type="text/javascript">
var iframe = document.createElement("iframe");
iframe.src = "http://www.randomdomain.dk/StatusWebModule.aspx";
iframe.width = '100%';
iframe.id = 'StatusModule';
iframe.scrolling = 'no';
if (iframe.attachEvent) {
iframe.attachEvent("onload", function () {
FrameManager.registerFrame(iframe);
});
} else {
iframe.onload = function () {
FrameManager.registerFrame(iframe);
};
}
document.getElementById('framecontainer').appendChild(iframe);
</script>
With HTTP as URL its work on IE and Firefox - not Chrome. If I set it to HTTPS it works on Chrome and IE - Not Firefox. Same error:
"ReferenceError: FrameManager is not defined".
What is going on here?
a couple of things:
I would bet on a race condition when you have two independent
resources which are supposed to be loaded concurrently. You can
easily check this by writing to log (or to document, whichever works
for you) when both finish loading (i.e. add a little script in the
iframe to dynamically add the time to the content or write to log if
you're using chrome, do that in the external script file as well,
and see if they post the time in a specific order when this fails). In your case, if the script appears before the iframe, and you don't mark it as async, it should be loaded before the iframe is fetched, so it would seem strange for the iframe not to find it due to a race condition. I would bet on (3) in that case.
Assuming there is such an issue (and if there isn't now, when you go
out into the real world it will be), a better way to do this is to
make sure both behave well in case the other loads first. In your
case, I would tell the iframe to add itself to a local variable
independent of the script, and would tell the script to check if the
iframe registered when it loads, and after that in recurring
intervals until it finds the iframe.
If the page the script is loaded into is not in the same domain
as the iframe (note that it doesn't matter where the script comes
from, it only matters what the page's domain is), (or even the same
protocol as someone mentioned here), you will not be able to access
the content so you won't be able to resize according to what the
content is. I'm not sure about the onload method, if it's considered part of the wrapping page or part of the internal iframe.
Check out this question, it sounds relevant to your case:
There's also an interesting article here about this.
I think that your frame is loaded before the script, so "FrameManager" does not exist yet when the iframe has finished loading.

jQuery change page's title when user in a different tab

I have live chat on my page. I want to change the title (with something moving like in omegle.com) when a new message is received and the user is not in the same tab as the live chat. When the user returns to the tab, the title would return to normal.
I guess it should be done by jQuery. Do you know any plugins or how can I do that?
Title can only be edited like so:
document.title = "blah";
So you could do:
var origTitle = document.title;
document.title = "You have ("+x+") new messages - "+origTitle;
To make it flash you would have to do something with setTimeout();
var origTitle = document.title;
var isChatTab = false; // Set to true/false by separate DOM event.
var animStep = true;
var animateTitle = function() {
if (isChatTab) {
if (animStep) {
document.title = "You have ("+x+") new messages - "+origTitle;
} else {
document.title = origTitle;
}
animStep = !animStep;
} else {
document.title = origTitle;
animStep = false;
}
setTimeout(animateTitle, 5000);
};
animateTitle();
try
$('title').text("some text");
Update
Apparantly, in IE, $('title')[0].innerHTML returns the content of the <title> tag, but you can't set it's value, except using document.title. I guess this should be an improvement to the jQuery API, since $('title')[0] does return a DOMElement (nodeType = 1)...
$('title').text('your title') suffices.
To see if you're taking the right path, simply use IE's developer toolbar (F12) and go to console and write $('title'), you should see [...] in console. This means that $('title') is an object and it works up to here. Then write typeof $('title').text, and you should see function as the result. If these tests are OK, then your IE is broken.

Categories