My requirement is on Click of "Submit" button -
loop through "< li >" elements on HTML page, get the objectURL from each
"< li >" element, load the image on to Canvas and get dataURL from
it. Store these dataURLs inside hidden field on HTML page.
Then retrieve the dataURLs from Hidden fields, convert them to byte
array and proceed with further processing.
I targeted to achieve below way...
1.Using YUI3 java script (submitBehavior_js.js) to achieve the first part. Used ("click" event)
submitButton.add(new submitBehavior_js('click',parameters));
2.Overriding onSubmit() method of "Submit" button to achieve second part.
onSubmit(target,form)
{
String[] imgArray = null;
imgdata = hiddenImageData.getValue();
imgArray = imgData.split(',');
.........
}
I have gone through several threads and with my practical experience, onSubmit() java code is invoked before submitBehavior_js.js and so, the hidden fields didn't have any image data.
So, I tried to invoke the java script using "mouseup" event instead of "click". This was working perfectly fine and java script is running before the onSubmit() on wicket controller.
However, my code is adaptive web and it should work across browsers on mobile platforms. Evidently "mouseup" din't come to my rescue. I tried to use "touchend" and "gesturemoveend" events as suggested by YUI3 documentation, but in both cases onSubmit() wicket java code is executed before the javascript.
Then, I tried to invoke javascript as below:
onSubmit(target, form)
{
target.appendJavaScript("new submitBehavior_js('click',<<parameters>>)");
System.out.println("Inside Submit method in wicket");
String[] imgArray = null;
imgdata = hiddenImageData.getValue();
imgArray = imgData.split(',');
.........
}
With above piece of code, control is going to java script from Wicket controller but comes back to java code before executing the onLoad() of Canvas element. Here is my java script snippet...myCanvas is an hidden element on HTML(style=display:none)
alert("Start here");
var imgArray[];
var lineCtr = 0;
for each LI List item (Say I have 2 items)
{
var imageObjectURL = node.get('children').getAttribute('href')
image = new Image()
image.onLoad = function() {
alert("Inside onload of image to canvas");
var canvas = document.getElementById("#myCanvas");
var ctx = canvas.getContext('2d');
ctx.fillRectangle('white');
ctx.drawImage(image,700,600,0,0);
var data = ctx.toDataUrl();
imgArray[lineCtr] = data;
Y.one("#hiddenImageData").setAttribute('value',imgArray);
lineCtr = lineCtr + 1;
alert("finished here");
}
image.src = imageObjectURL;
alert("after assigning object URL. Completed List item");
}
The order of display/alert is as follows:
alert - Start here
alert - after assigning object URL. Completed List item
alert - after assigning object URL. Completed List item
JAVA Sysout - Inside Submit method in wicket
alert - Inside onload of image to canvas
alert - finished here
alert - Inside onload of image to canvas
alert - finished here
Because on load of Canvas element is executed after the java code, obviously the hidden Image Data variable has null values....and I am losing the captured/uploaded images by User.
Any reason for this weird behavior? or May be my understanding is wrong? Also, a better way to accomplish my task.
Appreciate your time and help!!
Do your JavaScript you want to do in an IAjaxCallListener like i showed in this answer. This way you make sure it is executed before the onSubmit() login is executed.
Related
I currently have a div that's used to display and image via CSS.
For example:
HTML
<div id="myDiv" class="play"></div>
CSS
.play{background: url('../img/playIcon_black.png') no-repeat;}
This image appears as it should.
What I'm attempted to do is to change the image by changing the class (via JavaScript).
Example:
CSS
.pause{background: url('../img/pauseIcon_black.png') no-repeat;}
JavaScript
function myFunction() {
myDiv.className = "pause";
}
When I call myFunction() everything seems to work correctly with one exception. Occasionally the image does not update in the browser.
A few things to note:
I'm certain the function is being called correctly. If I put a console.log() statement within the function, it prints when it should. Additionally, if I inspect the element within the browser, the class is in fact changed to .pause
The image changes from the "play icon" to blank once the function is called, BUT upon hovering over the div the images then appears permanently.
This only seems to happen once the page is initially loaded. Meaning, I can only recreate the issue once upon refresh, then everything works correctly after that.
I have attempted to clear my cache but nothing seems to have changed.
(I'm not sure how relevant this is) I'm calling myFunction() via onended attribute of an audio tag.
For example:
<audio onended="myFunction()"></audio>
But I'm not certain if this would affect anything because the function appears to be called correctly.
Any ideas of why this might be happening?
So the issue is that when you change the class, the browser has to fetch the new image, which takes time. One way to fix the issue is by using sprites, where both images are actually in one image and you only show a piece of that image at a time.
Another solution is to preload the image and then apply the preloaded image source to your new element like this:
var image = newImage();
image.src = '../img/pauseIcon_black.png';
function myFunction() {
var cssBackground = 'url(' + image.src + ') no-repeat';
myDiv.style.background = cssBackground;
// Optionally with jQuery instead:
// $('#myElementID').css('background', cssBackground);
}
Note that if you call myFunction before the image loads you'll encounter the same error. The difference is that this will load the image when the page is loaded (or more properly, when this JS executes and myFunction is assigned) rather than when myFunction is called. To ensure the image is loaded you can use the onLoad event handler for the image object. For more details on preloading images check out this answer: preload image then change background javascript
You need to get the element id
function myfunction(){
var myDivElem = document.getElementById('myDiv');
myDivElem.className = 'pause';
}
You can use document.getElementById("myDiv").className="";in your function
OK if you don't want use first solution you can use second one:
You can add a class to element using
document.getElementById("myDiv").className +=" n";
Then add a class named .play.n to your css file after class named.play
Then add your image address.
If you want to manipulate the div with id "myDiv". Use it as
document.getElementById('myDiv').class
Sample codesnippet: example snippet
I'll start by apologising as this may seem like or actually be a duplicate, but I've tried every solution I've encountered and none seem to be working for me.
In my HTML I have an iframe referencing another HTML document. With JavaScript, at the press of a list of buttons I insert text into the body of that iframe. I also use JavaScript to maintain focus on the iframe body. The problem is that nothing appears to work for me to get the cursor to move to the end of the text each time I press those buttons, it always moves to the beginning.
One of the solutions I've tried was to add this code to the function that handles my button presses:
iFrameBody.focus();
var content = iFrameBody.innerHTML;
iFrameBody.innerHTML = content;
so the function looks like this:
function typeIn(buttonId) {
var iFrameBody = document.getElementById("iFrame").contentWindow.document.body;
iFrameBody.innerHTML += buttonId;
iFrameBody.focus();
var content = iFrameBody.innerHTML;
iFrameBody.innerHTML = content;
}
Something else I tried was, in the HTML file referenced by my iframe I did:
<body onfocus="this.innerHTML = this.innerHTML;"></body>
I tried several other more complicated solutions that frankly I didn't even quite understand to be honest, all to no avail. Any help would be much appreciated.
I figured it out. The issue was that I was using a body element, writing to it's innerHTML and trying to set focus on the body. By simply using a textarea inside my iFrame instead it became very simple and it only required the simplest code.
This to set focus when the page loads:
window.onload = function () {
var iFrameTextArea = document.getElementById("iFrame").contentWindow.document.getElementById("iFrameTextArea");
iFrameTextArea.focus();
}
And then this to set the button to write to the textarea while maintaining focus:
function typeIn(buttonId) {
var iFrameTextArea = document.getElementById("iFrame").contentWindow.document.getElementById("iFrameInput");
iFrameTextArea.focus();
iFrameTextArea.value += buttonId;
}
Super easy!!
Instead of again using textarea in iframe, u can also solve this by using the following code.
var iframeElement = document.getElementById("iFrame").contentWindow.document.body;
iframeElement.focus();
var len = iframeElement.length ;
iframeElement.setSelectionRange(len, len);
We have a print functionality in our application where we are printing images in the browser. We are dynamically forming the HTML div with all the image sources [image source is from the webservice url]
When we trigger 'Windows.Print()' , only the first image is always available in print preview (chrome) and remaining images are displayed blank.
If i trigger the print event for the second time, all the images are getting printed without any issue because all the images are cached by that time.
Please let me know how to push all my images in cache before printing. I need to do this in javascript. Dont want to make any html change.
I am using backbone.js and creating a model view with the images. Then Binding the view in HTML. Then i ma using for printing. This works fine in IE and Safari. but not in chrome, it shows print preview screen and always trying to load all the images from browser cache. But i will not be having those images in the browser while giving printing. All my images sources are dynamic and coming from the service. I am just setting the url dynamically to the image source.
<%_.each( Documents, function(oDocument) {%>
<div class="images span1">
<img src="<%- oDocument.URL%>" width="98" height="70" />
</div>
<% });%>
in print preview only one image is coming rest all coming as dots. if i cancel the print and give print again all are coming fine.
Thanks,
Jeevitha
This can be done purely in JavaScript by using the Image object.
var cachedImage = new Image();
cachedImage.addEventListener('load', function () {
alert('Cached image loaded');
});
cachedImage.src = 'http://cdn.sstatic.net/stackoverflow/img/apple-touch-icon.png';
I have created a working JSFIDDLE example showing this at http://jsfiddle.net/pwdst/wc1zrL0v/
The new images could be created in response to a user event, for example clicking on a button, or even scrolling past a certain position. If the image from the server has the proper cache headers, it will then be retained in the browser cache for later use in your print page.
You will be able to see the request in the "Network" tab of the Chrome dev tools, or by using the excellent Fiddler tool from Telerik. Successful load will also trigger the load event listener added in the code sample.
I have called the custom function with the array of images i want to cache. Used Jquery 'Deffered' to hold the next operation until all the images are loaded. This is working very fine
var $deferredimages = $.Deferred();
var items = []; // load all the images paths
PreloadImages(items, loadImageitem, function (){
$deferredimages.resolve();
})
function PreloadImages(items, preloadimages, allDone) {
var count = items.length;
// this callback counts down the things to do.
var pendingimages = function (items, i) {
count--;
if (0 == count) {
allDone(items);
}
};
for (var i = 0; i < items.length; i++) {
// 'do' each thing, and await callback.
preloadimages(items, i, pendingimages);
}
}
function loadImageitem(items, i, onComplete) {
var onLoad = function (e) {
e.target.removeEventListener("load", onLoad);
// this next line can be removed.
// only here to prove the image was loaded.
document.body.appendChild(e.target);
// notify that we're done.
onComplete(items, i);
}
var img = new Image();
img.addEventListener("load", onLoad, false);
img.src = items[i];
img.style.visibility = 'hidden';
}
Reference http://jsfiddle.net/8baGb/1/
I'm making a html-5 based report generator. I created a button to upload a [HTML] page containing multiple paragraphs and tables, which is continuous.
Now my task is to display the whole contents into separated a4-sized pages, just like in Microsoft Word.]
This is the sketch: >>>LINK<<<
Here are part of my codes.
function xx (){
var fi = document.getElementById('fi').files[0];
reader.onload = function (e){
var reader = new FileReader();
var inner ="";
inner += this.result;
inn.innerHTML ="<center><div class='bg' id='0'><div id='testmain'>"+inner+"</div></div></center>";
}
reader.onerror = function (e){
dd.innerHTML = "error<br>";
}
reader.readAsText(fi);
}
After displaying the result of pages, users can click a specific part of the paper, just like a paragraph, then a pagebreak is created and the pages changes, the remaining content are pushed starting from top of next page.
Could you please give me some ideas about how to realize it?
Instead of using comments as chat to present my suggestion, here's my answer:
I once tried to do such a thing, back in html4. Here's the logic I was using. Create a div that has the exact size of your page CONTENT (after margins and all) put all your content in it and cycle through its direct children. If the current child's bottom is lower than his parent, take it and all the following children and put them in a new div CONTENT. Rinse and repeat.
For this, you will need to calculate the height of the container and cross-check it against the offset+height of the elements. My vanillaJS is a bit rusty as for browser specifics and all... So I will display the logic using jQuery but most of it can easily be made in pure JS. The code will assume that we have a div.page that has the right CSS to make it exactly the size of a content page, and that will not resize to content (overflow:hidden) and the document will contain one of those div with all the content of what should be in the pages...
$(document).ready(function(){
var $page = $('div.page');
var newPage = true;//To track if we loop
while(newPage){
newPage = false;
$page.children().each(function(){
if($(this).offset().top+$(this).outerHeight() > $page.offset().top+$page.height()){
$page = $('<div>').addClass('page').appendTo('body');
$(this).nextAll().appendTo($page);
$(this).prependTo($page);//Don't forget the element too.
newPage = true;
}
});
}
});
Edit: Just found out this is a chrome problem, the code works fine in firefox
I have an iframe on a webpage that shows a book formatted as html. I would like to insert some javascript within this iframe to make the book more dynamic (e.g. click on sentences, show animations etc). The iframe content is in the same domain as the parent page.
I can insert the javascript into the iframe but get an error calling a function in the inserted javascript. I've described the different bits of code below:
My parent page javascript is:
function iframeLoaded()
{
var iFrameID = document.getElementById('preview-iframe');
var jsLink = iFrameID.contentDocument.createElement("script");
jsLink.src="/tests/iframeAPI.js";
jsLink.type = 'text/javascript';
iFrameID.contentDocument.head.appendChild(jsLink);
iFrameID.contentWindow.initialiseApi()
}
and the html containing the iframe is:
<iframe id="preview-iframe" width="640" height="240" frameborder="0" src="./testpage.htm" onload="iframeLoaded()" scrolling="no"></iframe>
The contents of iframeAPI.js is:
window.initialiseApi = function() { alert("Hello world") }
Looking at the iFrame's html in the browser shows that the iFrameAPI.js tag is inserted ok into the iframe head, but I don't get the alert popup when the page is loaded. The error appears on the following line:
iFrameID.contentWindow.initialiseApi()
Uncaught TypeError: Object [object Window] has no method 'initialiseApi'
However I can run this line in the browser's javascript console and the alert popup works fine.
Any help would be much appreciated.
Thanks,
Brian
Edit: I've just tried with an onload event to make sure the page is loaded and I still have the problem:
My parent page javascript is now :
function iframeLoaded()
{
var iFrameID = document.getElementById('preview-iframe');
var jsLink = iFrameID.contentDocument.createElement("script");
jsLink.src="/tests/iframeAPI.js";
jsLink.type = 'text/javascript';
iFrameID.contentDocument.head.appendChild(jsLink);
jsLink.onLoad= iFrameLoaded();
}
function iFrameLoaded()
{
alert("Iframe loaded"); // Alert works ok
var iFrameID = document.getElementById('preview-iframe');
iFrameID.contentWindow.initialiseApi(); // Same error message on this line
}
It sounds like you are trying to use the function before the content has loaded.
try this instead:
var t = setTimeout(iFrameID.contentWindow.initialiseApi(),500);
This will wait half a second before trying the function which should give the page tiem to load. Delay times are given in milliseconds.
An even better approach is to try using Jquery and its ready() method but this requires the jquery library to be loaded as well. Its well worth it though in my opinion, see http://api.jquery.com/ready/.
You would try something like:
$("body",iFrameID.contentWindow.document).ready(iFrameID.contentWindow.initialiseApi())
You're executing it right away without giving the script a chance to load. Hook up an onload event to your script block and run your main function then.
Try, in the page included in the iFrame, accessing the main page by doing something like:
window.parent.xyz = something;
Where something is what you want exposed to the main page. Could be a function or an object of functions. Now in the main page you can just do:
something(); // or something.somefunction();
You could also send window references, I think, but I have not tried that.
The easiest way is to call the initialiseApi function in the iframeAPI.js itself as it will be called as soon as it's loaded. The iframeAPI.js could look like that:
function initialiseApi() {
alert("Hello world");
}
initialiseApi();
There is no callback or timeout needed.