How to render (in pdf) responsive pages in PhantomJS - responsive-design

I'm wondering how to render responsive pages using PhantomJS in pdf format.
I have tried so many responsive pages and found that it is printing the pdf using the print css.
So, if the page includes the print css OR screen only css it will render the pdf same as we found via print command preview (Ctrl + p).
Is there any way OR script by which i can get the pdf as I'm seeing them on web browser?
Attaching the file when i tried to get the pdf from http://getbootstrap.com/examples/jumbotron/.
Also the main issue is not responsive designes, the issue is print css applied over them.
example pdf

jorupp came up with a javascript solution in this gist. It essentially let's you "lock" all the media queries in the document's stylesheets to whatever applies presently, before changing to print mode.
In case the link ever disappears, here's the code:
function process(rule) {
if(rule.cssRules) {
for(var i=rule.cssRules.length-1; i>=0; i--) {
process(rule.cssRules[i]);
}
}
if(rule.type == CSSRule.MEDIA_RULE) {
if(window.matchMedia(rule.media.mediaText).matches) {
rule.media.mediaText = "all";
} else {
rule.media.mediaText = "not all";
}
}
return rule;
}
for(var i=0; i<document.styleSheets.length; i++) {
process(document.styleSheets[i]);
}

This is quite tricky since there is no option to tell PhantomJS to use the screen when rendering as PDF.
You would need to
load all the linked stylesheets that contain a print block with __utils__.sendAJAX,
remove #media print block (this is quite hard with regex because you need to look out for balanced braces, but relatively easy with plain JS),
maybe you even need to rename #media screen to #media print,
remove the linked stylesheet from the document and
add a style element which has the manipulated stylesheet inside (preferable in the same place as the previous stylesheet) to the DOM.
Your page won't look good, because you usually have page breaks and the like with pdf. Also, page width and viewport width are quite hard to get right. Changing the page width doesn't change the viewport, so it won't be the proper responsive that would have with a pixel perfect png. But that is only a solution if you don't need selectable text.

Related

Masonry Views can't load masonry effect in D7

I had installed Masonry Views module, along with Masonry module in my Drupal 7 site.
In my view, I can select format as "Masonry", and had updated the details such as column width.
But the output still displays the view like unfomatted list.
In my status report, it shows
jQuery Masonry 2.1.08
jQuery Update jQuery 1.10.2
My js file is in: www/mydomain/sites/all/libraries/masonry/jquery.masonry.min.js
I had flushed cached, but the masonry effect still doesn't appear. Any idea what's the problem?
Reading your question again I have a silight suspicion what the problem might be: are your content items display literally as a list? Then you might have to adjust their widths first so more than one can fit inside your content container – otherwise they'll be listed as a list.
So for example if your content container is 960px wide, you should add / modify something like this to your theme's stylesheet, adjusted to your personal preferences of course:
for the container:
.my-container-view #content {
width:960px;
}
for the items:
.my-container-view .item {
width:320px;
float:left;
}
The float might be redundant since masonry should take care of that – but this is at least what I have in my stylesheet…

Printing pages of AngularJS app to PDF

I have an Angular JS single-page application used for reporting. I would like to print the report as rendered client-side to PDF format, taking into consideration certain elements users may have dynamically shown or hidden.
Is there anyway to achieve this?
Add class to div no-print
and css,
#media print {
.no-print{
display:none;
}
}
and print using,
javascript:window.print()

Google translate widget appears twice

