Background images missing while printing a webpage - javascript

I need some help on the topic: as i am printing the webpage it prints all well but not the background images, so my page breaks up at some places.Please suggest.
Regards
Jos

In your print stylesheet you should use something along the lines of:
.background {
display: list-item;
list-style-image: url(image.gif);
list-style-position: inside;
}
Please note that you can't use image sprites and more advanced background positioning this way and you need to do it for every image.

I just came across the same issue. My header background image wasn't printing on single post articles, leaving a big white gap at the head of the page where the header image would normally show. So to fix this, I added the background image via HTML directly on the page - which your users browser will print by default. Below is a basic example of how to achieve this:
1, Create a blank style sheet and name it print.css. Now add this style sheet to your page header, and make sure media="print". We need this in order to tell the browser which elements we want and don't want to print:
<link rel="stylesheet" href="pathtoyour/css/print.css" type="text/css" media="print" />
2, Add the image you want printed to your page and make sure it has an ID so we can style it within the print.css and your main style sheet:
<div id="header">
<img id="print-image" src="pathtotheimageyouwanttoprint.jpg"/></div>
</div>
3, In your main style sheet, add your image ID so we can tell browsers to stop the image from showing during normal viewing of your page:
#print-image {display:none}
4, In your print.css style sheet, because we've told your image to not display in your main style sheet, we need to now make sure that your image prints and doesn't remain hidden. Add the following to achieve this:
#print-image {display:block;}
You're done. Test and adjust styling to suit.
Doing this also allows you to fully customise the way your page is printed, for example - when printing, you now have the ability to hide your print button, menu items etc. and can code in any styling as per normal.
Hope this helps.

Try using David Aragon's Javascript
function replaceSprite(selector){
if ($.browser.msie == true) {
var back_x = $(selector).css('background-position-x'),
back_y = $(selector).css('background-position-y'),
back_position = back_x+" "+back_y;
} else {
var back_position = $(selector).css('background-position');
}
var back_image = $(selector).css('background-image'),
width = $(selector).width(),
height = $(selector).height(),
index1 = back_image.indexOf('http'),
index2 = back_image.indexOf('.png');
back_position = back_position.split(" ");
back_image = back_image.substring(index1, (index2+4));
$(selector)
.append('<img src="'+back_image+'"/>')
.css('width',width)
.css('height',height)
.css('overflow','hidden');
$(selector).find('img')
.css('margin-left',back_position[0])
.css('margin-top',back_position[1]);
}
http://quickleft.com/blog/printing-css-sprites

This is a user setting in the browser. By default some browsers won't print background images.
The user may choose to print background images also, but you can't force this with code or markup.

Related

Ensure element is always on top

I'm building a very simple Chrome extension that will put a clickable image on top of any youtube.com page.
The image shows up and has its intended click-functionality, but it is layered below any other elements that appear on the page. This is my code:
const linkItem = document.createElement("a");
linkItem.href="https://www.youtube.com/";
linkItem.innerHTML = "<img src='https://imgur.com/gBgwnSa.png' title='YouTube Home'>";
linkItem.setAttribute("style", "position:absolute;top:50px;left:200px;");
document.getElementsByTagName("body")[0].appendChild(linkItem);
The position is just a placeholder.
How can I set the image to always appear layered above any other elements of the page (preferably without having to create a CSS style sheet)? I know this is a beginner question, but any help would be greatly appreciated! :)
You can use the "z-index" property on CSS. You just have to set it to a value high enough, and it'll always be over everything else that have a smaller/null z-index set.
In this case:
linkItem.setAttribute("style", "position:absolute;top:50px;left:200px;z-index:99");

Display dynamic html content like an epub/ebook, without converting html to epub format?

