I have a task where i need to load a URL (e.g www.yahoo.com) , on my webpage, and take screenshot. I am using html2canvas for screenshot and appending it to the body of the page.
The page specified by the URL is successfully loaded in an iframe inside a div element. But when i try to take screenshot of that, the iframe area comes blank.
Below is the code for previewURL and screenshot.
//to preview the URL content
function previewUrl(url,target){
//use timeout coz mousehover fires several times
clearTimeout(window.ht);
window.ht = setTimeout(function(){
var div = document.getElementById(target);
div.innerHTML = '<iframe style="width:100%;height:100%;" frameborder="0" src="' + url + '" />';
},20);
}
function pic() {
html2canvas(document.body, {
onrendered: function(canvas) {
document.body.appendChild(canvas);
}
});
};
And the HTML part goes here :
<body>
<input type="button" class="clear-button" onclick="pic();" value="Take Screenshot" >
Hover to load
<div id="div1"></div>
</body>
The screenshot looks something like this :
I am stuck and don't understand why is this happening. I want something similar to this which can load URL and then onclick can give me screenshot.
The problem here is that you are not pointing correctly to the part of the iframe that you want to take the screenshot, instead you are pointing directly to the document body.
you can try this:
var body = $(iframe).contents().find('body')[0];
html2canvas(body, {
onrendered: function( canvas ) {
$("#content").empty().append(canvas);
},
Hope this helps!
Seems like it's not possible:
The script doesn't render plugin content such as Flash or Java applets. It doesn't render iframe content either.
http://html2canvas.hertzen.com/documentation.html#limitations
This code worked 4 me:
setTimeout(() => {
html2canvas($('#'+idd2).contents().find('body')[0], {
allowTaint : true,
logging: true,
profile: true,
useCORS: true
}).then(function(canvas) {
document.getElementById('screen').appendChild(canvas);
}); }, 3000);
Related
I have embedded images in text blocks on my Divi website. I'd like that when the user clicks on the image, the largest/original size of the image opens up in a lightbox (instead of the thumbnail size as stated in the src). I have hundreds of images and therefore would be too time consuming to change the src link on each to the original size url. Could anyone help me on how I can change the src link to point to the largest/original image size and then for it to open in a lightbox upon click? I'm not sure of the JQuery to go about this. I've included below the HTML structure I'm using for each embedded image in the text blocks. I've also included the JQuery snippet I'm currently using. The snippet opens the image in a lightbox but only the thumbnail version (not the largest size possible).
Here are a few examples of the URLs of the images on my site:
https://mydomain/wp-content/uploads/2023/01/myimage-235x300.jpg
https://mydomain/wp-content/uploads/2023/01/myimage.jpg
https://mydomain/wp-content/uploads/2023/01/myimage-1.jpg
HTML:
<div class="dmpro_timeline_item_description">
<img decoding="async" loading="lazy" src="https://mydomain/wp-content/uploads/2023/01/myimage-235x300.jpg" width="235" height="300" class="wp-image-2129 alignnone size-medium">
<br>
<em>Image caption</em>
</div>
JQuery:
<script>
if ( jQuery('.dmpro_timeline_item_description').length > 0 ) {
jQuery(".dmpro_timeline_item_description p img").each(function(i, e){
var img_src = jQuery(this).attr("src");
var img = jQuery(this).parent().html();
var new_elem = jQuery('<a style="color: inherit;" href="'+img_src+'">'+img+'</a>');
jQuery(this).parent().html(new_elem);
});
}
jQuery(document).ready(function($){
$(".dmpro_timeline_item_description p").magnificPopup({
delegate: 'a',
type: 'image',
closeOnContentClick: true,
closeBtnInside: false,
mainClass: 'mfp-no-margins mfp-with-zoom',
gallery:{
enabled:false,
},
zoom: {
enabled: true,
duration: 200
}
});
});
</script>
In the snippet below you can see that the width and the height attributes can be toggled.
function toggleLarge(context) {
if (!context.large) {
context.large = true;
context.formerWidth = context.width;
context.formerHeight = context.height;
context.removeAttribute("width");
context.removeAttribute("height");
} else {
context.large = false;
context.width = context.formerWidth;
context.height = context.formerHeight;
}
}
for (let img of document.querySelectorAll("img.size-medium")) {
img.addEventListener('click', function(event) {
toggleLarge(this);
});
}
<div class="dmpro_timeline_item_description">
<img decoding="async" loading="lazy" src="https://www.yourtango.com/sites/default/files/styles/header_slider/public/image_blog/lion-meaning.png?itok=-eB2XSyC" width="235" height="300" class="wp-image-2129 alignnone size-medium">
<br>
<em>Image caption</em>
</div>
If you also need to change the URLs, then you will need to proceed similarly. Since you have not given a sample of large URLs, it's impossible to tell you how to convert the URL to something you did not specify. However, if the "-235x300" part is the problematic, then you can do something like this:
function toggleSrc(context) {
if (context.large) {
context.src = context.src.replace(".", "-235x300.");
} else {
context.src = context.src.replace("-235x300", "");
}
}
and call this function in toggleLarge just before the if, passing context. If this is inappropriate to your problem, then you need to provide further information.
EDIT
Initially, for the sake of simplicity, the event listener was defined with the onclick attribute, but I have changed it to be an addEventListener as per Roko C. Buljan's suggestion.
EDIT2
As Roko C. Buljan explained, it's also possible to use forEach instead of a for loop. For those who prefer that syntax, there is another snippet below:
function toggleLarge(context) {
if (!context.large) {
context.large = true;
context.formerWidth = context.width;
context.formerHeight = context.height;
context.removeAttribute("width");
context.removeAttribute("height");
} else {
context.large = false;
context.width = context.formerWidth;
context.height = context.formerHeight;
}
}
document.querySelectorAll("img.size-medium").forEach(function(img) {
img.addEventListener('click', function(event) {
toggleLarge(this);
});
});
<div class="dmpro_timeline_item_description">
<img decoding="async" loading="lazy" src="https://www.yourtango.com/sites/default/files/styles/header_slider/public/image_blog/lion-meaning.png?itok=-eB2XSyC" width="235" height="300" class="wp-image-2129 alignnone size-medium">
<br>
<em>Image caption</em>
</div>
EDIT3
In the snippet below I have implemented the two functions you need based on the comment section's content:
/*
https://mydomain/wp-content/uploads/2023/01/myimage-235x300.jpg
https://mydomain/wp-content/uploads/2023/01/myimage.jpg
https://mydomain/wp-content/uploads/2023/01/myimage-1.jpg
*/
function thumbnailToLarge(input) {
return input.substring(0, input.lastIndexOf(".")).split("-").filter((item) => (
!/[0-9]+x.*[0-9]+/g.test(item)
)).join("-") + input.substring(input.lastIndexOf("."));
}
console.log("Thumbnail to large: " + thumbnailToLarge("https://mydomain/wp-content/uploads/2023/01/myimage-235x300.jpg"));
function largeToThumbnail(input) {
return input.substring(0, input.lastIndexOf(".")) + "-235x300" + input.substring(input.lastIndexOf("."))
}
console.log("Large to thumbnail " + largeToThumbnail("https://mydomain/wp-content/uploads/2023/01/myimage.jpg"));
console.log("Large to thumbnail " + largeToThumbnail("https://mydomain/wp-content/uploads/2023/01/myimage-1.jpg"));
i have a link in my main page that uses ajax to retrieve a PDF which is displayed in an Iframe, i am trying to detect scroll event of the PDF document and display a message or do something. i have tried different solutions from other solutions on stackoverflow and google search in general and couldn't find a good solution.
Main.php
<html>
<!--ajax request-->
<script type="text/javascript">
$(document).on('click','#nextpdf',function(event) {
event.preventDefault();
var reg = $(this).attr("href");
var str = reg.split('?')[1];
$.ajax({
type: "GET",
url: '../functions/pdfreader.php',
data: 'pdfxs='+str+'',
cache:false,
async: false,
success: function(data) {
// data is ur summary
$('.refresh').html(data);
return false;
}
});//end of ajax
});
</script>
<?php
while($obj = $c_content->fetch())
{
$title = $obj['lecture_title'];
echo '<article class="comment2">
//pdf link
<div class="comment2-body">
<div class="text" style="color:#999;padding-right:130px;">
<p><a href="../functions/pdfreader.php?'.$title.'""
style="color:#999" id="nextpdf">'.$title.'</a></p>
</div>
</div>
</article>
';
}
?>
</html>
pdfreader.php
//detect iframe pdf scroll
<script type="text/javascript">
$("myiframe").load(function () {
var iframe = $("myiframe").contents();
$(iframe).scroll(function () {
alert('scrolling...');
});
});
</script>
<?php
........
while($obj = $gettrend->fetch())
{
$coursefile = $obj['lecture_content'];
//this is my iframe
echo '<div class="mov_pdf_frame"><iframe id="myiframe"
src="https://localhost/einstower/e-learn/courses/pdf/'.$coursefile.'"
id="pdf_content"
width="700px" height="800px" type="application/pdf">
</iframe></div>';
}
?>
The major problem here is that nothing happens when i scroll the pdf document, how can i detect scrolling?
i found this fiddle that works but i cant view the javascript solution. http://fiddle.jshell.net/czw8pbvj/1/
First off, $("myiframe") isn't finding anything, so it attaches a load event to nothing. 1) change it to $("#myiframe") or $("iframe").
Here's a working fiddle (for iframe scroll detection)
UPDATE: to detect the scroll within PDF document, you can't use iframe. For that, you need embed or object tags AND a JS-enabled PDF document (hopefully its your PDFs..), who can send messages to your page's JS (see this answer).
Unfortunately, I couldn't find a scroll event in Adobe's Acrobat API Reference. It lists only these events:
Event type: Event names
App: Init
Batch: Exec
Bookmark: Mouse Up
Console: Exec
Doc: DidPrint, DidSave, Open, WillClose, WillPrint, WillSave
External: Exec
Field: Blur, Calculate, Focus, Format, Keystroke, Mouse Down, Mouse Enter, Mouse Exit, Mouse Up, Validate
Link: Mouse Up
Menu: Exec
Page: Open, Close
Screen: InView, OutView, Open, Close, Focus, Blur, Mouse Up, Mouse Down, Mouse Enter, Mouse Exit
So, basically, I think what you want just isn't possible as for now, at least with default rendering. With custom rendering (https://github.com/mozilla/pdf.js) it could be possible, though I'm not sure.
Apparently, it could be done with page scroll (see this issue). So back to iframes solution. :^D
Because this question is asked a long time ago, i think i need to help with my experience before.
The answer is: You can not
Why? because PDF is rendered by external apps, such as adobe pdf reader, foxit or else. And you can not attach event on them.
if you are using adobe reader, The only you can do is goto page, change zoom etc. Full example you can read here: https://www.adobe.com/content/dam/acom/en/devnet/acrobat/pdfs/pdf_open_parameters.pdf#page=8 (see. i bring you to page 8 directly instead to first page).
But, hei.. how if our client using another apps? we will confused more
The way to do this is only build your own pdf viewer.
we can using js library, like: http://www.bestjquery.com/2012/09/best-jquery-pdf-viewer-plugin-examples/
but here i only will show you to use pdf.js which created by mozilla.
main.php
<style>
.preview{
display:none;
width: 400px;
height: 400px;
border: 1px solid black;
}
</style>
file/test.pdf<br>
file/test1.pdf<br>
<div class="preview">
<iframe id="myiframe" frameborder="0" width="400px" height="400px" >not support iframe</iframe>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
$(document).on('click', '#nextpdf', function(e){
e.preventDefault();
$('#myiframe').attr('src', $(this).attr('href'));
$('.preview').show();
});
//handle iframe on scroll
$('#myiframe').on('load', function () {
$(this).contents().scroll(function () {
console.log('scrolled');
}).click(function(){
console.log('clicked');
});
});
});
</script>
pdfreader.php
<?php
$path = 'file/';
$pdf = isset($_GET['pdfxs']) ? $path . $_GET['pdfxs'] : '';
if(!file_exists($pdf) || !mime_content_type($pdf) =='application/pdf') die('file not found');
?>
<div id="pdf-container">
<div id="pdf-box"></div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="//mozilla.github.io/pdf.js/build/pdf.js"></script>
<script>
$(function(){
//original script : https://gist.github.com/fcingolani/3300351
function renderPDF(url, canvasContainer, options) {
var options = options || { scale: 1 };
function renderPage(page) {
var viewport = page.getViewport(options.scale);
var canvas = $(document.createElement('canvas'));
var renderContext = {
canvasContext: canvas[0].getContext('2d'),
viewport: viewport
};
canvas.attr('width', viewport.width).attr('height', viewport.height);
canvasContainer.append(canvas);
page.render(renderContext);
}
function renderPages(pdfDoc) {
for(var num = 1; num <= pdfDoc.numPages; num++)
pdfDoc.getPage(num).then(renderPage);
}
PDFJS.disableWorker = true;
PDFJS.getDocument(url).then(renderPages);
}
renderPDF('<?=$pdf;?>', $('#pdf-box'));
});
</script>
Note: i put pdf on folder file/
in main.php you will notice that you can attach event scroll (and click too) to the pdf. because our pdf is not rendered by external apps now.
and the last part is, if you read pdfreader.php carefully, you will notice that you no need iframe anymore. You just need div, and then you can fully handle all event that do you want to your pdf : like scroll, click, change page, zoom, etc. why?? because your pdf is redered as canvas now (pdf.js render your pdf as HTML5 canvas). see full example of pdf.js
Please try this
iframe.on( "scroll", handler )
$("#frame").scroll(function () {
if ($(window).scrollTop() == $(document).height() - $(window).height())
alert('Bottom reached');
});
I found this in the JSFiddle that was referenced in the Fiddle you linked. The HTML field is empty. This CSS was in there, too.
body {
height: 1500px;
}
In the fiddle that you linked, the <iframe> has an ID of frame. I figured you can use the jQuery selector like $("#frame").
I think this will help you.
$("#myiframe").load(function () {
$(this).contents().scroll(function () {
//your code here
});
});
I'm working on a web application using JSF and Javascript. I have a question about how to open a pop-up and add information into it.
Indeed, i'm using html2canvas to get the image of the content of a HTML page.
This is the code of my js :
function openPopupWithScreenshot(){
html2canvas($('#contentBody'), {
onrendered: function (canvas) {
var img = canvas.toDataURL("image/png");
window.open(img);
}
});
}
And the code of my button in JSF:
<h:commandButton value="#{bundle.button_print}" onclick="openPopupWithScreenshot();"/>
The code works perfectly, when i click on the button, a popup appears with my image. But my problem is I want to add more information (stored in a Javabean) into my popup.
Schematically, i want that my popup displays my image and a String stored in my Javabean. I'm a noob in javascript and i don't know how to do.
Could you help me please?
Thank you.
EDIT :
I have tried this :
function ouvrirPopupAvecImprEcran(){
html2canvas($('#contentBody'), {
onrendered: function (canvas) {
var img = canvas.toDataURL("image/png");
var newImg = window.open(img);
newImg.document.write("<title>TITLE</title>");
newImg.document.write("<img src='"+ img.src +"'/>");
newImg.document.write("<p>TEST</p>");
}
});
}
My popup appears correctly but my image is not display because it doesn't find the source of my image. How could i modify this?
You was almost there, try this:
function ouvrirPopupAvecImprEcran(){
html2canvas(document.body, {
onrendered: function(canvas) {
var img = canvas.toDataURL("image/png");
var newImg = window.open();
newImg.document.write("<title>TITLE</title>");
newImg.document.write("<img src='"+ img +"'/>");
newImg.document.write("<p>TEST</p>");
}
});
}
The image you created from canvas here var img = canvas.toDataURL("image/png"); was not the HTML Element img. It was a string with data: URL, it's like an image encoded into string.
To understand it better you could look at HTMLCanvasElement#toDataURL() method here http://developer.mozilla.org/en/docs/Web/API/HTMLCanvasElement
I am trying to use fancybox v2 to show a div whose contents are generated dynamically. I set the size of the div quite late in the scheme of things. I have tried the examples from fancybox's documentation for displaying divs whose size is fixed. It looks like this:
<a id="fancy" href="#showdiv">Show contents of div.</a>
<div id="showdiv">...</div>
<script>
$(document).ready(function() {
$("#fancy").fancybox({autoSize:false, width: W, height: H, ...});
});
</script>
What I want is W=$("#showdiv").width and H=$("#showdiv").height. Obviously, H and W are not available to me at document ready. How do I go about doing this?
EDIT: Here is the html for the content div:
<div id="hidediv" style="display:none">
<div id="showdiv" style="display:block;position:relative">
<canvas id="mycanvas" style="position:relative;display:block"></canvas>
</div>
</div>
In a click handler of the anchor "#fancy" I do:
function onclick() {
var jcanvas = $("#mycanvas").css('width', some_width).css('height', some_height);
// draw on canvas
}
"#fancy" is the one associated with Fancybox.
Assuming that this function handles the response of your HTTP POST
function onclick() {
// set size of canvas
var jcanvas = $("#mycanvas").css({
"width": some_width, // variable from response ?
"height": some_height
});
// draw on canvas
}
... then call that function using the fancybox afterLoad callback like
$("#fancy").fancybox({
fitToView: false, // the box won't be scaled to fit the view port (optional)
afterLoad: onclick()
});
EDIT :
Another option is to handle both, the canvas and fancybox within the same function using jQuery .on() so if you have
<a id="fancy" href="#showdiv">Show contents of div</a>
use this script :
$("#fancy").on("click", function () {
// do HTTP POST
// on success, get size form response
var some_width = 300,
some_height = 180;
// set canvas size
var jcanvas = $("#mycanvas").css({
// variables from response
"width": some_width,
"height": some_height
});
// draw on canvas
//
// then open fancybox ($(this) = #showdiv )
$.fancybox($(this),{
// API options etc
fitToView: false
});
});
in this case you don't need any callback.
NOTE : .on() requires jQuery v1.7+
See JSFIDDLE for documentation purposes.
i have many links in my page each with two attributes that are format & src.
<a class="play" src="'.$p['video_path'].'" format="'.$p['video_type'].'"></a>
what its clicked i get its 2 attr and make HTML in js like this.
$(".play").live('click',function() {
var src = $(this).attr('src');
var fmt = $(this).attr('format');
var html = '<video width="200" height="240" controls> <source src="'+src +'" type="video/'+ fmt +'"> </video>';
$("#myVideoDiv").html(html);
$.mobile.changePage( $("#myVideoDiv"), { transition: 'pop' } );
});
<div data-role="dialog" id="myVideoDiv"></div>
when i clicked on any video link my browser url changes like this
http://pp.local/maps/maps/40295472#&ui-state=dialog
but nothing displaying just a white screen.
although its working $("#myVideoDiv").html( html ); i can see the HTML through Firbug.
No error or Warning in Firebug:(
Basically what i need to do is that i want to show each video in jquery Mobile dialog like we do in normal jquery UI like the code below.i need to do same thing here too but with jquery mobile dialog.
$(".watchVideo").live('click', function() {
if( $('div.ui-dialog').length ) {
$('div.ui-dialog').remove();
}
var path = $(this).attr('rel');
var title = $(this).attr('title');
var $dialog = $('<div>', {
title: 'Title'
}).dialog({
autoOpen: false,
modal: true,
width: 600,
height: 500,
closeOnEscape: false
});
var tab = '<table id="video_player" style="margin: 10px 10%;"><tr><td><object codebase="http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0" classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"><param value="'+path+'" name="src"><param value="true" name="autoplay"><param value="true" name="controller"><embed pluginspage="http://www.apple.com/quicktime/download/" controller="true" style="height:300px;width:400px;background-color:#D9EBFB" autoplay="true" target="myself" src="'+path+'"></object></td></tr></table>';
$('<div id="updateContent">').html( tab ).appendTo( $dialog );
$dialog.dialog('open');
return false;
});
I have successfully recreated your problem, unfortunately I can't be 100 % sure this is the problem. I think you have a an error with your page/dialog setup.
Take a look at my working example, try to use it in your app: http://jsfiddle.net/Gajotres/5REkc/. This example uses dialog as a video container:
$('#index').live('pagebeforeshow',function(e,data){
$('#show-video').live('click', function(e) {
$('#video-content').append('<video width=450px height=300px controls="controls"><source src="http://dev.swinginsam.com/_files/testvid_01.ogv" type="video/ogg"></video>');
$.mobile.changePage("#second", { transition: "slide"});
});
});
I have also created another example for you. This one is much better and it uses popup as a video container. Unlike dialog popup will resize to accommodate video tag: http://jsfiddle.net/Gajotres/vscrU/.
$('#index').live('pagebeforeshow',function(e,data){
$('#show-video').live('click', function(e) {
$('#popup-video').append('<video width=600px height=300px controls="controls"><source src="http://dev.swinginsam.com/_files/testvid_01.ogv" type="video/ogg"></video>');
$('#popup-video').popup("open");
});
});
<div data-role="popup" id="popup-video" data-tolerance="15,15" class="ui-content"</div>
Data tolerance is here so popup can have a padding. Without it video player is overflowing popup container.
One more thing, I can see you are using php for content generation. In this case popup is much better solution. Unlike dialog (which acts as another page, and is a another page), popup is a part of a single page, so i has a much better usability in server side generation.
WARNING:
My examples will only work in firefox browser. I have used only a ogg video source. Video sources are taken from this post.