Make Facebook plugin responsive - javascript

So I am using the new Facebook plugin (Page Plugin) and have a hard time to get it responsive on window resize.
I have set the option data-adapt-container-width="true", but that only triggers when there i a page load/reload.
Please se my JSFiddle: http://jsfiddle.net/29zgc790/ (try it in exporer and if that dont work try my plunker: http://plnkr.co/edit/IPnjpJUXxkO4WTLFTTW0?p=preview) where i have set the start width for the plugin to max (500px), but I want to trigger a reload of the plugin when the container (window) gets smaller then the plugin at that particular time.
I am thinking about somthing like:
$(window).resize(function () {
//Do the reload of plugin
});
Hope you guys have an idea of an solution that can guid me in the right way.

Embed the iframe generated:
<iframe id="facebook" frameborder="0" allowtransparency="true" allowfullscreen="true" scrolling="no" title="fb:page Facebook Social Plugin" src="http://www.facebook.com/v2.5/plugins/page.php?adapt_container_width=true&app_id=&channel=http%3A%2F%2Fstatic.ak.facebook.com%2Fconnect%2Fxd_arbiter%2FTlA_zCeMkxl.js%3Fversion%3D41%23cb%3Df1ce7bfb%26domain%3Drun.plnkr.co%26origin%3Dhttp%253A%252F%252Frun.plnkr.co%252Ff152208424%26relation%3Dparent.parent&hide_cover=true&href=https%3A%2F%2Fwww.facebook.com%2Fmicrosoft&locale=en_US&sdk=joey&show_facepile=false&show_posts=true&small_header=true&width=500"
style="border: none; visibility: visible;width: 500px; height: 500px;" class=""></iframe>
Get parent width and set it into iframe and iframe's src attribute
$(window).resize(function() {
//Do the reload of plugin
var new_width = $("#facebook").parent().width();
$("#facebook").css("width", new_width);
var url = $('#facebook').attr('src').split("&width=");
url = url[0] + '&width=' + new_width;
$('#facebook').attr('src', url);
});