I want to create a responsive, mobile optimized reading experience similar to an epub/ebook reader, like the Kindle app, or iBooks, using dynamic html as the source.
Imagine a long article or blog post that requires a lot of vertical scrolling to read, especially on a small mobile device. What I would like to do is break the long page into multiple full-screen sections, allowing the user to use left/right navigation arrows and/or the swipe gesture to "page" through the article.
There are many JS libraries available that can create a "slide show" or "carrousel" of pre-defined slides (using divs or other container elements). But I want the text and html content to dynamically re-flow to fit any device viewport and still be readable... just like an epub/ebook user interface, like the Kindle app or iBooks. So, for the same article, there would be many more "pages" on a phone than there would be on a tablet or desktop viewport, and those "pages" would need to be dynamically created/adjusted if/when the viewport size changes (like switching from portrait to landscape on a mobile device).
Here is an example of a javascript .epub reader: epub.js
... notice the responsive behavior. When you resize your viewport, all the text re-flows to fit the available space, increasing or decreasing the total number of "pages". The problem is that epub.js requires an .epub file as its source.
What I want is the same user interface and functionality for an html page.
I have searched and searched for some kind of library that can do this out of the box, but haven't been able to find anything.
I realize that I could use a conversion script to convert my html page into an .epub file, and then use epub.js to render that file within the browser, but that seems very round-about and clunky. It would be so much better to mimic or simulate the .epub reader user experience with html as the direct source, rendering/mimicking a client side responsive ebook user experience.
Does anyone know if something like this already exists, or how I could go about building it myself?
The crucial functionality is the dynamic/responsive text-reflow. When the viewport dimensions are reduced, the text/content needs to reflow to the next "page" to avoid any need for vertical scrolling. I don't know how to do this efficiently. If I were to code it myself, I might use something like the jQuery Columnize plugin, setting all columns to width: 100vw; height: 100vh, so that each column is like a "page", and then figuring out how to create a swipe UI between those "pages".
Any help is much appreciated!
This becomes very difficult if the html page is complex, eg with precisely positioned elements or images. However if (as in the epub.js example) the content consists only of headings and paragraphs, it is achievable.
The basic idea is to progressively add content until just before the page overflows. By keeping track of where we start and stop adding content, clicking to the next page is a case of changing the page start to the previous page end (or vice versa if you're going back).
Process for reshaping content into pages
Let's assume you have all your content in one long string. Begin by splitting all the content into an array of words and tags. It's not as easy as splitting by whitespace as whitespace between < and > should be ignored (you want to keep classnames etc within each tag). Also tags should be separated as well, even if there is no whitespace between the tag and a word.
Next you need a function that checks if an element's contents overflow the element. This question has a copy-paste solution.
You need two variables, pageStart and pageEnd, to keep track of what indexes in the array are the beginning and end of the current page.
Beginning at the index in pageStart you add elements from the array as content to the page, checking after each add whether or not the contents overflow. When they do overflow you take the index you're up to, minus 1, as the index for pageEnd.
Keeping tags across page breaks
Now if all's ticketyboo then this should fill the page pretty well. When you want to go to the next page set your new pageStart as pageEnd + 1 and repeat the process. However there are some issues that you may want to fix.
Firstly, what happens if the page overflows in the middle of a paragraph? Strictly speaking the closing tag, </p>, is not required in HTML, so we don't need to worry about it. But what about the start of the next page? It will be missing an opening tag and that is a major problem. So we have make sure we check if the page's content begins with a tag, and if it doesn't then we get the closest opening tag prior to the current pageStart (just step back along the array from pageStart) and add it in before the rest of the content.
Secondly, as shown in the example, if a paragraph continues onto the next page, the last line of the current page is still justified. You need to check if pageEnd is in the middle of a paragraph and if so add syle="text-align-last:justify;" to the opening tag of that paragraph.
Example implementation
A pen showing all this in action is at https://codepen.io/anon/pen/ZMJMZZ
The HTML page contains all content in one long element. The content is taken directly from the container #page and reformed into pages, depending on the size of #page. I have't implemented justifying the last line if a page break occurs within a paragraph. Resize the #page element in the css and see how the content resizes itself - note that since the page size is fixed you'll have to use click forward and back to trigger a recalculation. Once you bind the page size to the window size, recalculating pages on the fly simply involves adding a resize event listener to the window that calls fillPage.
No doubt there are numerous bugs, indeed it will sometimes display things incorrectly (eg skipping or repeating words at the beginning or end of a page), but this should give you an idea of where to start.
Take a look at this repository on GitHub. Otherwise, you can create a one-page website with many sections, each one as high as the viewport, by using only CSS (demo):
.section { height: 100vh; }
or by using JavaScript, adding an anchor to each section to navigate between them, and applying a responsive unit (my demo) for the text of each section, to adapt it on resize... Something like this:
var curr_el_index = 0;
var els_length = $(".container").length;
$(".next_section").on("click", function(e) {
curr_el_index++;
if (curr_el_index >= els_length) {
curr_el_index = 0;
}
$("html, body").animate({
scrollTop: $(".container").eq(curr_el_index).offset().top
}, 300);
return false;
});
$(".previous_section").on("click", function(e) {
curr_el_index--;
if (curr_el_index < 0) {
curr_el_index = els_length - 1;
}
$("html, body").animate({
scrollTop: $(".container").eq(curr_el_index).offset().top
}, 300);
return false;
});
* {
border: 0;
margin: 0;
padding: 0;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
}
body {
background-color: #1a1a1a;
}
section {
height: 100vh;
background-color: #eee;
border: 2px solid red;
font-size: 6vw;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="container">Section 1 Previous Next</section>
<section class="container">Section 2 Previous Next</section>
<section class="container">Section 3 Previous Next</section>
<section class="container">Section 4 Previous Next</section>
<section class="container">Section 5 Previous Next</section>
EDIT #1
An idea of algorithm, that come from a my codepen, that uses the same jQuery plugin:
Create your reader layout, copying the whole text in it
Use this jQuery plugin to check the text inside the viewport (demo)
Count the number of characters/WORDS with "Onscreen" label in the
viewport (a references)
Split the whole text in a list containing as many characters/WORDS as
there are in the "Onscreen" label
Create a section for each element of the obtained list, filling each
section with the relative text; the number of elements of the list
gives you the number of pages (sections) of the whole text. You may
navigate between sections like above
On resize event, redo [2-5] algorithm steps
Cheers
The idea is to have a div that will contain the whole text (let's call this div #epub_container). Then, you will have a div with the same size of the page viewport (let's call it #displayer) and it will contain #epub_container.
#displayer will have css overflow:hidden. So when the site loads, it will only show the first page, because the rest of the #epub_container will be hidden.
Then you need a page navigator to increment/decrement the page number. When the page number changes, we will move the top offset of the #epub_container based on that.
This is the jQuery function:
function move_to_page() {
var height = window.innerHeight;
var width = window.innerWidth;
var $displayer = $('#displayer');
var offset = $displayer.offset();
$displayer.height(height - offset.top - 5);
var $epub = $('#epub_container');
var offset_top = offset.top - $displayer.height() * m_page;
$epub.offset({top: offset_top, left: offset.left});
}
JSFiddle
EDIT: call move_to_page() after the text reflow in order to recompute the pages.
I created a plugin that handles this perfectly. It has features like dark mode, font changing, line height adjustment, select chapter in a side nav menu, save and restore scrolling/reading position. You can find it for free on git hub at https://github.com/E-TechDev/Html-Book-Reader
Screenshots
Light Mode Dark Mode Side Nav Menu Change Font Adjust Paragraph
You can try CSS scroll snap points on text with columns
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Scroll_Snap_Points
Somehow make the columns as wide as the viewport, and allow horizontal snapped scrolling.
Update
I mean to try to do the text flowing entirely using css. Pen:
https://codepen.io/ericc3141/pen/RYZEpr
body {
scroll-snap-type: mandatory;
scroll-snap-points-x: repeat(100%);
}
#columns-test {
height: 80vh;
columns: 90vw auto;
}
All you need is to insert a page break at the right places when you load the page. You can take the cue from here:
Dynamic Page-Break - Jquery
Here you can set the page height to your viewport height. You can handle the rest with javascript and css.

Jquery Loading After CSS

I have (Joomla) a web page with the following elements;
<section id="sp-top-bar">
<!-- html content -->
</section>
<section id="sp-footer">
<!-- html content -->
</section>
The #sp-top-bar is styled via custom.css - with a background-color: blue.
The #sp-footer is styled via template.css - with a background-color: green.
I am using jquery to force the #sp-top-bar to use the same background colour as is set for #sp-footer in the template.css file. (I know there are others ways to set the colour but I'm experimenting with jquery so please bear with me!).
This is my jquery code, which works.
jQuery(function ($) {
var brand = $('#sp-footer');
var bg = brand.css('background-color');
$("#sp-top-bar").css({
backgroundColor: bg
})
});
My jquery code is in the <head> of the document, after my template.css file.
When my page loads, the #sp-top-bar initially flashes blue for a split second, then successfully changes to the #sp-footer green.
I've had a look at the source code and my template.css file is loading before my jquery code - presumably this is the issue?
Is there anything I can do to avoid this initial background colour flash in the #sp-top-bar?
Thanks
You could try hiding the top-bar until everything's been loaded
CSS
#sp-top-bar {
display: hidden
}
JS
$("#sp-top-bar").css({
backgroundColor: bg,
display: 'block'
})
in jQuery you can set the background color like this:
$("#sp-top-bar").css('background-color','#f6f6f6');
(I used an imaginary shade of grey f6f6f6)
Hope that helps you.
Try this
$("#sp-top-bar").hide();
$(document).ready(function(){
var brand = $('#sp-footer');
var bg = brand.css('background-color');
$("#sp-top-bar").css({
backgroundColor: bg,
display: 'block'
})
});
Using JQuery for this one is kinda hard, since the JQuery has to wait for the DOM element to be loaded into the page before it can change it. So you'll usually have the flash effect because the header will use the default style from the css.
In css you could just overwrite the default style before the header is rendered.
But if it has to be JQuery, something like the hide trick described below might work. Or you could insert an absolutely positioned header in the right color completely overlapping the header and remove it again after the page has loaded.
But that's alot of work to replicate one line of css.
Edit:
Another angle is loading the css with ajax after the page has loaded, but then nothing will be styled, which might be worse than flashing.
You could also show a fully blank page until all scripts have ran, but this also isn't perfect, since it comes across as being a 'slowloading' page.

How can I record the link pressed?

(I don't want to add code here because it would be very large chunks that would need explaining.)
To put it simply, I have:
A page with a 2x2 grid of images on (let's call that images.html),
A page that is a fullscreen image gallery made using CSS3 and HTML5 (let's call that gallery.html),
A style sheet that styles aspects of every page in the site except the gallery (let's call that main-styles.css),
And a style sheet that styles only gallery.html (let's call that gallery-styles.css).
The images in the 2x2 grid (images.html) need to open up the same gallery.html using gallery-styles.css. The only difference should be the range of images the fullscreen gallery displays.
So for one image on images.html, it may display 3 images in gallery.html. But for another image in images.html, it may display 4 entirely different images in gallery.html.
The problem I am having is how to track the image link that is clicked in images.html so as to display the different range of images in gallery.html.
The gallery-styles.css has a div that is positioned to be fullscreen, then there is an image list, e.g. '.image1{background-image:url(../images/1.jpg)}' of the different images that can be browsed through (left and right clickable arrows in the gallery.html). The HTML will use each image individually but with the same content holder, e.g.
<div class="image-1 holder">
How can I go about using the same gallery.html and gallery-styles.css files for each image in images.html? I'm not entirely against JavaScript but have gone this far with just CSS3 and HTML5 would be nice if it was possible to continue that way. Is there possibly a way using the input element?
Any help is great, thanks.
There are two ways to deal with processing information from the page: client side script (JS) and server side script (PHP or like) unless you have a great number of hand-coded html pages you can load for a corresponding link clicks.
Given that, you either link to your hard-coded page directly from the link, which I assume you have already thought of,
Or, you pass a parameter to server side in a form http://myserver.asdf/gallery.php?linkid=12&someotherparam=somevalue
In that case you capture these parameters on server side and generate a page with needed images.
In php all parameters can be found in $_REQUEST array.
Does this answer your question?
For this, I think the easiest way for you would be to use window.location.search. When you click the first image sending you to gallery.html, rather than just opening a regular copy, open for example, gallery.html?image1. Then in JavaScript, you can add this as a class to <body> or some other node when the page has loaded, and do the rest from CSS
window.addEventListener(
'load',
function () {document.body.className += ' '+window.location.search.slice(1)}
);
You can now do the decision making using, for example
body > genericNodes {display: none; }
body.image1 > someNode { display: block; }
/* etc */
A different option for pure CSS is to use a hash and then :target, but this means you lose the ability to have anchors in your page. i.e. open gallery.html#image1 and have
#image1, #image2, #image3, #image4 { display: none; }
:target { display: block !important; }
/* etc */
With some nodes of the form
<span id="image1"><!-- contents --></span>
<span id="image2"><!-- contents --></span>

Trouble with window.print after having altered page elements

I am in trouble with the print function offered by javascript: It doesn't print the current page.
From the beginning: The purpose of the page is to take input from the user, process it and display a result. In fact, it is a simple form with a couple of input fields. With the help of jquery the input given by the user is interpreted and a result is displayed. If the input is satisfactory, a plus sign on a green background in a div-container is displayed. If not, a minus sign on a red background is displayed.
Now, the problem: The user is offered a print-button. That is not 21st century, but a requirement. The printout looks pretty fine thanks to the print.css. But there is one problem: The div-containers only appear in their unprocessed shape. No matter what the input of the user was, the div-containers are printed in their initial state (meaning: gray background).
The div-containers are changed by using the jquery-function addclass() or removeclass(). On the screen, everything works fine. But a look at the source code after having processed the input of the user still reveals an unchanged div-container. Therefore the print result is short of its purpose.
How do I convince the browser to print the altered div container instead of the initial one (as it was at the time of loading the page)? What am I missing here?
For your help, lets have a look at the crucial parts of the source code:
a) how the css files are linked in:
<link rel="stylesheet" href="styles/standard.css">
<link rel="stylesheet" media="print" href="styles/print.css" />
b) how the print button is handled:
$('a#print').click(function(e){
e.preventDefault();
window.print();
});
c) how the div containers are altered:
$('div#result').addClass('res_red');
$('div#result').removeClass('res_green');
$('div#result').removeClass('res_zero');
Again: On the screen everything works fine. Just the print-out is in a mess...
i do not get that.
do you load print.css to all users? or just who clicks the "Print" button?
nothing is wrong in your code. im afraid its just css rules not applying right.
(maybe some !important or just override not strong enough*)
*override not strong enough example:
css:
div.container div.class-a:hover {
color: grey;
}
.container div:hover {
color: red;
}
the last class will not override the first one due to not strong enough selector.
so color remain grey on hover, although the last class written below.

Categories

Resources