I had help with this background carousel made with jquery for a website and it works just great.. except that i find that the page can take a while to load initially.. i thought that if i actually downloaded the pictures that i'm using for the background instead of loading them via 'http://www.whatever.jpg', that the page might load faster.. but i'm kind of a noob still.. and haven't been able to figure out why this isn't working.. Here is my code:
var images = [
//even though I downloaded the picture and its in the same folder as this file.js, the background just loads a black page, then the other 2 load fine.
"bg1-orig.jpg",
"http://www.desktopaper.com/wp-content/uploads/Cool-Hd-Wallpapers-2.jpg",
"http://wallpaperscraft.com/image/restaurant_table_interior_modern_style_39288_1920x1080.jpg"
];
var $body = $("body"),
$bg = $("#bg"),
n = images.length,
c = 0; // Loop Counter
num = 200;
// Preload Array of images...
for(var i=0; i<n; i++){
var tImg = new Image();
tImg.src = images[i];
}
$body.css({backgroundImage : "url("+images[c]+")"});
(function loopBg(){
$bg.hide().css({backgroundImage : "url("+images[++c%n]+")"}).delay(7000).fadeTo(2200, 1, function(){
$body.css({backgroundImage : "url("+images[c%n]+")"});
loopBg();
});
}());
i've searched around for a while now... thanks for the help!
You do yourself no favors trying to pre-load the images right before they are loaded for display in your CSS. In either case, the images have to be loaded first before you can see them, so there is going to be a delay regardless.
If the only thing that you want to change is the src attribute of the imgs to be a local folder, then I assume the only change to otherwise working code is the strings in your images array point to local files.
If that's the case, and if you want to resolve the location correctly without adding some sort of directory changes (../, img/ or the like), then you will need those images to be in the same directory as the html file, not the file.js file.
Related
All of the assets of the site are in an array of objects that will be shown after user interaction, something like a slider.
{"id":"1","icon":"icon-name-class","sound":"soud-name"},
{"id":"2","icon":"icon-2-name-class","sound":"soud-2-name"},
....
{"id":"100","icon":"icon-100-name-class","sound":"soud-100-name"}
I have about 150 small icons and around 100 small sounds that need to be preloaded, been looking and didn't find anything related to preload assets from a js array.
I'm using the images as a background and getting the class name from the object.
I thought that all images would be ready since they are coming from a css class, but i guess that i am wrong
.icon-class-1 { background-image: url(../img/icons/img-1.png); }
this link or something similar to this could do the trick but after reading the doc couldn't find how to apply it when the assets origin is in an array that will be managed with js.
You have to loop through the object array to load them.
EDIT
Since you have a lot images which doesn't load via CSS.
I suggest you remove all these backgroung-image:url('...'); and put these URLs in your json like this:
{"id":"1","icon":"icon-name-class", "icon_url":"http://domain/path/file.jpg", "sound":"sound-name","sound_url":"http://domain/path/file.mp3"},
And do the same for your sound urls.
PLUS! It will ease the maintenance in the long run... If you notice a broken URL someday.
Then, preloading can be made like this:
var object_array = [
{"id":"1","icon":"icon-name-class", "icon_url":"http://domain/path/file1.jpg", "sound":"sound-name","sound_url":"http://domain/path/file1.mp3"},
{"id":"2","icon":"icon-name-class", "icon_url":"http://domain/path/file2.jpg", "sound":"sound-name","sound_url":"http://domain/path/file2.mp3"},
{"id":"3","icon":"icon-name-class", "icon_url":"http://domain/path/file3.jpg", "sound":"sound-name","sound_url":"http://domain/path/file3.mp3"}
];
// Preloading arrays
var icon_url_arr = [];
var sound_url_arr = [];
// Load counter
var loaded_counter={icon:0,sound:0};
function increment_counter(x){
loaded_counter[x]++;
}
// Loop through the data array
for(i=0;i<object_array.length;i++){
if(typeof(object_array[i].icon_url)!="undefined"){
icon_url_arr[i] = $("<img>").attr("src",object_array[i].icon_url).on("load",function(){increment_counter("icon");});
}
if(typeof(object_array[i].sound_url)!="undefined"){
var audio_element = $("<audio>").attr("id","audio_"+i);
sound_url_arr[i] = $("<source>").attr("src",object_array[i].sound_url).attr("type","audio/mpeg");
audio_element.append(sound_url_arr[i]).on("loadeddata",increment_counter("sound"));
$("#main").append(audio_element);
}
}
// Interval to check load status
var check_all_loaded = setInterval(function(){
console.log("Loded icons: " +loaded_counter.icon+ " Loaded sounds: " +loaded_counter.sound );
$("#icon").html((loaded_counter.icon/icon_url_arr.length)*100+"%");
$("#sound").html((loaded_counter.sound/sound_url_arr.length)*100+"%");
// Stop the interval when all loaded
if( (icon_url_arr.length==loaded_counter.icon) && (sound_url_arr.length==loaded_counter.sound) ){
clearInterval(check_all_loaded);
console.log("Load check Interval stopped.");
// Now you can use the loaded icons and sounds
cycle_data();
}
},10);
// cycle through data on interval
function cycle_data(){
console.log("Display Interval started.");
// Background
var i=0;
setInterval(function(){
$("#main").css("background-image","url("+icon_url_arr[i].attr("src")+")");
// Audio
$(document).find("audio").get(0).pause();
$(document).find("#audio_"+i).get(0).play();
// Increment loop counter.
i++;
// Reset counter when the array end is reached
if(i==icon_url_arr.length){
i=0;
}
},2000);
}
So it won't be displayed or played anywhere...
But the browser will have it loaded.
You may have to hide the audio players via CSS:
audio{
display:none;
}
I made a CodePen demo to make sure it is working.
There is only 3 items in json...
And images and sounds are pretty small.
So you won't really notice the load delay in this demo.
;)
I suggest you place this script in a document.ready() wrapper...
And within a setTimeout() function to execute it something like 0.5 to 2 seconds after document is ready.
So the rest of your page won't lag.
I have a TinyMCE button and it works apart from passing the data from the media gallery into a variable (to edit into the content).
I have the following:
window.on('select', function(){
var files = window.state().get('selection').toArray();
console.log(files.id);
});
which doesn't work, but if I change too:
window.on('select', function(){
var files = window.state().get('selection').toArray();
console.log(files);
});
I get "array (object)" in the console.log and by opening the object I can see id is one of the "fields" available and has a value.
The basic idea is the button (before this code) opens a media library (WordPress) and on selection of the images, it passes the ID's of the images to TinyMCE to print them (later) and the only part that's not working is the above.
Anyone able to point me in the right direction (vanilla js not my forte and first time using tinymce)
You simply have to iterate the files because there are multiple file in this array.
Try this code.
window.on('select', function(){
var files = window.state().get('selection').toArray();
var images = files;
for (var k in files) {
var file = files[k];
console.log(file.id);
}
});
i'm putting together a personal website as a portfolio and i'm having trouble getting a photo gallery to work. I found a free Javascript gallery (http://ettrics.com/lab/demo/material-photo-gallery/) that I decided to implement. When putting the page together locally, the javascript runs no problem, however when I upload the page to the site (which already has plenty of other javascript running) I get the following error when scrolling on the page, or when trying to 'fullscreen' one of the images by clicking on it:
TypeError: this._fullImgs is undefined
I tried to isolate the issue and found that a line of code was executing differently on the server, than locally, the excerpt is below:
Gallery.prototype._loadFullImgsDone = function() {
var imgLoad = imagesLoaded(this._fullBox);
imgLoad.on('done', function(instance) {
var imgArr = instance.images;
this._fullImgs = [];
this._fullImgDimensions = [];
this._fullImgsTransforms = [];
for (var i = 0, ii = imgArr.length; i < ii; i++) {
var rect = imgArr[i].img.getBoundingClientRect();
this._fullImgs.push(imgArr[i].img);
this._positionFullImgs.call(this, imgArr[i].img, i);
this._fullImgDimensions.push(rect);
}
this._fullImgsLoaded = true;
}.bind(this));
};
I have found that the images are being found from their source location, however
imgLoad.on('done', function(instance) {
...
executes differently. The site is located at http://http://samueller.tech/photo-best.html id anybody would like to see for themselves the error I am getting.
Thanks in advance, i'm at a complete loss of how to fix this.
I'm seeing (on that site) the resizeHandler is getting called before the images are loaded
Gallery.prototype._handleScroll = debounce(function() {
this._resetFullImg.call(this);
}, 25);
Gallery.prototype._handleResize = function() {
this._resetFullImg.call(this);
};
Then this._resetFullImg fails because there are no images loaded yet which is why this._fullImgs is empty. The code seems to have another variable called _fullImgsLoaded and probably the _resetFullImg method should do nothing if images haven't been loaded.
You could try adding that like this:
// in material-photo-gallery.js line 1379
Gallery.prototype._resetFullImg = function() {
if (!this._fullImagesLoaded) {
return
}
this._fullImgsTransforms = [];
for (var i = 0, ii = this._fullImgs.length; i < ii; i++) {
...
I don't know how this will affect the reset of the gallery code, but it might work. It makes some sense that on your production system, the page load time (with extra JS and stuff) is such that these events might get called before things are ready which is something you don't see locally.
good luck.
No idea what I'm doing or why it isn't working. Clearly not using the right method and probably won't use the right language to explain the problem..
Photogallery... Trying to have a single html page... it has links to images... buttons on the page 'aim to' modify the path to the images by finding the name currently in the path and replacing it with the name of the gallery corresponding to the button the user clicked on...
example:
GALLERY2go : function(e) {
if(GalleryID!="landscapes")
{
var find = ''+ findGalleryID()+'';
var repl = "landscapes";
var page = document.body.innerHTML;
while (page.indexOf(find) >= 0) {
var i = page.indexOf(find);
var j = find.length;
page = page.substr(0,i) + repl + page.substr(i+j);
document.body.innerHTML = page;
var GalleryID = "landscapes";
}
}
},
There's a function higher up the page to get var find to take the value of var GalleryID:
var GalleryID = "portfolio";
function findGalleryID() {
return GalleryID
}
Clearly the first varGalleryID is global (t'was there to set a default value should I have been able to find a way of referring to it onLoad) and the one inside the function is cleared at the end of the function (I've read that much). But I don't know what any of this means.
The code, given its frailties or otherwise ridiculousness, actually does change all of the image links (and absolutely everything else called "portfolio") in the html page - hence "portfolio" becomes "landscapes"... the path to the images changes and they all update... As a JavaScript beginner I was pretty chuffed to see it worked. But you can't click on another gallery button because it's stuck in a loop of some sort. In fact, after you click the button you can't click on anything else and all of the rest of the JavaScript functionality is buggered. Perhaps I've introduced some kind of loop it never exits. If you click on portfolio when you're in portfolio you crash the browser! Anyway I'm well aware that 'my cobbled together solution' is not how it would be done by someone with any experience in writing code. They'd probably use something else with a different name that takes another lifetime to learn. I don't think I can use getElement by and refer to the class/id name and parse the filename [using lots of words I don't at all understand] because of the implications on the other parts of the script. I've tried using a div wrapper and code to launch a child html doc and that come in without disposing of the existing content or talking to the stylesheet. I'm bloody lost and don't even know where to start looking next.
The point is... And here's a plea... If any of you do reply, I fear you will reply without the making the assumption that you're talking to someone who really hasn't got a clue what AJAX and JQuery and PHP are... I have searched forums; I don't understand them. Please bear that in mind.
I'll take a stab at updating your function a bit. I recognize that a critique of the code as it stands probably won't help you solve your problem.
var currentGallery = 'landscape';
function ChangeGallery(name) {
var imgs = document.getElementsByTagName("img") // get all the img tags on the page
for (var i = 0; i < imgs.length; i++) { // loop through them
if (imgs[i].src.indexOf(currentGallery) >= 0) { // if this img tag's src contains the current gallery
imgs[i].src = imgs[i].src.replace(currentGallery, name);
}
}
currentGallery = name;
}
As to why I've done what I've done - you're correct in that the scope of the variables - whether the whole page, or only the given function, knows about it, is mixed in your given code. However, another potential problem is that if you replace everything in the html that says 'landscape' with 'portfolio', it could potentially change non-images. This code only finds images, and then replaces the src only if it contains the given keyword.
I'm working on a site where I'd like to cycle images, similar to a slideshow, while the user is on the page. I've searched around and haven't been able to find a lead.
Has anyone done this with Rails and the Javascript frameworks it supports?
you could possible use the jquery cycle plugin, here's the link: http://malsup.com/jquery/cycle/ . It looks like it would do what you want.
FYI, Rails isn't particularly tied to any JS framework, even though it comes with prototype out of the box.
I assume that when you say AJAX, you don't mean AJAX. If you were to rotate the image using AJAX, you would have the rotated image being generated server side and sent to the client, as AJAX = performing requests with javascript. </pedantic>
With that said, you can use pretty much any JS image rotator you can find on google.
EDIT: Oh, you meant cycling through images, not rotating it e.g. 90ยบ clockwise etc. (?)
I've been using this very simple function. It doesn't use any framework and it doesn't fade between slides, but it should get you started.
function SlideShow( elem_id, hold_time )
{
this.elem = document.getElementById( elem_id );
this.slides = [];
this.num_slides = 0;
this.cur_slide = 1;
this.add_slide = function( image )
{
this.slides[ this.num_slides++ ] = image;
}
var self = this;
this.next_slide = function()
{
if ( self.num_slides > 1 )
{
self.elem.src = self.slides[ self.cur_slide++ ].src;
if ( self.cur_slide == self.num_slides )
self.cur_slide = 0;
}
}
setInterval( self.next_slide, hold_time )
}
the parameters are the element_id of an img tag and the number of mS to display each slide.
the add_slide function takes a JavaScript Image object.
The reason cur_slide is initialised to 1 is because I pre load the img tag with the first image.
In my application I create the slideshow in the window.onload method and arrange for each Image to add itself to the slide show as it is loaded.
Example (untested):
window.onload = function() {
var slide_show = new SlideShow( "slide_image", 4000 )
{ var img = new Image();
img.onload = function(){ slide_show.add_slide(img); };
img.src="/images/slide1.jpg"; }
...
/* Repeated for each image */
}
This approach is only valid if you don't care about the order of the slides.
I assume you want to make persistent changes on images. I'm working on a Rails app where we implemented resize, crop and rotate similar to features in snipshot.com
On technical side we used YUI for resize and crop in user interface and RMagick on server to process the images and send the results back to UI. YUI provides imagecrop widget out-of-the box.
We also considered doing a series of actions in UI and then submit the last result for server-side processing but that would have been lead to inadequate results.