After a few days of trying to achieve this, I came up with a working solution!
I actually registered only to share it :)
Copy the iframe code of the page plugin here:
Facebook Page Plugin (go to "Get code" and then click on "iFrame" on the top of the window that just opened.)
Paste the code to your html inside a div with class fb-column, then remove the width and src attributes (paste the value of the src attribute - the long link - somewhere else, you will need it later)
Add this code to your main .js file (credit for calculating the box size and calling the function goes to Mugo Web
function resizeFBPlugin() {
//calculate parent box width
var container_width = (Number($('.fb-column').width()) - Number($('.fb-column').css('padding-left').replace("px", ""))).toFixed(0);
// set the src and replace the actual width with the calculated width.
document.getElementById("fb-column").src = //paster link from iFrame here. Be sure to keep everything as it is, only replace the number after &width= with container_width
// it should look something like this: 'https://www.facebook.com....&width='+container_width+'&height=......';
// NOTE: take note of the use of apostrophes and + signs
//set the width of the iframe
document.getElementById("fb-column").width = container_width;
};
// call the function on resize and on window load
$(window).on('resize', function() {
setTimeout(function(){resizeFBPlugin()}, 500);
});
$(window).on('load', function() {
setTimeout(function(){resizeFBPlugin()}, 1500);
});
That's it! You now have a fully responsive Facebook page plugin (of course, within the min 180px and max 500px width.
BTW, The Twitter plugin works perfectly. I have no idea why Facebook decided not to fix this... I suppose they don't have the money for the right developers :)

So after reading the documentation for the facebook web sdk I found this little function that reloads the iframe.
FB.XFBML.parse();
https://developers.facebook.com/docs/reference/javascript/FB.XFBML.parse
That solved my problem, but #LucaGiardina hade a good solution as well but I think its always a god practice to use the built in functions if thay exist.

I have found out some solution but i think the best one is at least for me is that setting the parent tag of fb-comment-wrapper in a certain responsive then use facebook built in css data-width:
<div class="fb-comment-wrapper">
<div class="fb-comments" data-href="{{request.build_absolute_uri}}"
data-numposts="3" data-width="100%">
</div>
</div`>

Related

How to enforce user must scroll pdf within iframe

I have a pdf file within iframe. I want user to scroll must in pdf file before submitting the form. i am trying with this,
var position = $('#myIframe').contents().scrollTop();
But not working. Please help me Thanks in advance.
If you don't mind making a static height for your iframe, I have a solution for you.
HTML and CSS
1. Wrap your iframe in a div container
2. set heights for both your container and iframe (height of container should be the height you want your frame to be seen and the iframe height should be large enough to show entire pdf.)
3. set container div's overflow to scroll
Now you have a scrollable "iframe".
Javscript
Get container element. (var containerEl = $("#container")[0];)
Write a scroll function. Within the scroll function find if the total height of the element (scrollHeight) is less than or equal to how much has been scrolled (scrollTop) plus the inner height (clientHeight) of the
element. If it is, remove disabled property from button
Here's the fiddle. Made some changes to #mJunaidSalaat's jsfiddle.
Well I've tried almost an hour on this, Researched it, finally coming to a conclusion that Unfortunately this is not possible using this method.
The PDF is usually not a DOM element, it's rendered by PDF reader software. Every browser has its own mechanism for rendering PDFs, there is no standard. In some cases, the PDF might be rendered by PDF.js; in those situations you might be able to detect scrolling. But Adobe Reader, Foxit, and some of the native PDF rendering don't provide that option.
I've also created a Github issue for this. But no use.
Sorry. Please update me if you could find any thing or any workaround.
I've made a Fiddle for your solution. You can disable the submit button for user until user scroll on your iframe.
function getFrameTargetElement(objI) {
var objFrame = objI.contentWindow;
if (window.pageYOffset == undefined) {
objFrame = (objFrame.document.documentElement) ? objFrame.document.documentElement : objFrame = document.body;
}
return objFrame;
}
$("#myIframe").ready(function() {
var frame = getFrameTargetElement(document.getElementById("myIframe"));
frame.onscroll = function(e) {
$('.submitBtn').prop('disabled', false);
}
});
Hope it helps.
try this
$("#myIframe").ready(function() {
var frame = getFrameTargetElement(document.getElementById("myIframe"));
frame.onscroll = function(e) {
$('.submitBtn').prop('disabled', false);
}
});

Chrome ignoring hashes in URL

I've spent quite a while trying to find answers for this issue, but haven't had any success. Basically I need to scroll the user to the contact portion of the website when they go to healthdollars.com/#contact. This works just fine in Safari, but in Chrome I haven't had any luck. I've tried using jQuery/Javascript to force the browser to scroll down, but I haven't been able to.
Does anyone have any ideas? It's driving me crazy - especially since it's such a simple thing to do.
Not a full answer but in Chrome if you disable Javascript I believe you get the desired behavior. This makes me believe that something in your JavaScript is preventing default browser behavior.
It looks to me like the target element doesn't exist when when page first loads. I don't have any problem if I navigate to the page and then add the hash.
if (window.location.hash.length && $(location.hash)) {
window.scrollTo(0, $(location.hash).offset().top)
}
check for a hash, find the element's page offset, and scroll there (x, y).
edit: I noticed that, in fact, the page starts at #contact, then scrolls back to the top. I agree with the other answerer that there's something on your page that's scrolling you to the top. I'd search for that before adding a hack.
You can do this with JS, for example` if you have JQuery.
$(function(){
// get the selector to scroll (#contact)
var $to = $(window.location.hash);
// jquery animate
$('html'/* or body */).animate({ scrollTop: $to.offset().top });
});
The name attribute doesn't exists in HTML 5 so chrome looks to have made the name attribute obsolete when you use the DOCTYPE html.
The other browsers have yet to catch up.
Change
<a name="contact"></a>
to
<a id="contact"></a>
Maybe this workaround with vanilla javascript can be useful:
// Get the HTMLElement that you want to scroll to.
var element = document.querySelector('#contact');
// Stories the height of element in the page.
var elementHeight = element.scrollHeight;
// Get the HTMLElement that will fire the scroll on{event}.
var trigger = document.querySelector('[href="#contact"]');
trigger.addEventListener('click', function (event) {
// Hide the hash from URL.
event.preventDefault();
// Call the scrollTo(width, height) method of window, for example.
window.scrollTo(0, elementHeight);
})

How can popup a window in a new URL but also shadow out the current window and prevent clicks (possibly with jQuery)

I am normally used to "window.open" to open a popup window into a new URL. How can open a window into a new URL, shadow out/grey out the current window, and on close remove the shadow background.
Is it best to use jQuery to do this? Could I use the default libraries without use jquery plugins?
I want to do something like this and then "disable" my shadow on unload. Hopefully that uses core jQuery libraries or standard javascript calls. I want to avoid using any plugins besides jQuery.
var popup = window.open('http://google.com', 'popup');
showShadow();
$(window).unload(function() {
if(!popup.closed) {
disableShadow();
}
});
Basically, you can open the popup and set that window the beforeunload. In short, something like this:
popup = window.open("", "name", "width=400, height=300")
popup.onbeforeunload = function() { $('#shadow').hide();}
I created a fiddle for you.
http://jsfiddle.net/DDksS/
So you want to build your own modal box using jQuery instead of using an existing plugin? ...OK, let's play (as it was already pointed out, using popups is not a user-friendly solution):
Your check list :
- the trigger
- the shadow layer
- the modal box size and position
- add content to modal and display it along the shadow
1) The trigger is a simple html link to open the content inside the modal
open url
... we will pass the size of the modal via data-width and data-height (HTML5) attributtes.
2) The shadow layer is the html structure that we will append to the body after the trigger. We can set the structure in a js variable
var shadow = "<div class='shadow'></div>";
3) As we mentioned, the size of the modal is set through some data-* attributes in the link. We would need to do some math
var modalWidth = $(this).data("width");
var modalHeight = $(this).data("height");
var modalX = (($(window).innerWidth()) - modalWidth) / 2; // left position
var modalY = (($(window).innerHeight()) - modalHeight) / 2; // top position
NOTE : $(this) is our trigger selector .myModal that we'll get inside an .on("click") method later on. BTW, the .on() method requires jQuery v1.7+
4) Now we need to create the modal's html structure and pass the content href. We'll create a function
function modal(url) {
return '<div id="modal"><a id="closeModal" title="close" href="javascript:;"><img src="http://findicons.com/files/icons/2212/carpelinx/64/fileclose.png" alt="close" /></a><iframe src="' + url + '"></iframe></div>';
}
... as you can see, our structure contains a close button to remove the modal and the shadow layer. The function also gets a parameter when is called (url) which allows to set the src attribute of the iframe tag.
NOTE : we have to use the iframe tag to open external urls, however we should always consider the same origin policy and other security restrictions when using iframes.
So now, we need to put together all the events after we click on our .myModal trigger, which are appending both the shadow and the modal box to the body and to remove them when we click on the close button so
$(".myModal").on("click", function(e) {
e.preventDefault();
// get size and position
modalWidth = $(this).data("width");
modalHeight = $(this).data("height");
modalX = (($(window).innerWidth()) - modalWidth) / 2;
modalY = (($(window).innerHeight()) - modalHeight) / 2;
// append shadow layer
$(shadow).prependTo("body").css({
"opacity": 0.7
});
// append modal (call modal() and pass url)
$(modal(this.href)).appendTo("body").css({
"top": modalY,
"left": modalX,
"width": modalWidth,
"height": modalHeight
});
// close and remove
$("#closeModal").on("click", function() {
$("#modal, .shadow").remove();
});
}); // on
STYLE : of course we will need some basic CSS style to make our modal elements work properly:
.shadow {width: 100%; height: 100%; position: fixed; background-color: #444; top: 0; left:0; z-index: 400}
#modal {z-index: 500; position: absolute; background: #fff; top: 50px;}
#modal iframe {width: 100%; height: 100%}
#closeModal {position: absolute; top: -15px; right: -15px; font-size: 0.8em; }
#closeModal img {width: 30px; height: 30px;}
* SEE DEMO *
BONUS : you could also bind a keyup event to close the modal using the escape key
$(document).keyup(function(event) {
if (event.keyCode === 27) {
$("#modal, .shadow").remove();
}
}); //keyup
LAST NOTE : the code is subject to many improvements and optimization but is a basic layout of what many lightboxes do. My last recommendation : use fancybox for more advanced functionality ... sometimes it doesn't worth the effort to re-invent the wheel ;)
Using Javascript to create new popup windows is so 1990's, not to mention not very user-friendly. What you're looking for, both UI-wise and looks-wise is a modal dialog; there's billions of examples and pre-packaged jquery snippets on how to create modal dialogs, and most client-side UI frameworks such as jQuery UI, YUI and Bootstrap have modal dialog functionality built-in. I'd recommend diving into those.
Try jquery plugins such as fancybox http://fancybox.net/
Basically, you need to attach an event listener to your new window to run the disableShadow() function in your webpage.
If you add this to your code I think it should work.
popup.unload(function() { disableShadow() });
Adapted From: Attach an onload handler on a window opened by Javascript
You should use the beforeUnload event of the window instance returned by the window.open() call, like this:
popup = window.open('relative_url', 'popup');
$(popup).bind('beforeunload', function() {
disableShadow();
});
Note that the URL must be on the same domain in order for the opener window to interact with the popup!
See the fiddle here: http://jsfiddle.net/hongaar/QCABh/
You can open a new window, and when it closes you can execute a function in the opener window.
I'll do a quick example by writing the script right into the new window, but you could also just include it in the HTML that is used for the new window if a link is supplied for the popup:
$("#popupBtn").on('click', openPopup); //using a button to open popup
function openPopup() {
$('#cover').fadeIn(400);
var left = ($(window).width()/2)-(200/2),
top = ($(window).height()/2)-(150/2),
pop = window.open ("", "popup", "width=400, height=300, top="+top+", left="+left),
html = '<!DOCTYPE html>';
html += '<head>';
html += '<title>My Popup</title>';
html += '<scr'+'ipt type="text/javascript">';
html += 'window.onbeforeunload = function() { window.opener.fadeoutBG(); }';
html += '</sc'+'ript>';
html += '</head>';
html += '<body bgcolor=black>';
html += '<center><b><h2 style="color: #fff;">Welcome to my most excellent popup!</h2></b></center><br><br>';
html += '<center><b><h2 style="color: #fff;">Now close me!</h2></b></center>';
html += '</body></html>';
pop.document.write(html);
}
window.fadeoutBG = function() { //function to call from popup
$('#cover').fadeOut(400);
}
Using a fixed cover that is faded in will also prevent any clicks on elements on the page, and you could even attach a click handler to the cover with pop.close() to close the popup if the cover is clicked, just like a modal would close if you clicked outside it.
One of the advantages of calling a function on the parent page from the popup is that values can be passed from the popup to the parent, and you can do a lot of stuff you otherwise could'nt.
FULLSCREEN_FIDDLE
FIDDLE
All you need is standard javascript function showModalDialog. Then your code will look like
var url = 'http://google.com';
showShadow();
var optionalReturnValue = showModalDialog(url);
//Following code will be executed AFTER you return (close) popup window/dialog
hideShadow();
UPDATE
As hongaar stated Opera does not like showModalDialog. And it does not fire on(before)unload when popup is closed either. To make workaround you need timer (window.setTimeout) to periodically check if window still exists. For further details look here
Why don't you just use jQuery UI? I know that you don't want another library but is rather extension of jQuery rather then another lib since it can live without it.
It have great deal of widget and every one of them can be changed,configured.
What is best that it can viewed with different themes, even you can create one with they're theme roller fast and easy, and it can be modularized. Just take what you need in current project.
Check this out:
http://jqueryui.com/dialog/#modal-form
It's really simple to use. With this you can open modal dialog with frame to different url. On close event you can do whatever you want.
Try ColorBox
its simple and easy to use
http://www.jacklmoore.com/colorbox
quick example:
<link rel="stylesheet" href="http://www.jacklmoore.com/colorbox/example1/colorbox.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script src="http://www.jacklmoore.com/colorbox/colorbox/jquery.colorbox.js"></script>
<script>
$(document).ready(function(){
//Examples of how to assign the ColorBox event to elements
$(".iframe").colorbox({iframe:true, width:"80%", height:"80%"});
});
</script>
<a class='iframe' href="http://google.com">Outside Webpage (Iframe)</a>
You can also try this out ...
http://fancyapps.com/fancybox/
Examples here
try http://thickbox.net/ in modal type, examples: http://thickbox.net/#examples
I've done this as well.
First off, some URLs simply WILL NOT WORK in an (iframe) modal window; I can't say if it'll work in the browser-supported native modal windows as I haven't tried this. Load google or facebook in an iframe, and see what happens.
Second, things like window onunload events don't always fire (as we've seen some people already).
The accepted answer version will also only work on a static page. Any reloading (even F5 on the page) will cause the shadow to hide. Since I can't comment on the accepted answer, I at least wanted this to be known for anyone else looking at these results.
I've taken a less technical approach to solving this problem in the past: polling.
http://jsfiddle.net/N8AqH/
<html>
<head>
<script type="text/javascript">
function openWindow(url)
{
var wnd = window.open(url);
var timer = null;
var poll = function()
{
if(wnd.closed) { alert('not opened'); clearInterval(timer); }
};
timer = setInterval(poll, 1000);
}
</script>
</head>
<body>
click me
</body>
</html>
See the link above for an example. I tested in IE, FF, and Chrome. My timer is every 1 second, but the effort on the browser is so low you could easily drop this down to 100 ms or so if you wanted it to feel more instant.
All you'd have to do in this example is, after calling window.open, call your "show shadow" function and instead of alerting when you close, call your "hide shadow" function and it should achieve what you're looking for.

