I made a web app that loads images using jquery, ajax and json. I got it to work in Firefox, but alas, Safari and Chrome remain stubborn.
It has to do with a "race condition" where images don't load quickly enough, so I have a load event as well as a trigger event to wait until all images are loaded before appending the html to a container div.
Here is the link to the page that works in FF:
http://chereecheree.com/dagworthy/style.html
And some code:
var aSectionImages = new Array;
//count how many images are in a section:
var aImagesCount = new Array();
//count how many images of a particular section have been loaded
var aImagesLoaded = new Array();
var htmlString;
var jsonStyleImages = "images.json"
var jsonNavImages = "imagesNav.json";
//container div:
var scrollableArea = $("#scrollableArea");
$.getJSON(jsonNavImages, getNavIcons);
$.getJSON(jsonStyleImages, makeScroller);
//trigger this function on load event:
function imageLoaded(oImg){
//get the name of the section of images:
var locSectionId = (imageInSection(oImg.src)).replace(/\s|'/g, "_");
//get the file name of the current image
var locFileName = getFileName(oImg.src);
if (aImagesLoaded[locSectionId]===undefined){
aImagesLoaded[locSectionId] = new Array;
};
//check if it has already been loaded by seeing if it exists in the array of loaded images:
var inArray = false;
inArray = $.inArray(locFileName, aImagesLoaded[locSectionId]);
if (inArray == -1) {
//array.push returns the new length of the array:
var tempLength = aImagesLoaded[locSectionId].push(locFileName);
}
if (tempLength==aImagesCount[locSectionId]){
htmlString += "</div>";
scrollableArea.append(htmlString);
//after the html has been appended, force it to be 1000 px -- totally unstable hack.
scrollableArea.width(1000);
}
}
//helper function to get section name of a loading image:
function imageInSection(src){
var resultId=false;
var locFileName = getFileName(src);
for (var k = 0; k < aSectionImages.length; k++){
for(var j=0; j < aSectionImages[k].images.length; j++){
tempSrc = aSectionImages[k].images[j].src.split("/");
tempFileName = tempSrc[tempSrc.length-1];
if (tempFileName == locFileName) {
resultId = aSectionImages[k].id;
}
}
}
return resultId;
}
//helper function to get the file name of a loading image:
function getFileName(href){
var resultFileName=false;
var locSrc = href.split("/");
resultFileName = (locSrc[locSrc.length-1]);
return resultFileName;
}
//function called when ajax request is successful -- it puts together the html string that will be appended to the containter div
function makeScroller(data){
aSectionImages = data;
for (ii=0; ii<aSectionImages.length; ii++){
var locData = aSectionImages[ii];
var locId = locData.id.replace(/\s|'/g, "_");
aImagesCount[locId] = locData.images.length;
htmlString = "<div id=\"" + locId + "\">";
for (jj=0; jj<locData.images.length; jj++){
var oImage = new Image();
var locImage = locData.images[jj];
$(oImage)
.load(function(){
imageLoaded(oImage);
})
.attr("src", locData.images[jj].src);
if (oImage.complete && oImage.naturalWidth !== 0){
$(oImage).trigger("load");
}
//alert (oImage.width);
locImage.id ? locImage.id = " id=\""+locImage.id+"\" " : locImage.id = "";
htmlString += "<img height=\"" + locImage.height + "\"" + " width=\"" + oImage.width + "\"" + locImage.id + " src=\"" + locImage.src + "\" />";
}
}
}
But it's probably best to look at it online, as there is a plugin that's used.
Anyhow, the computed style for the container div shows up at "0px" sometimes, which is why I'm forcing it to "1000px" but that hack is not very stable.
Any ideas would be greatly appreciated.
Thanks!
--Daniel.
In this section:
$(oImage)
.load(function(){
imageLoaded(oImage);
})
.attr("src", locData.images[jj].src);
if (oImage.complete && oImage.naturalWidth !== 0){
$(oImage).trigger("load");
}
image.naturalWidth isn't available in all browsers (so undefined !== 0 won't be a correct check), but you don't need it to use it, just rearrange the code, like this:
$(oImage).one('load', function(){ imageLoaded(this); })
.attr("src", locData.images[jj].src)
.each(function() {
if (this.complete) $(this).trigger("load");
});
This uses .each() to loop through after setting the src and triggers the load event in case it came from cache (this.complete being instantly true indicates this). The .one() call ensures the load event only fires once, whether from cache or a normal load.
Related
I have this basic code for the development of what I need, who can help me is a lot of help for me !!
note: I used the function .search () and replace () without getting good results, I do not know what else way to take
var fjstr = document.getElementsByClassName("js-product-variants-list");
var fjinnerColor = '';
var fjscolor2 = ["Rojo-Wengue",
"Aqua-Natural",
"Gris/Decape",
"Rosa-Blanco",
"Turqueza-Wengue",
"Turqueza-Blanco",
"Naranja-Natural",
"Amarillo-Natural"];
var resultado = "";
var pos = -1
fjscolor2.forEach(function(element) {
pos = fjstr.innerHTML.search(element.toString());
if(pos!=-1){
resultado += "<a href='#" + (fjscolor[i]) + "' ><li class='fj-product-color-icon' id='color-" + (fjscolor[i]) + "'></li></a>"
document.getElementsByClassName('cont-product-variacion-color')[0].firstElementChild.innerHTML = resultado;
}
});
I'm creating a print function and the key is to call the grid that I want to print. It has been working well if the grid is existing on the aspx page, until when I also need to print a list of RadGrids that are generated programmatically behind the code then JavaScript cannot detect these non-existing grids and return the error of "the control does not exist". Just to be clear, it's not working because at the time when I'm typing the code, there's no RadGrid_Dynamic on the page, hence erroring. There's nothing to do with when the page execute/page life cycle etc.
My work around is to try to call the control by string value, as using
$find('<%= RadGrid_Dynamic.ClientID %>'),
the page will highlight RadGrid_Dynamic and say it doesn't exists as mentioned above. Below is my code, I've also tried replacing the $find() with document.getElementById(), but no luck, any advice? Thanks.
function getOuterHTML(obj) {
if (typeof (obj.outerHTML) == "undefined") {
var divWrapper = document.createElement("div");
var copyOb = obj.cloneNode(true);
divWrapper.appendChild(copyOb);
return divWrapper.innerHTML
}
else {
return obj.outerHTML;
}
}
function Print() {
var previewWindow = window.open('about:blank', '', '', false);
var styleSheet = '<%= Telerik.Web.SkinRegistrar.GetWebResourceUrl(this, RadGrid1.GetType(), String.Format("Telerik.Web.UI.Skins.{0}.Grid.{0}.css", RadGrid1.Skin)) %>';
var baseStyleSheet = '<%= Telerik.Web.SkinRegistrar.GetWebResourceUrl(this, RadGrid1.GetType(), "Telerik.Web.UI.Skins.Grid.css") %>';
var htmlContent = "<html><head><link href = '" + styleSheet + "' rel='stylesheet' type='text/css'></link>";
htmlContent += "<link href = '" + baseStyleSheet + "' rel='stylesheet' type='text/css'></link></head><body>";
for (i = 1; i < 13; i++) {
var CYGrid = "RadGrid_CY_Strategy_" + String(i);
var CYradGrid = $find('<%=CYGrid.ClientID %>'); //Highlighted as red and erorr: The Name 'CYGird' does not exist in the current content
var LYGrid = "RadGrid_LY_" + String(i);
var LYradGrid = $find('<%=LYGrid.ClientID %>'); //Ditto
htmlContent += getOuterHTML(CYradGrid.get_element());
if (LYradGrid.hidden == false) {
htmlContent += getOuterHTML(LYradGrid.get_element());
}
}
htmlContent += "</body></html>";
previewWindow.document.open();
previewWindow.document.write(htmlContent);
previewWindow.document.close();
previewWindow.print();
if (!$telerik.isChrome) {
previewWindow.close();
}
}
You could programmatically assign an ID to the dynamic grid when it's being created and use that ID to do a $find().
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;
}
I made a function to add <a> tag in chat text and it worked fine, but it seems the variables of the function are shared between different instances of the function called from different chat rooms. I thought function variable were local, can anyone explain why I'm encountering this problem? Well I found out the code was wrong and a <p> tag the ajax function was adding to the string was interfering with this function. i fixed it by adding a space before the conflicting <p> tag and now it works fine...updated the code with english variable names too :)
function ajoutertagdelien(dataChat)
{
if (dataChat)
{
}
else
{
dataChat = " ";
}
var chatsendvar = dataChat;
var linkLocation, chatStringLeftPiece, chatfinal = "", chatStringRightPiece, lienfin, LinkAlone, LinktagString, LinkPiece;
var linkTagA = new Array();
var variablelocation = new Array();
var variablechatsend = new Array();
var increment=0;
var earlierLinkLength = 0;
linkLocation = chatsendvar.indexOf("www.");
while (linkLocation != -1) {
increment++;//
if (linkLocation != -1)
{
chatStringLeftPiece = chatsendvar.substring(0,linkLocation);
LinkPiece = chatsendvar.slice(linkLocation,chatsendvar.length);
lienfin = LinkPiece.indexOf(" ");
LinkAlone = LinkPiece.substring(0,lienfin);
chatStringRightPiece = chatsendvar.substring(((lienfin + linkLocation)),chatsendvar.length) ;
console.log( chatStringLeftPiece + " droit et gauche " + chatStringRightPiece + " number of theloop in the while=" + increment);
LinktagString = "<a target='_blank' href='http://"+ LinkAlone+"'>"+LinkAlone+"</a>";
chatsendvar = chatStringLeftPiece + " " + chatStringRightPiece;
linkTagA.push(LinktagString);
variablelocation.push(chatStringLeftPiece.length + earlierLinkLength);
earlierLinkLength = earlierLinkLength + LinktagString.length +1;
}
linkLocation = chatsendvar.indexOf("www.");
}
for (var x = 0, j = linkTagA.length; x<j; x++) {
chatsendvar = chatsendvar.split('');
chatsendvar.splice((variablelocation[x]),1," "+linkTagA[x]+" ");
chatsendvar = chatsendvar.join('');
};
return chatsendvar;
}
All this code to detect links in a text?
I know that's not what you asked, but this small function can do this. It can detect links beginning with www. or http:// and even handles url parameters, like ?a=1&b=2. Here is a demo fiddle.
The regex could be modified to handle https:// or url encoding for example, but you get my point.
function makeLinks(text) {
return text.replace(/(?:http:\/\/|(www\.))([\w\d.\/\?&=]+)/gi, '<a target="_blank" href="http://$1$2">$1$2</a>');
}
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.