I have a responsive site that uses the google translate widget. The weird thing is that for some time the widget now appears twice, and this seem to be related to the responsive design because if I place the same widget code on a simple html page it only appears once. I have no idea on how to solve this. Has anyone come across this?
Update.
I have discovered that this is caused by jquery.themepunch.showbizpro.min.js, if I remove that one the widget only appears once. I have not found a way to fix this yet but there might be a way. I found this piece of code.
<script>
function googleTranslateElementInit() {
new google.translate.TranslateElement(
{ pageLanguage: 'sv' },
'google_translate_element'
);
/*
To remove the "powered by google",
uncomment one of the following code blocks.
NB: This breaks Google's Attribution Requirements:
https://developers.google.com/translate/v2/attribution#attribution-and-logos
*/
// Native (but only works in browsers that support query selector)
if(typeof(document.querySelector) == 'function') {
document.querySelector('.goog-logo-link').setAttribute('style', 'display: none');
document.querySelector('.goog-te-gadget').setAttribute('style', 'font-size: 0');
}
//If you have jQuery - works cross-browser - uncomment this
jQuery('.goog-logo-link').css('display', 'none');
jQuery('.goog-te-gadget').css('font-size', '0');
}
</script>
This code remove the logo, so I'm thinking that if I use javascript I could check and remove duplicate occurrences of <select class="goog-te-combo"> then I would only have one left, is that possible?
This happened to me using Bootstrap. I had two instances of the Google Translate code - one instance for larger screen sizes and another that was only visible for smaller screens. Both showed up regardless of screen size. Bootstrap classes like visible-xs and hidden-xs do not seem to affect the display of the Google Translate button.
You can set a global counter and make sure it's only called once.
<div id="google_translate_element"></div>
<script type="text/javascript">
var duplicate_google_translate_counter = 0;//this stops google adding button multiple times
function googleTranslateElementInit() {
if (duplicate_google_translate_counter == 0) {
new google.translate.TranslateElement({pageLanguage: 'en'}, 'google_translate_element');
}
duplicate_google_translate_counter++;
}
</script>
<script type="text/javascript" src="https://translate.google.com/translate_a/element.js?cb=googleTranslateElementInit"></script>
Had the same problem on RoR. Problem caused by cashing pages with turbolinks. I solved it with deprecating cashing all links in (when script loading it adds attr "data-turbolinks="false" to the body-tag)
Hello to all! I had the same issue and I KNOW is not the best practice but I fixed it with CSS just adding overflow: hidden and a right border on it.
It visually fix the problem until we get a solution and really saved time diving into JS files. Hope it works for you too. Cheers!

Using screen.width and window.devicePixelRatio to detect mobile and/or retina displays is this a bad approach?

I'm developing a website for a business. It's not a web application by any stretch of the imagination but I would like it to look ok on mobile devices rather than simply scale the desktop version. After lots of research into media queries and responsive/adaptive design approaches my requirements are that the mobile layout only kicks in when the user really is on a small screen and not just resizing their desktop window, the solution is simple and can be accomplished with media queries and minimal javascript.
The approach I've come up with is something like this:
<script type="text/javascript">
var isRetina = window.devicePixelRatio > 1 ? true : false;
var isMobile = (screen.width < 768) ? true : false;
if (isMobile && isRetina) {
SHOW MOBILE LAYOUT AND HI-RES IMAGES
} else if (isMobile && !isRetina) {
SHOW MOBILE LAYOUT AND LO-RES IMAGES
} else if (!isMobile && isRetina) {
<<SHOW HI_RES IMAGES>>
} else if (!isMobile && !isRetina) {
SHOW DESKTOP LAYOUT AND LO-RES IMAGES
}
</script>
Before I commit to this approach I figured I'd check in and see if there is a problem or a terrible gotcha awaiting me. Or if there's an even simpler/better way to achieve this goal. I've searched a bunch on SO an haven't seen any mention of using this exact same solution.
The reason javascript is not a preferred method when loading CSS layouts is because javascript is usually the last thing loaded when the browser renders your page. This means that for a flash second you'll see your initial layout on the screen, before it loads the correct CSS. The simplest and most ideal approach is to make use of CSS3 Media Queries (something like this simple tutorial could go a long way: http://webdesignerwall.com/tutorials/responsive-design-in-3-steps).
The other option you have is to use Modernizr to load your stylesheets or other files that you may want to load based on viewport sizes. Look into the Modernizr Doc, you can basically "test" for the functionalities and features on the current browser that's being used to view your webpage - and load files accordingly. As a side note, Modernizr is a JS library so again use with caution when loading CSS files - it's known to load them without the splash screen of your initial layouts but I'd still say the best practices for loading layouts based on media queries is to use the CSS3 media queries themselves.
sorry to post to answer, couldn't add comment.
window.devicePixelRatio on firefox (and i believe Mac) will be bigger than 1 if you zoom in, which could result in a bug
navigator.userAgent.match(/iPhone/i)) || (navigator.userAgent.match(/iPod/i)) || (navigator.userAgent.match(/iPad/i)
this might help

Twitter Bootstrap2 100% height responsive

I want to make a responsive layout with twitter's bootstrap v2, with a column and a map.
The idea is to build a UI like that from maps.google.com, but using a responsive design with bootstrap2.
I want to have a style for desktop with
navbar on top
1 left column (as sidebar)
height: 100% minus navbarHeight, with a scrollbar
width: .span3
content that fills the rest of the screen
Then for the responsive mobile design I want the parts that have the full height to have a height depending on the content.
I made a sketch to explain better
EDIT: Looking to do something like this but responsive, and only with north (navbar), west (sidebar), and center (content)
EDIT2: I finally made it with jquery, but I want a CSS solution. If someone asks, I will put the solution as an answer.
EDIT3: Ok, here is the solution I found using JQuery (I think it's easy to do with plain js)
$(window).bind('resize', function() {
if ( $(window).width() > 980 ) {
$("#content").height(($(window).height()-40)+"px")
$("#sidebar").height(($(window).height()-58)+"px")
$("body").css("padding-top","40px")
}
else {
$("#content").height(($(window).height()-50)+"px")
$("#sidebar").height(($(window).height()-68)+"px")
$("body").css("padding-top","0px")
}
$("#sidebar").css("overflow", "auto")
$("body").css("padding-bottom","0px")
$(".navbar").css("margin-bottom","0px")
});
The $(selector).css() functions and the conditional if could be replaced with plain css and the media queries from CSS3 http://twitter.github.com/bootstrap/scaffolding.html#responsive
But the problem is that $(window).height() is calculated runtime. That should be replaced maybe by something like a height:100% in CSS, and that could do the trick, but I couldn't find the right place to put that 100% height.
EDIT4: Here I found what it could be a CSS-only solution! If I make progress, I'll post the answer!
http://blog.stevensanderson.com/2011/10/05/full-height-app-layouts-a-css-trick-to-make-it-easier/
From my investigations this week (I'm trying to accomplish the same thing), it seems like bootstrap and a 100%-height design are incompatible from a pure CSS perspective (unless you want to make changes to bootstrap). I'd be interested in seeing your jquery solution.
I'm not sure that I totally understand what you are looking for, but take a look at http://reactivewebdesign.net/Chicago/Traffic which has a top menu (adding the bootstrap navbar should be easy).
The left column spans 3 columns and the map occupies 9 columns. There is also a link in the left menu named "Where Am I" that also uses a Google map. The css for the map is at the top of the page. If you are looking to squeeze the map into three columns, merely reverse the 3 & 9 to 9 & 3 - it should still work.
Hope this helps.
here is the solution I found using JQuery (I think it's easy to do with plain js)
$(window).bind('resize', function() {
if ( $(window).width() > 980 ) {
$("#content").height(($(window).height()-40)+"px")
$("#sidebar").height(($(window).height()-58)+"px")
$("body").css("padding-top","40px")
}
else {
$("#content").height(($(window).height()-50)+"px")
$("#sidebar").height(($(window).height()-68)+"px")
$("body").css("padding-top","0px")
}
$("#sidebar").css("overflow", "auto")
$("body").css("padding-bottom","0px")
$(".navbar").css("margin-bottom","0px")
});
The $(selector).css() functions and the conditional if could be replaced with plain css and the media queries from CSS3 http://twitter.github.com/bootstrap/scaffolding.html#responsive
But the problem is that $(window).height() is calculated runtime. That should be replaced maybe by something like a height:100% in CSS, and that could do the trick, but I couldn't find the right place to put that 100% height.

Resources