How to move an iFrame in the DOM without losing its state?

Take a look at this simple HTML:
<div id="wrap1">
<iframe id="iframe1"></iframe>
</div>
<div id="warp2">
<iframe id="iframe2"></iframe>
</div>
Let's say I wanted to move the wraps so that the #wrap2 would be before the #wrap1. The iframes are polluted by JavaScript. I am aware of jQuery's .insertAfter() and .insertBefore(). However, when I use those, the iFrame loses all of its HTML, and JavaScript variables and events.
Lets say the following was the iFrame's HTML:
<html>
<head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
// The variable below would change on click
// This represents changes on variables after the code is loaded
// These changes should remain after the iFrame is moved
variableThatChanges = false;
$(function(){
$("body").click(function(){
variableThatChanges = true;
});
});
</script>
</head>
<body>
<div id='anything'>Illustrative Example</div>
</body>
</html>
In the above code, the variable variableThatChanges would...change if the user clicked on the body. This variable, and the click event, should remain after the iFrame is moved (along with any other variables/events that have been started)
My question is the following: with JavaScript (with or without jQuery), how can I move the wrap nodes in the DOM (and their iframe childs) so that the iFrame's window stays the same, and the iFrame's events/variables/etc stay the same?
It isn't possible to move an iframe from one place in the dom to another without it reloading.
Here is an example to show that even using native JavaScript the iFrames still reload:
http://jsfiddle.net/pZ23B/
var wrap1 = document.getElementById('wrap1');
var wrap2 = document.getElementById('wrap2');
setTimeout(function(){
document.getElementsByTagName('body')[0].appendChild(wrap1);
},10000);
This answer is related to the bounty by #djechlin
A lot of search on the w3/dom specs and didn't find anything final that specifically says that iframe should be reloaded while moving in the DOM tree, however I did find lots of references and comments in the webkit's trac/bugzilla/microsoft regarding different behavior changes over the years.
I hope someone will find anything specific regarding this issue, but for now here are my findings:
According to Ryosuke Niwa - "That's the expected behavior".
There was a "magic iframe" (webkit, 2010), but it was removed in 2012.
According to MS - "iframe resources are freed when removed from the DOM". When you appendChild(node) of existing node - that node is first removed from the dom.
Interesting thing here - IE<=8 didn't reload the iframe - this behavior is (somewhat) new (since IE>=9).
According to Hallvord R. M. Steen comment, this is a quote from the iframe specs
When an iframe element is inserted into a document that has a browsing context, the user agent must create a new browsing context, set the element's nested browsing context to the newly-created browsing context, and then process the iframe attributes for the "first time".
This is the most close thing I found in the specs, however it's still require some interpretation (since when we move the iframe element in the DOM we don't really do a full remove, even if the browsers uses the node.removeChild method).
Whenever an iframe is appended and has a src attribute applied it fires a load action similarly to when creating an Image tag via JS. So when you remove and then append them they are completely new entities and they refresh. Its kind of how window.location = window.location will reload a page.
The only way I know to reposition iframes is via CSS. Here is an example I put together showing one way to handle this with flex-box:
https://jsfiddle.net/3g73sz3k/15/
The basic idea is to create a flex-box wrapper and then define an specific order for the iframes using the order attribute on each iframe wrapper.
<style>
.container{
display: flex;
flex-direction: column;
}
</style>
<div class="container">
<div id="wrap1" style="order: 0" class="iframe-wrapper">
<iframe id="iframe1" src="https://google.com"></iframe>
</div>
<div id="warp2" style="order: 1" class="iframe-wrapper">
<iframe id="iframe2" src="https://bing.com"></iframe>
</div>
</div>
As you can see in the JS fiddle these order styles are inline to simplify the flip button so rotate the iframes.
I sourced the solution from this StackOverflow question: Swap DIV position with CSS only
Hope that helps.
If you have created the iFrame on the page and simply need to move it's position later try this approach:
Append the iFrame to the body and use a high z-index and top,left,width,height to put the iFrame where you want.
Even CSS zoom works on the body without reloading which is awesome!
I maintain two states for my "widget" and it is either injected in place in the DOM or to the body using this method.
This is useful when other content or libraries will squish or squash your iFrame.
BOOM!
Unfortunately, the parentNode property of an HTML DOM element is read-only. You can adjust the positions of the iframes, of course, but you can't change their location in the DOM and preserve their states.
See this jsfiddle I created that provides a good test bed. http://jsfiddle.net/RpHTj/1/
Click on the box to toggle the value. Click on the "move" to run the javascript.
This question is pretty old... but I did find a way to move an iframe without it reloading. CSS only. I have multiple iframes with camera streams, I dont like when they reload when i swap them. So i used a combination of float, position:absolute, and some dummy blocks to move them around without reloading them and having the desired layout on demand (resizing and all).
If you are using the iframe to access pages you control, you could create some javascript to allow your parent to communicate with the iframe via postMessage
From there, you could build login inside the iframe to record state changes, and before moving dom, request that as a json object.
Once moved, the iframe will reload, you can pass the state data into the iframe and the iframe listening can parse the data back into the previous state.
PaulSCoder has the right solution. Never manipulate the DOM for this purpose. The classic approach for this is to have a relative position and "flip" the positions in the click event. It's only not wise to put the click event on the body, because it bubbles from other elements too.
$("body").click(function () {
var frame1Height = $(frame1).outerHeight(true);
var frame2Height = $(frame2).outerHeight(true);
var pos = $(frame1).css("top");
if (pos === "0px") {
$(frame1).css("top", frame2Height);
$(frame2).css("top", -frame1Height);
} else {
$(frame1).css("top", 0);
$(frame2).css("top", 0);
}
});
If you only have content that is not cross-domain you could save and restore the HTML:
var htmlContent = $(frame).contents().find("html").children();
// do something
$(frame).contents().find("html").html(htmlContent);
The advantage of the first method is, that the frame keeps on doing what it was doing. With the second method, the frame gets reloaded and starts it's code again.
At least in some circumstances a shadow dom with slotting might be an option.
<template>
<style>div {outline:1px solid black; height:45px}</style>
<div><slot name="a" /></div>
<div><slot name="b" /></div>
</template>
<div id="shadowhost">
<iframe src="data:text/html,<button onclick='this.innerText+=`!`'>!</button>"
slot="a" height=40px ></iframe>
</div>
<button onclick="ifr.slot= (ifr.slot=='a') ? 'b' : 'a';">swap</button>
<script>
document.querySelector('#shadowhost').attachShadow({mode: 'open'}).appendChild(
document.querySelector('template').content
);
ifr=document.querySelector('iframe');
</script>
In response to the bounty #djechlin placed on this question, I have forked the jsfiddle posted by #matt-h and have come to the conclusion that this is still not possible.
http://jsfiddle.net/gr3wo9u6/
//this does not work, the frames reload when appended back to the DOM
function swapFrames() {
var w1 = document.getElementById('wrap1');
var w2 = document.getElementById('wrap2');
var f1 = w1.querySelector('iframe');
var f2 = w2.querySelector('iframe');
w1.removeChild(f1);
w2.removeChild(f2);
w1.appendChild(f2);
w2.appendChild(f1);
//f1.parentNode = w2;
//f2.parentNode = w1;
//alert(f1.parentNode.id);
}

