I'm trying to preload certain images that I have decorated with an attribute and I'm wondering if you guys can help me figure out what's going wrong here. I have
var barlen = $('#SSWEprogressbar').width(),
$elems = $('[data-srcurl]'),
n = $elems.length;
for ( var k = 0; k < n; ++k )
{
var $elem = $($elems[k]);
var img = new Image(),
url = $elem.attr('data-srcurl');
$(img).load(function(){
console.log("we're here");//TEST
$('#SSWEloaderfront').attr('src',url);
$('#SSWEloadprogress').width(k/n*barlen + "px");
});
var srctgt = $elem.attr('data-srctgt');
if ( srctgt == "srcattr" )
{
$elem.attr('src',url);
}
else if ( srctgt == "bgimg" )
{
$elem.css('background-image',url);
}
}
and then
console.log("we're here");//TEST
isn't being invoked. Any ideas?
You aren't setting the src attribute on the img element, so the load will never fire. You need to add $(img).attr('src', url);
Related
I need your help. My script validate images resolution before sending form.
The problem is that when script should stop because one or more photos is bigger than maximum resolution. It's not happening.
var err is counting number of bad resolution photos, but on the end, i dont know why it is always 0.
Any ideas?
jQuery("form").submit( function( e ) {
var form = this;
e.preventDefault();
var photos = document.getElementById('imgInp');
var howmany = photos.files.length;
var err = 0;
var img = new Array();
for (var i = 0; i < howmany; i++) {
if (photos.files[i]) {
img[i] = new Image();
img[i].src = window.URL.createObjectURL( photos.files[i] );
img[i].onload = function() {
window.URL.revokeObjectURL( this.src );
if( this.width < 1281 && this.height < 1025 ) {
} else {
alert('Zdjęcie jest zbyt duże');
err++;
}
};
} else {
form.submit();
}
}
if(err > 0) {
alert('Niestety ale jedno lub więcej zdjęć, które próbujesz załadować są zbyt duże (dopuszczalna rozdzielczość maksymalna to 1280 x 1024).');
} else {
alert('Ok'); // form.submit();
}
});
https://jsfiddle.net/5fv42o0e/2/
It's because
Image loading is asynchronous
Image loading takes time but browser won't pause your script it would keep running code that follows.For simplicity keeping aside your code assume I have this
var img = new Image();
img.onload = function(){ alert('image loaded');}
img.src = "lion.jpg";
alert('hello');
Because loading image will always take some finite time you would always see "hello" being alerted before "image loaded" always!
Now you can probably guess where the problem was , when your forloop was over completing all its iteration not even the first image is done loading up till that time so err is 0 therefore no error message.
How to solve?
You can choose from a variety of solutions - callbacks,promise,counters etc.Assuming it's a simple application below I have used counters to solve
<script>
var err = 0;
var counter = 0;
jQuery("form").submit( function( e ) {
var form = this;
e.preventDefault();
var photos = document.getElementById('imgInp');
var howmany = photos.files.length;
var img = new Array();
for (var i = 0; i < howmany; i++) {
if (photos.files[i]) {
img[i] = new Image();
img[i].src = window.URL.createObjectURL( photos.files[i] );
counter++;
img[i].onload = function() {
window.URL.revokeObjectURL( this.src );
if( this.width < 1281 && this.height < 1025)
{
} else {
alert('Zdjecie jest zbyt duze');
err++;
}
counter--;
if(counter === 0 ){
if(err > 0) {
alert('Niestety ale jedno lub wiecej zdjec, które próbujesz zaladowac sa zbyt duze (dopuszczalna rozdzielczosc maksymalna to 1280 x 1024).');
} else {
alert('Ok'); // form.submit();
}
}
};
}
}
});
</script>
Here is how it works : A counter will keep track of how many images are outstanding ie. for which src has been assigned but are waiting to get loaded.Increment counter each time you assign a src and decrement it each time an image gets loaded (onload function) also check if it was the last image to get loaded (check if counter is 0) if yes all images are done now run your check
So I'm making a slideshow that includes many img and video elements, some of which are large and so I want to "pre-load" all media assets so they don't have to load when you scroll to the slide they're on.
Now, from what I understand, to get a img element to truly load you need to "use" it and the hack for that is basically
var url = $myimg.attr('src');
$myimg.attr('src') = '';
$myimg.attr('src') = url;
So I know that I can pre-load all images with
function LoadMediaAssets ( )
{
var $imgs = $('img'),
k = 0;
for ( var k = 0; k < $imgs.length; ++k )
{
var $img = $($imgs[k]),
url = $img.attr('src');
$img.attr('src') = '';
$img.attr('src') = url;
}
}
My question is how I would add videos into the mix. How do you pre-load videos? Like this?
function LoadMediaAssets ( )
{
var $imgs = $('img'),
$vids = $('video'),
k = 0,
n = $imgs.length + $vids.length;
for ( var k = 0; k < $imgs.length; ++k )
{
var $img = $($imgs[k]),
url = $img.attr('src');
$img.attr('src') = '';
$img.attr('src') = url;
console.log("Progress : " + (++k/n * 100) + "%");
}
for ( var k = 0; k < $vids.length; ++k )
{
var $src = $($vids[k]).find('source'),
url = $src.attr('src');
$src.attr('src') = '';
$src.attr('src') = url;
console.log("Progress : " + (($imgs.length + (++k))/n * 100) + "%");
}
}
Is there an entirely better way to do this?
I'm trying to create a lightbox for my site, and I want it to load all the images from a given directory with a filename like image#.jpg.
This is the code I have:
for(var i=0; i<1000; i++)
{
var filename = "images/image"+i+".jpg";
$.get(filename)
.done(function() {
$('#lightbox').append('<img src="placeholder.gif">');
})
.fail(function() {
i=1000; //ugh
});
}
It kind of works, but only tries to load image1000.jpg.
Also, is there a better way to do something like this? I'm sure saying 'do this a ton of times and stop when I manually change the for loop counter' is frowned on.
If your image names are sequential like your said, you can create a loop for the names, checking at every iteration if image exists - and if it doesn't - break the loop:
var bCheckEnabled = true;
var bFinishCheck = false;
var img;
var imgArray = new Array();
var i = 0;
var myInterval = setInterval(loadImage, 1);
function loadImage() {
if (bFinishCheck) {
clearInterval(myInterval);
alert('Loaded ' + i + ' image(s)!)');
return;
}
if (bCheckEnabled) {
bCheckEnabled = false;
img = new Image();
img.onload = fExists;
img.onerror = fDoesntExist;
img.src = 'images/myFolder/' + i + '.png';
}
}
function fExists() {
imgArray.push(img);
i++;
bCheckEnabled = true;
}
after dynamicly creating some iframes, setting src and onload, I expect that the contents would be available for putting it to an array and sort the array. Next would be removing the iframes (interesting content already put in array) and create a table on my HTML-page. When no alert is set before sorting, the array is empty as the onload fires just before finishing the script. When an alert is place before sorting,I found the onload-procedure fired, array was populated and everything works fine?!! But I don't want to put an alert, can anyone explain what I did wrong? It's my first script so please help me to understand.
function LoadFile( ) {
var FName, PName, myID, myFrame;
var myBody = document.getElementById("StartList");
for ( var i = 0; i < FileList.length; i++ ) {
// Read input file into frame
FName = FileList[i].FName;
PName = FName + ".html";
myID = "iframe" + i;
// Create frame.
myFrame = document.createElement("iframe");
myFrame.setAttribute("id", myID);
myFrame.setAttribute("width","0");
myFrame.setAttribute("height","0");
myFrame.setAttribute('src', PName);
//Attach onload-event to frame, triggering ReadTableInfo.
if (myFrame.attachEvent){
myFrame.attachEvent("onload", function(){
ReadTableInfo();
});
} else {
myFrame.onload = function(){
ReadTableInfo();
};
}
myBody.appendChild(myFrame);
}
}
function ReadTableInfo() {
var a = document.getElementsByTagName("iframe")[idx];
var p = FileList[idx].FName;
var b = (a.contentWindow || a.contentDocument);
var td;
if ( b.document) {
b = b.document;
// Get and process table with functions and procedures.
var myTable = b.getElementsByTagName("Table")[5];
var myList = myTable.getElementsByTagName("TR");
var Name = "";
var Desc = "";
for ( var j = 0; j < myList.length; j++) {
Name = myTable.getElementsByTagName("TR") [j].getElementsByTagName("A")[0].innerHTML;
if ( myTable.getElementsByTagName("TR")[j].getElementsByTagName("TD")[1] != null) {
td = myTable.getElementsByTagName("TR")[j].getElementsByTagName("TD")[1];
Desc = td.textContent || td.innerText || "";
}
if ( searchval == "" || ( TestVal.test(Name) && searchkey == 1 ) || ( TestVal.test(Desc) && searchkey == 2 ) ) {
ProcList[ProcList.length++] = new AddProcList(Name.toLowerCase(), p.toLowerCase(), Desc);
}
Name = "";
Desc = "";
}
idx++;
}
}
function UpdateList( opt ) {
searchval = document.getElementById("edtSearchVal").value;
TestVal = new RegExp(".", "i");
if ( searchval !== "" ) {
if ( opt == 2 ) {
TestVal = new RegExp(searchval, "i"); // searchpattern for RegExp descriptions
} else {
TestVal = new RegExp(searchval.replace(" ","_"), "i"); // searchpattern for RegExp.
}
}
switch ( opt ) {
case 1: searchkey = 1;
break;
case 2: searchkey = 2;
break;
default:
searchkey = 3;
}
Init();
// Get package names from index.
SetFileList(); // Determines which external files to examine.
LoadFile(); // Loads the external files into iframes to be used later.
alert("Start generating list, this may take a while."); // Necessary to read frames! Don't know why???
var sortkeys = {FName:"a",PName:"a"}; // Sorting order of ProcList, which will be the listorder.
ProcList.keySort(sortkeys); // Sort ProcList.
TableCreate(); // Make new table with all entries in ProcList
}
Thanks for any comments, just here to learn from others :))
your LoadFile(); is loading content to iframe , and alert() is giving just enough time for iframe content to load completely, hence rest of the code works. If you remove alert then rest of the code is executed immediately before iframe content is loaded.
I would suggest to put onload even inside iframe page as well. Then propagate this event to parent window. To access parent container window you can do window.parent inside iframe.
I am trying to load a page and then run a javascript code on it, I found a Greasemonkey script that does the same, but I am having problems implementing the same thing in android, probably because I don't know anything about javascript.
This is the Greasemonkey script; it's supposed to a give a new link:
window.addEventListener("load", function ()
{
var link = document.evaluate("//div[#class='dl_startlink']/div/a[contains(#href,'"+window.location.href.match(/\?(.*)$/)[1]+"')]", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
if( !link.snapshotLength )
return;
location.href = link.snapshotItem(0).href;
}, false);
and this is how I want to run it:
public void onPageFinished (WebView view, String url) {
System.out.println("webview loaded");
webView.loadUrl("javascript:/*...........Javascript code here........*/");
}
Any ideas on how I get that link and load that page in the webview?
EDIT: Another version does the same thing.
var candidates = document.evaluate("//*[#class = 'dl_startlink']/div", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
if( !candidates.snapshotLength )
return;
//The DIV with the highest zIndex has the *real* link; the rest are useless.
- var maxDiv = candidates.snapshotItem(0);
- for( var i = 1; i < candidates.snapshotLength; i++ )
- if( maxDiv.style.zIndex < candidates.snapshotItem(i).style.zIndex )
- maxDiv = candidates.snapshotItem(i);
- location.href = maxDiv.children[0].href;
Ok, here's only simple Xpath query, which may be rewritten as CSS selector.
Also I decided to replace window.location.href.match(/\?(.*)$/)[1]. If my version will not work, replace first 2 lines with var query = window.location.href.match(/\?(.*)$/)[1];.
Actually, maybe even var query = window.location.search.replace(/^\?/,'') is enough.
window.addEventListener("load", function ()
{
var l = window.location;
var query = l.search ? (l.search.replace(/^\?/,'') + l.hash) : ""
var link = document.querySelector("div.dl_startlink > div > a[href='" + query + "']");
if (!link) return;
l.href = link.href;
}, false);
New code for Android:
var candidates = document.querySelector("div.dl_startlink > div");
if( !candidates.length)
return;
//The DIV with the highest zIndex has the *real* link; the rest are useless.
var maxDiv = candidates[0];
for( var i = 1; i < candidates.length; i++ )
if( maxDiv.style.zIndex < candidates[i].style.zIndex )
maxDiv = candidates[i];
location.href = maxDiv.children[0].href;
Compacted version:
webView.loadUrl("javascript:window.addEventListener('load',function(){var%20candidates=document.querySelector('div.dl_startlink>div');if(!candidates.length)return;var maxDiv=candidates[0];for(var%20i=1;i<candidates.length;i++)if(maxDiv.style.zIndex<candidates[i].style.zIndex)maxDiv=candidates[i];location.href=maxDiv.children[0].href;},false)");