I ran into a very surprising behaviour and I can't figure out what it comes from : I build 3 nested blank iframes in javascript but the third one is invisible.
Tested in Chrome. Here is the code : (https://jsfiddle.net/44uL3bku/)
(function() {
var i1 = document.createElement('iframe');
i1.width = 315;
i1.height = 300;
i1.addEventListener('load', function() {
this.contentDocument.body.innerHTML = 'IFRAME 1<br>';
var i2 = this.contentDocument.createElement('iframe');
i2.width = '100%';
i2.height = '100%';
i2.addEventListener('load', function() {
this.contentDocument.body.innerHTML = 'IFRAME 2<br>';
var i3 = this.contentDocument.createElement('iframe');
i3.width = '100%';
i3.height = '100%';
i3.addEventListener('load', function() {
this.contentDocument.body.innerHTML = 'IFRAME 3<br>';
});
this.contentDocument.body.appendChild(i3);
var i4 = this.contentDocument.createElement('iframe');
i4.width = '100%';
i4.height = '100%';
i4.addEventListener('load', function() {
this.contentDocument.body.innerHTML = 'IFRAME 3<br>';
});
this.contentDocument.body.appendChild(i4);
var bottom = document.createElement('div');
bottom.innerHTML = 'bottom';
this.contentDocument.body.appendChild(bottom);
});
this.contentDocument.body.appendChild(i2);
});
document.body.appendChild(i1);
})();
Just to be clear : the DOM tree is properly set, and the "IFRAME 3" is actually there. But it is just not displayed.
Also it only concerns blank iframes. As soon as there is a regular src everything works fine again.
Any idea ?
Thank you all !
Related
I have made a character fighting simulation website, but when you enter in the image for a character, it just makes the image appear as flat and a wallpaper instead of the original resolution. The purpose of this was to test my knowledge of html after a few months of not using it, aswell as to test some features to see if I can incorporate it into another project later on.
This is my script:
<!DOCTYPE html>
<html>
<head>
<script>
document.addEventListener("DOMContentLoaded", function() {
var characterList = [];
var characterListDiv = document.createElement('div');
characterListDiv.id = 'characterListDiv';
document.body.appendChild(characterListDiv);
var characterNameInput = document.createElement('input');
characterNameInput.id = 'characterNameInput';
characterNameInput.placeholder = 'Character Name';
document.body.appendChild(characterNameInput);
var characterImageInput = document.createElement('input');
characterImageInput.id = 'characterImageInput';
characterImageInput.placeholder = 'Character Image URL';
document.body.appendChild(characterImageInput);
var addCharacterButton = document.createElement('button');
addCharacterButton.id = 'addCharacterButton';
addCharacterButton.innerHTML = 'Add Character';
addCharacterButton.onclick = function() {
var characterName = document.getElementById('characterNameInput').value;
var characterImage = document.getElementById('characterImageInput').value;
var character = {
name: characterName,
image: characterImage
};
characterList.push(character);
var characterDiv = document.createElement('div');
characterDiv.innerHTML = character.name;
characterDiv.style.backgroundImage = 'url(' + character.image + ')';
characterListDiv.appendChild(characterDiv);
};
document.body.appendChild(addCharacterButton);
var fightButton = document.createElement('button');
fightButton.id = 'fightButton';
fightButton.innerHTML = 'Fight';
fightButton.onclick = function() {
var characterListCopy = characterList.slice();
var fightResults = [];
while (characterListCopy.length > 1) {
var character1 = characterListCopy.pop();
var character2 = characterListCopy.pop();
var winner = Math.random() > 0.5 ? character1 : character2;
var loser = winner === character1 ? character2 : character1;
fightResults.push({
winner: winner,
loser: loser
});
characterListCopy.push(winner);
}
var fightResultsDiv = document.createElement('div');
fightResultsDiv.id = 'fightResultsDiv';
document.body.appendChild(fightResultsDiv);
fightResults.forEach(function(fightResult) {
var fightResultDiv = document.createElement('div');
fightResultDiv.innerHTML = fightResult.winner.name + ' beat ' + fightResult.loser.name;
fightResultsDiv.appendChild(fightResultDiv);
});
};
document.body.appendChild(fightButton);
});
</script>
</head>
</html>
I have tried messing with the image section but nothing changes. Google doesn't help me.
If you mean that the whole image is not shown, then the cause is that a background image just uses the size of the div and not the size of the image.
You could solve that by giving the div a fixed height. You can also adjust the background size so that it always fills the whole div (cover) or shows the whole image (contain).
characterDiv.style.backgroundImage = 'url(' + character.image + ')';
characterDiv.style.height = "300px";
characterDiv.style.backgroundSize = "cover";
I probably should not be attempting this, but I have gotten so far and I don't want to give up now. I want to create my own Lightbox type script. I can create an absolute div with the class ligthbox and it covers the page. Then I create a img that is fixed and it animates when loading. The I also have nav arrows to move through the photos. All works accept when I click on the arrows it creates new close X and arrows. I don't understand because the is done through the animation function which is not attached to the arrow function.
I have added event.stopPropagation(); to the arrow function and the animate function but that did not work.
The function that initiates everything.
jQuery(".marks-lightbox img").click( function() {
var Img = jQuery(this),
cImg = Img.attr("src"),
allImg = jQuery(".marks-lightbox img");
//finding the current img from the available images
for(i=0; i < allImg.length; i++) {
if( jQuery(allImg[i]).attr("src") == Img.attr("src") ) {
lbImgCurrent = i;
}
}
makeLightBox()
});
function makeLightBox() {
var bodyHeight = jQuery("body").height(),
lightbox = jQuery("<div>").addClass("lightbox").css({"width":"100vw","height":bodyHeight}),
scrollTop = 72,
lbContainer = jQuery("<div>").addClass("lbContainer"),
lbImg = jQuery(".marks-lightbox img"),
imgSRC = jQuery(lbImg[lbImgCurrent]).attr("src"),
lbClose = jQuery("<span>").addClass("lb-close").text("X");
jQuery("body").prepend(lightbox);
lbContainer.appendTo(".lightbox");
jQuery('<img src="'+ imgSRC +'">').load(function() {
jQuery(this).appendTo(".lbContainer").css("display","none").addClass("lb-image");
var w = jQuery(".lb-image").width(),
h = jQuery(".lb-image").height(),
lbw = lightbox.width(),
margin = (lbw - w) /2;
jQuery(this).appendTo(".lightbox").css({"position":"fixed","display":"block","width":0,"height": 0}).animate({"top":scrollTop,"width":w,"height":h,"margin-left":margin, "margin-right":margin},1000,function(event){
var lbimg = jQuery(this),
lbH = lbimg.height() + 63,
lbLeft = lbimg.offset().left,
lbW = lbimg.width(),
larrow = jQuery("<div><</div>").addClass("left-arrow-lb lb-arrow"),
rarrow = jQuery("<div>></div>").addClass("right-arrow-lb lb-arrow");
larrow.appendTo("body").css({"position":"fixed","top":lbH/2,"left":lbLeft+18});
rarrow.appendTo("body").css({"position":"fixed","top":lbH/2,"left":lbLeft+lbW-90});;
lbClose.appendTo(".lightbox").css({"position":"fixed","top": lbH,"left": lbLeft+lbW - 18});
});
});
}
Here is the click function
jQuery("body").on("click",".left-arrow-lb", function() {
console.log(jQuery(this));
var lbImgLength = jQuery(".marks-lightbox img").length,
lbImg = jQuery(".marks-lightbox img");
lbImgCurrent = (lbImgCurrent < 1 ) ? lbImgLength : lbImgCurrent -1;
var imgSRC = jQuery(lbImg[lbImgCurrent]).attr("src");
console.log(imgSRC);
jQuery(".lb-image").attr("src",imgSRC);
});
Every click creates a load new img scr and animates the photo (unexpectedly) and creates new arrows and close x.
I found it was the on("load"... working every time an image was being loaded. So I created a var reload and set it to true. The in the on(load... function I said if not true return false. In the arrow functions set the reload to false. This prevented the on(load... working reloading.
I have created a "prev/next" slideshow using javascript, now I want to add a counter(1/10, 2/10, 3/10...) beside my "prev/next" buttons but nothing seemed to work.
This is my first time attempting to make a website, I know nothing about jQuery, so please stick with html+javascript if possible. Here is my script
var image = new Array(
"http://i990.photobucket.com/albums/af24/callmeaaaaj/AJ/_MG_7747.jpg",
"http://i990.photobucket.com/albums/af24/callmeaaaaj/AJ/1109163s.jpg")
var imgNumber=1
var numberOfImg=2
function previousImage(){
if(imgNumber>1){
imgNumber--
}
else{
imgNumber = numberOfImg
}
document.slideImage.src = image[imgNumber-1]
}
function nextImage(){
if(imgNumber < numberOfImg){
imgNumber++
}
else{
imgNumber = 1
}
document.slideImage.src = image[imgNumber-1]
}
if(document.images){
var image1 = new Image()
image1.src = "http://i990.photobucket.com/albums/af24/callmeaaaaj/AJ/_MG_7747.jpg"
var image2 = new Image()
image2.src = "http://i990.photobucket.com/albums/af24/callmeaaaaj/AJ/1109163s.jpg"
}
Script+html: http://jsfiddle.net/nLHY9/5/
(Prev/Next buttons seem not to be working on this----they work fine when I launched them from laptop to browser.)
you could have used some existing javascript image sliders, for example, sliderman slider, for your current code, you can do like, add an element like span, to hold the count, and you could add a function like:
function changeCounter(cur, total) {
document.getElementById("counter").innerHTML = cur + "/" + total;
}
and call it in your previousImage() and nextImage() functions, as in this demo jsfiddle
There are many pure css slideshows that are beautiful and can do impressive things. However, as you try to support older browsers, the pure css slideshows get less and less impressive or even impossible. JavaScript is the most flexible and powerful way to go. That being, I wanted to help you clean up your code. I only had a few minutes, so this is a quickly thrown together plugin, but it should get you on the right track.
First, a few notes on your code:
//you're missing semicolons everywhere. ";"
/* "var image" is very unclear.
* it's an array, so it should be plural "images"
* there aren't images in this array - it's image urls or sources
* instead of "new Array" you could just use "[]"
*/
var image = new Array(
"http://i990.photobucket.com/albums/af24/callmeaaaaj/AJ/_MG_7747.jpg",
"http://i990.photobucket.com/albums/af24/callmeaaaaj/AJ/1109163s.jpg")
var imgNumber=1 //the name doesn't mean anything. I have to assume that you mean "currentImgNumber" or something to that effect
var numberOfImg=2 //this could be determined by checking the length of your array - myArray.length
And here's my exampe plugin:
Live demo here (click).
/***** This section is how you use the plugin. I start writing with the usage and then I make it mean something *****/
window.onload = function() { //when the page is loaded
var fooElem = document.getElementById('foo'); //get an element where we will attach the plugin
var foo = Object.create(slideshow); //create a new slideshow object
foo.create({ //create a slideshow with the given options
element: fooElem, //the element where the slideshow will be
sources: [ //image urls
"http://i990.photobucket.com/albums/af24/callmeaaaaj/AJ/_MG_7747.jpg",
"http://i990.photobucket.com/albums/af24/callmeaaaaj/AJ/1109163s.jpg"
]
});
//we can make more of these and with different options
var barElem = document.getElementById('bar');
var bar = Object.create(slideshow);
bar.create({
element: barElem,
sources: [
"http://eggboss.com/wp-content/uploads/2013/09/The-Gentleman-233x300.png",
"http://fc07.deviantart.net/fs71/f/2013/040/8/a/profile_picture_by_classy_like_a_sir-d5uf426.jpg"
]
});
};
/**** now let's create the plugin and make it work as it is used above *****/
var slideshow = {
currentIndex: 0,
imgs: [],
create: function(options) {
options.element.className+= ' slideshow'; //add a class to the main element for styling
this.imgs = this.getImgs(options.sources); //make img html
var controls = this.getControls(); //make controls
//add the html to the element from the options
var frag = document.createDocumentFragment();
this.imgs.forEach(function(img) {
frag.appendChild(img);
});
frag.appendChild(controls);
options.element.appendChild(frag);
},
getImgs: function(sources) {
var imgs = [];
sources.forEach(function(src, i) {
var img = document.createElement('img');
img.src = src;
imgs.push(img);
if (i > 0) {
img.style.display = 'none'; //hide all but first image
}
});
return imgs;
},
getControls: function() {
var that = this; //so that we can access "this" within the click functions
var controls = document.createElement('div');
controls.className = 'controls';
var counter = document.createElement('span');
counter.className = 'counter';
this.setCounter(counter);
var prev = document.createElement('a');
prev.textContent = 'Prev';
prev.className = 'prev';
prev.addEventListener('click', function() {
newIndex = (that.currentIndex) ? that.currentIndex-1 : that.imgs.length-1;
that.changeImg(newIndex, counter);
});
var next = document.createElement('a');
next.textContent = 'Next';
next.className = 'next';
next.addEventListener('click', function() {
newIndex = (that.currentIndex !== that.imgs.length-1) ? that.currentIndex+1 : 0;
that.changeImg(newIndex, counter);
});
controls.appendChild(prev);
controls.appendChild(next);
controls.appendChild(counter);
return controls;
},
changeImg: function(newIndex, counter) {
this.imgs[this.currentIndex].style.display = 'none';
this.imgs[newIndex].style.display = 'inline';
this.currentIndex = newIndex;
this.setCounter(counter);
},
setCounter: function(counter) {
counter.textContent = (this.currentIndex+1)+' / '+this.imgs.length;
}
};
This is my code:
var i;
var pic = document.getElementById('image');
var picSrc = pic.src;
var fullSrc = picSrc.split('h.jpg')[0] + '.jpg';
pic.src = fullSrc;
document.getElementById('next').onmousedown = function () {
i = 0;
// it works up to here
pic.addEventListener("DOMAttrModified", function(event) {
if (i == 0 && event.attrName == "src") {
pic = document.getElementById('image');
i = 1; // this is to prevent endless loop
picSrc = pic.src;
fullSrc = picSrc.split('h.jpg')[0] + '.jpg';
pic.src = fullSrc;
}
});
return true;
};
It should work on imgur's horizontal layout albums, and replace the low-res images with full-res ones, one image at a time (currently displayed image).
On click of the "next" button, a new image is displayed. However, the script does not load the next full-res image. It only works with the first image loaded.
You're messing up your scope completely, invalidating the entire code after the first run. This should also pop up more than enough errors in your console. Reshuffle assignments to the right spot:
document.getElementById('next').onmousedown = function () {
var i;
var pic = document.getElementById('image');
var picSrc = pic.src;
var fullSrc = picSrc.split('h.jpg')[0] + '.jpg';
pic.src = fullSrc;
pic.addEventListener("DOMAttrModified", function(event) {
if (i == 0 && event.attrName == "src") {
pic = document.getElementById('image');
i = 1; // this is to prevent endless loop
picSrc = pic.src;
fullSrc = picSrc.split('h.jpg')[0] + '.jpg';
pic.src = fullSrc;
}
});
return true;
};
Depending on how the page works specifically (I can't see without having a real world use case) you might have to reassign the entire mousedown event as well.
On every mousedown you are adding a new DOMAttrModified event listener.
Try arranging your code to something like following:
var pic = document.getElementById('image');
var i;
pic.addEventListener("DOMAttrModified", function(event) {
if (i == 0 && event.attrName == "src") {
//pic = document.getElementById('image');
i = 1; // this is to prevent endless loop
picSrc = pic.src;
fullSrc = picSrc.split('h.jpg')[0] + '.jpg';
pic.src = fullSrc;
i = 0;
});
document.getElementById('next').onmousedown = function () {
var picSrc = pic.src;
var fullSrc = picSrc.split('h.jpg')[0] + '.jpg';
pic.src = fullSrc;
});
You should also try using the addEventListener instead of onmousedown
I have a function that places an image provided by the input of the user into the body of an html page. When a second input is received I want to replace this picture with the new one. I have attempted to do just this in the below function.
function show_image(src, alt) {
var img = document.createElement("img");
img.src = src;
img.width = 400;
img.height = 300;
img.alt = alt;
var counter;
var mynodes= new Array();
mynodes.push(img);
counter+=1;
if(counter==1){
// This next line will just add it to the <body> tag
document.body.appendChild(img);
}
else if(counter!=1)
{
var newNode=mynodes[counter-1];
var oldNode=mynodes[counter-2];
document.body.replaceChild(newNode,oldNode);
}
The variable counter is a local variable.
Each time the method is called counter is initialized to 0.
Same thing with your mynodesvariable. It is always going to have only one node in the array.
So you may want to change your logic here. Do you want help rewriting this function?
Your code is totally awkward. As far as I can tell, you could simply change the same img tag instead of changing the whole node each time. There's barely a reason for a function..
Click here for a live demo.
function changeImg(img, src, alt) {
//I doubt you even need a function for this.
img.src = src;
img.alt = alt;
}
var img = document.createElement('img');
//you could just use a css class instead...
//that's probably better anyway...why does your js care how it looks?
img.width = 400;
img.height = 300;
document.body.appendChild(img);
changeImg(img, 'http://static.jsbin.com/images/favicon.png', 'image');
var imgSrcInput = document.getElementById('imgSrc');
var imgAltInput = document.getElementById('imgAlt');
var button = document.getElementById('change');
button.addEventListener('click', function() {
changeImg(img, imgSrcInput.value, imgAltInput.value);
});
I put together an object oriented example. This makes your logic very reusable and friendly. Check out the code in action here (click).
window.onload = function() { //usage
var someElement = document.getElementById('someIdHere');
var anotherElement = document.getElementById('anotherIdHere');
imageReplacer.setup({
element: someElement,
initSrc: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRg-icdkibfDt8VE7FkaKZyVUh8SBR4YTGd-2Jz1wZeUVacv4YD8zrvwclN',
initAlt: 'Starting Image'
});
imageReplacer.setup({
element: anotherIdHere,
initSrc: 'https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcRrHWuOzgYPbsuSF9cYQo3ORkcdIC4-8xaszlCrI3f7arAC7vhV7HwMN_fG',
initAlt: 'Starting Image'
});
};
var imageReplacer = { //package up your app
setup : function(options) {
//create a new imageReplacer so that each one will operate independently. The "this" pointer will refer to each element's imageReplacer.
options.element.imageReplacer = Object.create(imageReplacer);
options.element.imageReplacer.makeReplacer(options);
},
makeReplacer : function(options) {
options.element.className = 'imageReplacer';
var markup = this.createMarkup();
this.changeImage(options.initSrc, options.initAlt);
this.addClick(this.button);
options.element.appendChild(markup);
},
createMarkup : function() {
var frag = document.createDocumentFragment();
this.srcInput = document.createElement('input');
this.srcInput.type = 'text';
this.srcInput.placeholder = 'Image Source';
this.altInput = document.createElement('input');
this.altInput.type = 'text';
this.altInput.placeholder = 'Image Alt';
this.button = document.createElement('button');
this.button.textContent = 'Change Image';
this.imgTag = document.createElement('img');
frag.appendChild(this.srcInput);
frag.appendChild(this.altInput);
frag.appendChild(this.button);
frag.appendChild(this.imgTag);
return frag;
},
addClick : function(button) {
var that = this;
button.addEventListener('click', function() {
that.changeImage(that.srcInput, that.altInput);
});
},
changeImage : function(src, alt) {
this.imgTag.src = src;
this.imgTag.alt = alt;
}
};
Instead of creating a function to dynamically change the picture(which did work), I decided to hide one picture on my index.html file. And then changed the src with $("#my_image").attr("src","img/fire.gif"); #my_image being the id of the image tag.