Printing viewable contents of browser window

I have a website I am currently developing and the client has a very unique request. They would like the user to be able to hit a button and print the contents of the browser window. I wanted to know if anyone has implemented similar functionality or knows any strategy to develop something like this as I do not have the first clue.
Example: I have 30 images on a page but only 4 fit in the viewable area or browser window. I would like to only print the exact content of the browser window / or elements that are viewable area.
Thanks in advance,
JN
This method requires jQuery, but might be able to be rewritten in plain javascript.
With a bookmarklet app of mine I found that the popup window was the most reliable way to print dynamic content and allowed the user to see the content before printing it. I also found that reducing the font size allowed fitting all the content on the page while sill be readable. You might try shrinking the images as well if that is an option. I had tried targeting media types with CSS and some jQuery print plugins but found them unreliable at best.
Here's the function I use to pass a jQuery object to be printed. I maximized the window on open and changed the title/font size. If you have more than images you'll need to clone your CSS as well, mine just happened to be stored in a variable from the bookmarklet loading.
function printElement(oElement) {
var oPopupWindow = window.open('', 'newwin', 'width=500,height=500');
oPopupWindow.moveTo(0,0);
oPopupWindow.resizeTo(screen.availWidth,screen.availHeight);
oPopupWindow.document.open();
var sHTML = '<html><head><title>TBA Enhanced User Interace</title>' +
_EUI.sCSS + '<style>img {display:none!important}table{font-size:8pt!important}</style></head><body>'
+ $('<div />').append(oElement.clone()).html() + '</body></html>';
oPopupWindow.document.write(sHTML);
oPopupWindow.document.close();
oPopupWindow.print();
oPopupWindow.close();
}
function isScrolledIntoView(elem)
{
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom));
}
function printVisibleImages() {
var oImageElement = $('<div />');
$('img').each(function() {
if (isScrolledIntoView(this)) {
oImageElement.append(this);
}
});
printElement(oImageElement);
}
Using the isScrolledIntoView function from this question: Check if element is visible after scrolling, something like the code above might work with some tweaking. Call printVisibleImages(), you might need to add some CSS for padding or pass the style sheets from the main page.
You could - in the same or a new window - wrap a DIV around all of the BODYs content and restrict the display area to currently visible . If there's a root-container-DIV for example...
<body>
<div id="theWholeDocument">
... content
</div>
</body>
... it can easily be done by jQuery:
$('#theWholeDocument').wrap( function() {
// get coordinates and dimensions of visible area first
// assing to var prLeft, prTop, prWidth, prHeight
return '<div style="position:absolute;left:"+prLeft+"px; top:"+prTop+"px; width:"+prWidth+"px; height:"+prHeight+"px; overflow:hidden"/>');
}
Should result in a Document that shows nothing else than what has been visible before. Printout schould look the same, like a screenshot - with propably cropped images at the bottom.
Make a jQuery function that loads a page on the click of a button via Ajax. (sending the page name as a post parameter). In that page, you do this:
$file = file_get_contents($_POST['file']);
echo $file;
and you style accordingly.
Maybe you can play around with Javascript (take a look at how to get window dimensions and scroll positions), but I don't realize how to print only that part of the document...
Maybe this can help you: snapshot from browser with flash or javascript
I have 30 images on a page but only 4 fit in the viewable area or
browser window.
I don't think you can say with certainty that the above works in all situations.
It is quite possible that many other browsers/resolutions will produce man different configurations, including some where the images are chopped off, etc.
The better solution, I think, is to offer X number of images per printed page and style accordingly.
One of the web apps needed something similar to what you are asking for. It is an FAQ link which produced an FAQ page and the user wanted the ability to print it, if they so chose.
I did this by simply adding a button to the html:
<input type="button" value="Print" onClick='window.print();' />
<input type="button" value="Close" onClick='window.close();' />
Because I popped this into its own little browser window, I stripped off all the other controls from the parent page via:
function popFaq() {
window.open('faq.html', '',
'left=10, top=10, width=550, height=700, resizable=1, ' +
'location=0, personalbar=0, scrollbars=1, statusbar=0, toolbar=0, menubar=0');
}
... and ...
<div id='hLink'>
<a title='Click Here for (F)requently (A)sked (Q)uestions' href='' onclick='popFaq(); return false;'>FAQ</a>
</div>
Hope that helps!

Categories