Sorry if this has been answered before but I searched for hours trying to find how to do what I am trying to do. I know php would probably have an easier solution but php might not an option. Jquery is preferable although pure javascript would be great too.
I'm trying to get divs from an external file by class name. There are multiple divs using the same class name. I want to get all the div of that class put in an array that I can loop through in a later part of the script.
I'm trying keep the contents of the divs of this page synced up to the divs of a page of an external html file that will always be changing. But I'm not sure how best to do this.
I have had good results getting data from csv files into divs in other projects, no problem, but this one has me stymied.
I tried the following (for testing purposes, I was just logging to console). I have confirmed that the external file loads just fine. I can see it load in the Chrome Dev Tools. But the data never really seems to go anywhere after that.
$(document).ready( function() {
var array = [];
var testfunc = $('.test').each(function () {array.push(this.innerHTML);});
$.get('sharedResources/Bio.html', function(testfunc){
console.log(array);
});
});
I tried other variations but they were even messier and the script started pulling from classes of the current page instead of the external file. I could see the innerHTML of the current page showing up in the console log.
I'm sure there is a much better way that I'm not seeing.
I also tried something else I saw suggested online but this didn't works either. This gave me 'contents is undefined' error... not to surprised at that one.
$.ajax('sharedResources/Bio.html').done(function(e) {
$('.test').attr('innerHTML', contents);
});
Sorry if I am not asking this well. I don't often ask anything on these forums.
Thanks!
Assuming the URL is within the same origin, all you really have to do is
$.get('sharedResources/Bio.html', function(html){
var elements = $('<div />', {html: html}).find('.className');
}).fail(console.log);
And note that elements would only be available within that callback functions scope, as it's asynchronous.
Also note the added fail handler, and make sure you open the console and check for errors.
I thought it might be useful to someone else searching for this sort of thing to post what I ended up doing.
I used what I learned from adeneo's great suggestion (above) and was totally able to do what I needed to do. Thanks, adeneo
I needed to take team profile info from a bio page that often changes on the site and reuse & rearrange it on another page which needed to always be synced up.
So here is the code I ended up going with:
$.get('Bios.html', function(html){
var t_name = $('<div />', {html: html}).find('.t_name');
var t_creds = $('<div />', {html: html}).find('.t_creds');
var t_title = $('<div />', {html: html}).find('.t_title');
var t_bio = $('<div />', {html: html}).find('.t_bio');
var t_img = $('<img />', {html: html}).find('.t_img');
var t_imgTn = $('<img />', {html: html}).find('.t_imgTn');
var arrayLength = t_name.length;
for (var i = 0; i < arrayLength; i++) {
$('#name'+[i]).html(t_name[i]);
$('#creds'+[i]).html(t_creds[i]);
$('#title'+[i]).html(t_title[i]);
$('#bio'+[i]).html(t_bio[i]);
$('#bioImg'+[i]).html(t_img[i]);
$('#bioTn'+[i]).html(t_imgTn[i]);
}
}).fail(console.log);
});
It worked like a charm :-)
Related
I was working on a fairly large prototype in jsFiddle (which I've used many times for a similar purpose), and got an unpleasant shock when I hit the 'Update' button only be sent straight to http://jsfiddle.net with a completely empty code editor.
Luckily hitting 'Back' in the browser was sufficient to recover the lost code. But I quickly found that my code could not be saved, and that the problem didn't seem to affect any other bit of code on the site.
After a lot of trial and error, I determined that the code could not be saved due to the following benign-looking line:
window.location.href = "/u/deleteReport?reportId=" + reportId;
In fact, it appears that it's impossible to save any code (not even the most trivial of examples) on jsFiddle that contains window.location.href.*=.*;. I'm a bit surprised by this fact, and wondering if anyone knows why this limitation exists? It seems somewhat arbitrary and also entirely ineffective, as things like window["location"].href = "..."; are still allowed.
Here's an example; the following code can be saved in jsFiddle without any problems:
var path = window.location.href;
$("a").click(function(e) {
window["location"].href = path;
});
...while trying to save this equivalent code will dump you straight to the jsfiddle index page:
var path = window.location.href;
$("a").click(function(e) {
window.location.href = path;
});
Refer this Fiddle
Does anyone know of an explanation for why this happens?
i am using javascript to read the content of .aspx page. but i am not able to read it. i am using javascript as:
function edit(headtext,totext, bodytext, footertext){
alert('lll');
//var xmlDoc=new ActiveXObject("MSXML.DOMDocument");
xmlDoc.async="false";
xmlDoc.load("theme3ex.aspx");
var students = xmlDoc.documentElement;
alert('0000');
var student = students.childNodes(0);
document.getElementById('txtareahead').innerHTML = headtext;
document.getElementById('txtareato').innerHTML = totext;
document.getElementById('txtareabody').innerHTML = bodytext;
document.getElementById('txtareafooter').innerHTML = footertext;
location.href = "MailSender.aspx";
}
is there any problem eith my javascript..
First problem is that you've commented out the line which creates the AJAX object, so none of the subsequent code will work because they're trying to access an object which doesn't exist.
Second problem is that even if you uncomment that line, it's using Activex/MSXML which will only work with IE (and even then only older versions of IE).
In short, your code isn't good, and needs to be entirely redone rather than being fixed.
My recommendation is that you find a more up-to-date example of how to do AJAX code. Possibly even just use a good quality Javascript library like JQuery.
I agree with #Spudley's point.
It's also worth mentioning that if the textboxes such as txtareahead are ASP.NET TextBox Controls, then the ID's will have most likely changed during rendering.
Or, not precisely "executing," but updating a function that exists before the response with a function returned in the response.
Step 1
I have an HTML5 page that describes a location.
On the server side this page includes a ColdFusion file "MapFunction.cfm." (Which is used for consistent mapping all over the site at large.)
MapFunction.cfm outputs a javascript function "loadMap" mixed with the HTML.
loadMap() contains all the javascript needed to place a Bing map of the location on the page.
Some javascript in a separate js file actually calls loadMap().
This works when the page is first loaded.
Step 2
Search & results stuff is all fine too. Nothing needs to be done with the map here.
Step 3
When a search result is clicked, the result detail is loaded asynchronously via a jQuery $.get() request.
It returns mixed HTML and javascript which I use jQuery to traverse through.
With the jQuery objects I update specific areas of the page to show different details.
One of the areas I need to update is the map. That part isn't working.
What I'm working with is mixed HTML and Javascript that is identical in both Step 1 and Step 3:
<section id="mod-map" class="module mod-map">
<header class="mod-head">
Map <span class="arrow"></span>
</header>
<div id="map" class="mod-body">
<div id="cmMap" style="position:relative;width:369px;height:303px;"></div>
<script type="text/javascript" id="cfLoadMap">
// ...some global variables are defined to use...
function loadMap()
{
// ...Bing/Virtual Earth Map Stuff...
// This part here is unique to each location's detail
var propertypoint = new VELatLong(parseFloat(36.707756),parseFloat(-78.74204));
// ...More Bing/Virtual Earth Map Stuff...
// This part here is unique to each location's detail
var label = "<div class=\"wrapper\"><img onerror=\"replaceImage(this);\" src=\"noimage.jpg\" width=\"100\" class=\"thumb\" alt=\"\" /><div class=\"caption\"><br />City<br /> State, 12345</div></div>";
// ...More Bing/Virtual Earth Map Stuff...
}
</script>
</div>
</section>
Now, in Step 3 loadMap() does get called again, but it just refreshes the map to the same location. The loadMap() function as the browser knows it doesn't get updated with the one retrieved via ajax.
That updated block of mixed HTML & javascript above does get successfully added to the page after each ajax call. It is placed right where it originally is, but with different coordinates and captions where indicated by the comments above. The ajax callback looks like (slightly simplified):
$.get(urlToLoad, {}, function(data, status, request){
var newData = $(innerShiv(data, false)),
newModules = newData.find(".module");
// (innerShiv is used to make HTML5 tags work in IE. It's possible I'm going a little overboard with using it, but I had a lot of issues with IE. :-))
newModules.each(function(i){
var thisId = "#" + $(this).attr("id"),
thisBody = $(this).find(".mod-body").html(),
toReplaceAll = $("body").find(thisId),
toReplaceBody = toReplaceAll.find(".mod-body");
// These variables are used to choose add content in different ways based on thisID. Below is the one the map area is subject to.
toReplaceBody.html(innerShiv(thisBody));
}); // each
// Various things including loadMap() get called/re-initiated/etc. here
}, "html"); // get
This works in Firefox 3.6, but nowhere else I've tested (Opera 11, IE 7, Chrome 8).
I have done this before in a similar situation with dynamically PHP generated javascript written to a separate js file--$.getScript works great there. But this is mixed into the HTML of the ajax response.
I've been looking and have found and tried the following (among other things):
Attempted Solutions
1. var myScript = new Function($('script#cfLoadMap', data).text()); myScript();
2. eval(newData.text());
3. eval(newData.find("#cfLoadMap").text());
4. $("head").append(newData.find("#cfLoadMap"));
None of these so far seem to be doing any good.
I know there are a few other ways this could theoretically be done. But as it stands at the moment, I do not have any ability to change much of anything but what I do with the mixed HTML & javascript response. I need a solution where,
The details will be updated via ajax.
The javascript will be mixed in with the HTML.
The javascript will be a javascript function generated dynamically by ColdFusion.
Very similar questions have been asked & resolved before, so I hope this can be done. However, none of the solutions I've found are working for me. Might be making a mistake or missing something, or maybe it's just different when it's a function?
Any help would be appreciated.
Answer
It suddenly started working with the following code:
$.get(urlToLoad, {}, function(data, status, request){
var safeData = $(innerShiv(data, false)),
newModules = safeData.find(".module"),
newScript = safeData.find("script#cfLoadMap");
// Update Each module
newModules.each(function(i){
var jqoThis = $(this),
thisId = "#" + jqoThis.attr("id"),
newModule = jqoThis,
newModBody = jqoThis.find(".mod-body"),
curModule = $("body").find(thisId),
curModBody = curModule.find(".mod-body");
// Varies by id, this one is used by the map area.
curModBody.html(innerShiv(newModBody.html()));
}); // each
// Make sure plugins are bound to new content
$("body").oneTime(100, function(){
// Various things get initiated here
// Maps -- this one works: Chrome, Firefox, IE7, Opera
$("head").append(newScript);
// Maps -- these did not work
/*
// Firefox only (but Firefox always works)
runScript = new Function(newScript.text());
runScript();
*/
/*
// Firefox only (but Firefox always works)
eval(newScript.text());
*/
}); // oneTime
}, "html"); // get
One thing I did notice for sure was that without innerShiv, in all my browsers, $(data).find("script#cfLoadMap").text() was blank -- which I did not expect.
Most likely it's that functions in JavaScript can be declared in non-global scope, so when you're inserting the <script> tag, jQuery is evaling it, but not replacing the original function (as you noticed).
A fix for this would be to change how you declare the function from this:
function loadMap()
{
...
}
to this:
window.loadMap = function loadMap() {
...
}
That way the top-level loadMap will always be the latest one that came down from the server.
You may want to consider not modifying the client code this way as it can make debugging trickier, but that's totally up to you. Hopefully this answer works for you either way.
It suddenly started working with the following code:
$.get(urlToLoad, {}, function(data, status, request){
var safeData = $(innerShiv(data, false)),
newModules = safeData.find(".module"),
newScript = safeData.find("script#cfLoadMap");
// Update Each module
newModules.each(function(i){
var jqoThis = $(this),
thisId = "#" + jqoThis.attr("id"),
newModule = jqoThis,
newModBody = jqoThis.find(".mod-body"),
curModule = $("body").find(thisId),
curModBody = curModule.find(".mod-body");
// Varies by id, this one is used by the map area.
curModBody.html(innerShiv(newModBody.html()));
}); // each
// Make sure plugins are bound to new content
$("body").oneTime(100, function(){
// Various things get initiated here
// Maps -- this one works: Chrome, Firefox, IE7, Opera
$("head").append(newScript);
// Maps -- these did not work
/*
// Firefox only (but Firefox always works)
runScript = new Function(newScript.text());
runScript();
*/
/*
// Firefox only (but Firefox always works)
eval(newScript.text());
*/
}); // oneTime
}, "html"); // get
One thing I did notice for sure was that without innerShiv, in all my browsers, $(data).find("script#cfLoadMap").text() was blank -- which I did not expect.
However, I don't really see how this is different from what I had tried before and which failed. If someone spots a substantive difference, please let me know, for future reference?
(Note: it doesn't seem to make a difference that the Map bit is placed in the timeout, it works as well above it.)
I'm using Shadowbox.js to display a slideshow on a website.
This slideshow shows several pictures and I would like to know who's looking at what pictures.
For this purpose I'm using statcounter.com.
Shadowbox offers a so called hook to call a function when the slideshow opens and when it changes to another picture.
I've written a small piece of code to get things moving, but for some reason, I get an entry in my statcounter log, but the shadowbox does not appear.
When I don't use the onopen and onchange in the options, the shadowbox does display.
As a test you can set up a directory where you place below code. Create to subdirs in this directory called "sb" and "pix". Get the Shadowbox-application from the website and store it in the "sb" directory (http://shadowbox-js.com/download.html).
Next to that store 3 testimages (called image1.jpg, image2.jpg and image3.jpg) in the "pix" directory.
To check if statcounter is picking up the pictures, you can use my testaccount on statcounter.com (just for viewing: account testcase, password casetest1).
Please find the html with the code here: http://www.heres-online.nl/test/index.html
Please take into account, I only just starting in javascript and html programming.
I can imagine I'm overlooking something terribly simple ...
Any help is highly appreciated.
Instead of trying to insert an image tag that way, just make one:
var img = new Image();
img.src = "... tracker URL ...";
That's all you need to do. edit Also get rid of all those backslashes in your URL strings; there's no point to them.
edit again I think this is all you need:
var nonsense = 1;
function tracker() {
var img = new Image();
img.src = "http://c.statcounter.com/counter.php?sc_project=5981755&security=582aa718&invisible=1&u=" +
encodeURIComponent("http://my.pix/" + Shadowbox.getCurrent().content) +
'&nonsense=' + new Date().getTime() + '_' + nonsense++);
return true;
}
(added a "nonsense" parameter to try and overcome possible caching issues)
edits — OK note the "return true" and the change of "escapeURIComponent" (wrong) to "encodeURIComponent". (I always get confused because the old deprecated function was called "escape".)
Please hold your horses on my last comment. I made a mistake myself (typo).
Instead of encodeURIComponent I typed enocdeURIComponent (why not copy/paste ... yeah, well I just didn't).
The script is now doing exactly what I intended it to do. I know have a Statcounter entry for every picture in the slideshow! Superb. I'm very pleased with your help, this was really nagging me, not being able to get it running. And the speed of getting an answer here was really amazing!
I've posted your solution on the Shadowbox.js forum as well. I posted my question there too, but no answers yet. But for anyone strugling with the same issue, this solution might be helpfull.
Thanks again, and have a nice weekend!
I'm fully aware that this question has been asked and answered everywhere, both on SO and off. However, every time there seems to be a different answer, e.g. this, this and that.
I don't care whether it's using jQuery or not - what's important is that it works, and is cross-browser.]
So, what is the best way to preload images?
Unfortunately, that depends on your purpose.
If you plan to use the images for purposes of style, your best bet is to use sprites.
http://www.alistapart.com/articles/sprites2
However, if you plan to use the images in <img> tags, then you'll want to pre-load them with
function preload(sources)
{
var images = [];
for (i = 0, length = sources.length; i < length; ++i) {
images[i] = new Image();
images[i].src = sources[i];
}
}
(modified source taken from What is the best way to preload multiple images in JavaScript?)
using new Image() does not involve the expense of using DOM methods but a new request for the image specified will be added to the queue. As the image is, at this point, not actually added to the page, there is no re-rendering involved. I would recommend, however, adding this to the end of your page (as all of your scripts should be, when possible) to prevent it from holding up more critical elements.
Edit: Edited to reflect comment quite correctly pointing out that separate Image objects are required to work properly. Thanks, and my bad for not checking it more closely.
Edit2: edited to make the reusability more obvious
Edit 3 (3 years later):
Due to changes in how browsers handle non-visible images (display:none or, as in this answer, never appended to the document) a new approach to pre-loading is preferred.
You can use an Ajax request to force early retrieval of images. Using jQuery, for example:
jQuery.get(source);
Or in the context of our previous example, you could do:
function preload(sources)
{
jQuery.each(sources, function(i,source) { jQuery.get(source); });
}
Note that this doesn't apply to the case of sprites which are fine as-is. This is just for things like photo galleries or sliders/carousels with images where the images aren't loading because they are not visible initially.
Also note that this method does not work for IE (ajax is normally not used to retrieve image data).
Spriting
As others have mentioned, spriting works quite well for a variety of reasons, however, it's not as good as its made out to be.
On the upside, you end up making only one HTTP request for your images. YMMV though.
On the down side you are loading everything in one HTTP request. Since most current browsers are limited to 2 concurrent connections the image request can block other requests. Hence YMMV and something like your menu background might not render for a bit.
Multiple images share the same color palette so there is some saving but this is not always the case and even so it's negligible.
Compression is improved because there is more shared data between images.
Dealing with irregular shapes is tricky though. Combining all new images into the new one is another annoyance.
Low jack approach using <img> tags
If you are looking for the most definitive solution then you should go with the low-jack approach which I still prefer. Create <img> links to the images at the end of your document and set the width and height to 1x1 pixel and additionally put them in a hidden div. If they are at the end of the page, they will be loaded after other content.
As of January 2013 none of the methods described here worked for me, so here's what did instead, tested and working with Chrome 25 and Firefox 18. Uses jQuery and this plugin to work around the load event quirks:
function preload(sources, callback) {
if(sources.length) {
var preloaderDiv = $('<div style="display: none;"></div>').prependTo(document.body);
$.each(sources, function(i,source) {
$("<img/>").attr("src", source).appendTo(preloaderDiv);
if(i == (sources.length-1)) {
$(preloaderDiv).imagesLoaded(function() {
$(this).remove();
if(callback) callback();
});
}
});
} else {
if(callback) callback();
}
}
Usage:
preload(['/img/a.png', '/img/b.png', '/img/c.png'], function() {
console.log("done");
});
Note that you'll get mixed results if the cache is disabled, which it is by default on Chrome when the developer tools are open, so keep that in mind.
In my opinion, using Multipart XMLHttpRequest introduced by some libraries will be a preferred solution in the following years. However IE < v8, still don't support data:uri (even IE8 has limited support, allowing up to 32kb). Here is an implementation of parallel image preloading - http://code.google.com/p/core-framework/wiki/ImagePreloading , it's bundled in framework but still worth taking a look.
This was from a long time ago so I dont know how many people are still interested in preloading an image.
My solution was even more simple.
I just used CSS.
#hidden_preload {
height: 1px;
left: -20000px;
position: absolute;
top: -20000px;
width: 1px;
}
Here goes my simple solution with a fade in on the image after it is loaded.
function preloadImage(_imgUrl, _container){
var image = new Image();
image.src = _imgUrl;
image.onload = function(){
$(_container).fadeTo(500, 1);
};
}
For my use case I had a carousel with full screen images that I wanted to preload. However since the images display in order, and could take a few seconds each to load, it's important that I load them in order, sequentially.
For this I used the async library's waterfall() method (https://github.com/caolan/async#waterfall)
// Preload all images in the carousel in order.
image_preload_array = [];
$('div.carousel-image').each(function(){
var url = $(this).data('image-url');
image_preload_array.push(function(callback) {
var $img = $('<img/>')
$img.load(function() {
callback(null);
})[0].src = url;
});
});
async.waterfall(image_preload_array);
This works by creating an array of functions, each function is passed the parameter callback() which it needs to execute in order to call the next function in the array. The first parameter of callback() is an error message, which will exit the sequence if a non-null value is provided, so we pass null each time.
See this:
http://www.mattfarina.com/2007/02/01/preloading_images_with_jquery
Related question on SO:
jquery hidden preload