JavaScript can't add contenteditable attribute - javascript

JavaScript:
var insertImage = function(src, alt) {
var html = '<div contenteditable="false"><img ' + 'src="'+src+'" alt="'+alt+'" onclick="imageClick()" /></div>';
document.execCommand('insertHTML', false, html);
};
HTML:
<body>
<div id="yq_editor_content" style=" width: 100%; height: 100%; -webkit-overflow-scrolling: touch; overflow: hidden; background-color:lightblue;" contenteditable="true">
</div>
<div id="yq_editor_footer"></div>
</body>
But after I perform the JavaScript function, I get the HTML that div has no contenteditable, as below:

I guess you want something like this?
https://jsfiddle.net/_jserodio/ywe48rwy/
JavaScript, CSS and HTML
var insertImage = function(src, alt) {
var img = '<img ' + 'src="'+src+'" alt="'+alt+'"/>';
document.querySelector('#yq_editor_content').innerHTML += img;
};
document.querySelector('#insert').addEventListener("click", function() {
insertImage('http://cdn.sstatic.net/Sites/stackoverflow/img/favicon.ico', 'so');
}, false);
#insert {
width: 25px;
heigth: 25px;
cursor: pointer;
}
<div id="yq_editor_content" style=" width: 100%; height: 100%; -webkit-overflow-scrolling: touch; overflow: hidden; background-color:lightblue;" contenteditable="true">
Hello, try to edit this!
</div>
<div id="yq_editor_footer">
<img id ='insert' src="http://icons.iconarchive.com/icons/oxygen-icons.org/oxygen/256/Actions-insert-image-icon.png" alt="insert image icon">
</div>

Related

appendTo adds element to another one, but it does not show on the website

I am trying to add arrows to my simple lightbox. The arrows are simple symbols "<" and ">. I have created them with jquery and when I try to add them to the image, they show up in the developer tools but not in the website for whatever reason. Can you tell me what's the problem please?
Here is the screenshot of the issue, if you did not understand my poor english. As you can see, the arrows are created in developer tools, but they cannot be found on the website. https://prnt.sc/26lyfbc
//Gallery Lightbox made with Jquery
let gallery = $('#gallery'),
overlay = $('<div = id = "overlay"></div>').appendTo('body').hide();
//Opens the lightbox with chosen image
gallery.find('a').on("click", function(event){
event.preventDefault();
let href = $(this).attr('href'),
image = $('<img>', {src: href}),
larrow = $('<div = id = "larrow"> < </div>'); //LEFT ARROW
rarrow = $('<div = id = "rarrow"> > </div>'); //RIGHT ARROW
image.appendTo(overlay);
larrow.appendTo(image);
overlay.show();
//Closes the Lightbox with the image, by clicking on the overlay
$(document).on("click", "#overlay", function(){
overlay.hide();
image.remove();
})
})
.gallery {
display: none;
opacity: 0;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
width: 1004px;
margin: 0 auto;
}
.gallery img {
position: relative;
top: 100px;
height: 200px;
width: 300px;
margin: 0 1em;
}
#overlay {
background: rgba(0, 0, 0, .7);
position: fixed;
height: 100%;
width: 100%;
top: 0;
left: 0;
text-align: center;
z-index: 10;
}
#overlay img {
margin-top: 5%;
border: solid 5px white;
border-radius: 5px;
}
//Dont mind these, the silly values are just for testing purposes
#larrow {
font-size: 500px;
color: red;
z-index: 2000;
}
#rarrow {
font-size: 500px;
color: red;
z-index: 2000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="gallery" id="gallery">
<img src="img\placeholder1.jpg" alt="">
<img src="img\placeholder2.jpg" alt="">
<img src="img\placeholder3.jpg" alt="">
<img src="img\placeholder4.jpg" alt="">
<img src="img\placeholder5.jpg" alt="">
<img src="img\placeholder6.jpg" alt="">
</div>
</body>
You have a few errors in your code. Instead of
larrow = $('<div = id = "larrow"> < </div>'); //LEFT ARROW
rarrow = $('<div = id = "rarrow"> > </div>'); //RIGHT ARROW
You should write it like this. There is no need for the '=' between div and id.
larrow = $('<div id = "larrow"> < </div>'); //LEFT ARROW
rarrow = $('<div id = "rarrow"> > </div>'); //RIGHT ARROW
The same goes for the following tags:
overlay = $('<div id = "overlay"></div>').appendTo('body').hide();
Putting the div tags in the image will also not work. Instead you should put the image and the arrows in a container together like this:
<div id="overlay">
<img src ... </img>
<div id = "larrow"> < </div>
<div id = "rarrow"> > </div>
</div>
Refer to Floating Div Over An Image to see the needed css.

How can I change img src from list of (non-image) items?

What I'm trying to do feels like it should be very simple, but I haven't found the right thing.
Say I have something like this:
.list {
float: left;
width: 200px;
height: 500px;
overflow-y: auto;
}
.show {
float: right;
width: 500px;
height: 500px;
}
.display {
max-width: 500px;
max-height: 500px;
width: auto;
height: auto;
}
<div class="container" style="width: 700px;">
<div class="list">
<li>img1.jpg</li>
<li>img2.jpg</li>
<li>img3.gif</li>
<li>img4.png</li>
</div>
<div class="show">
<img src="img1.jpg" class="display" id="display">
</div>
</div>
When clicking on the list item on the left, I want the img src on the right to change to the displayed text in the list item (or some equivalent). Bonus points if there are previous and next arrows on the image on the right to continue scrolling through the available images.
Sort of like a lightbox gallery, but instead of using thumbnails, it's clicking on text or a link that creates the full size element, and instead of popping up a lightbox it just changes the existing image on the page.
Ideally I'd like to use vanilla JavaScript, but using jQuery or something isn't out of the question.
You can add JavaScript code on each li element, and sending in the li element itself with "this" in updateImage(this). I'm using a site with placeholder images, so it will look a little bit different.
function updateImage(liElement) {
const imgElement = document.querySelector('.show > img');
// Your code should be something like: "https://www.yourdomain.com/images/" + liElement.textContent
const imageSrc = `https://picsum.photos/id/${liElement.textContent}/200/200`;
imgElement.src = imageSrc;
}
.container {
display: flex;
}
.list {
width: 200px;
cursor: pointer;
padding: 0.25rem;
}
.display {
max-width: 500px;
max-height: 500px;
}
<div class="container">
<div class="list">
<li onclick="updateImage(this)">237</li>
<li onclick="updateImage(this)">240</li>
<li onclick="updateImage(this)">100</li>
<li onclick="updateImage(this)">301</li>
</div>
<div class="show">
<img src="https://picsum.photos/id/237/200/200" class="display" id="display">
</div>
</div>
You can also add a single click listener on your ul tag, and use event.target to get which li that is clicked upon.
It's a more dynamic approach, because you don't need to add onclick="updateImage(this)" on every single li tag, and it creates cleaner HTML code.
const listElement = document.querySelector('.list');
listElement.addEventListener('click', updateImage);
function updateImage(event) {
const imgElement = document.querySelector('.show > img');
const liElement = event.target;
// Your code should be something like: "https://www.yourdomain.com/images/" + liElement.textContent
const imageSrc = `https://picsum.photos/id/${liElement.textContent}/200/200`;
imgElement.src = imageSrc;
}
.container {
display: flex;
}
.list {
width: 200px;
cursor: pointer;
padding: 0.25rem;
}
list > li * {
/* so only the li tag can be event.target, and none of it's children */
pointer-events: none;
}
.display {
max-width: 500px;
max-height: 500px;
}
<div class="container">
<div class="list">
<li>237</li>
<li>240</li>
<li>100</li>
<li>301</li>
</div>
<div class="show">
<img src="https://picsum.photos/id/237/200/200" class="display" id="display">
</div>
</div>
Here's a starting point, roughing out the basic idea in vanilla JS:
const list = document.querySelector('.list');
const img = document.querySelector('#display');
const onclick = e => {
if (e.target.nodeName !== 'LI') return;
img.src = e.target.textContent;
};
list.addEventListener('click', onclick);
And a working example (I'm also setting the alt text, since the image srces are all broken links)
const list = document.querySelector('.list');
const img = document.querySelector('#display');
const onclick = e=> {
if(e.target.nodeName!=='LI') return;
img.src = e.target.textContent;
img.alt = e.target.textContent;
};
list.addEventListener('click', onclick)
.list {
float: left;
width: 200px;
height: 500px;
overflow-y: auto;
}
.show {
float: right;
width: 500px;
height: 500px;
}
.display {
max-width: 500px;
max-height: 500px;
width: auto;
height: auto;
}
<div class="container" style="width: 700px;">
<div class="list">
<li>img1.jpg</li>
<li>img2.jpg</li>
<li>img3.gif</li>
<li>img4.png</li>
</div>
<div class="show">
<img src="img1.jpg" class="display" id="display">
</div>
</div>

Javascript: How to change the images inside of a div on scroll?

so I am trying to create the effect seen on this website (for the photos on the left side of the column):
https://www.franshalsmuseum.nl/en/
I want to be able to change the image on scroll inside of a div.
And preferably, it won't scroll down past the page until all of the images have been scrolled through!
I'm trying to get the hang of javascript before adding things like jQuery, so can someone help with this using pureJS?`
window.onscroll = function() {
console.log(window.pageYOffset);
var img1 = document.getElementById('img1');
var img2 = document.getElemebtById('img2')
if ( window.pageYOffset > 1000 ) {
img1.classList.add("hidden");
img2.classList.remove("hidden");
} else {
img2.classList.add("hidden");
img1.classList.remove("hidden");
}
}
.rightPhotos {
max-width: 50%;
height: 50%;
overflow: auto;
}
.aPhoto {
max-height: 100%;
}
.hidden {
visibility: hidden;
}
.images {
width: 100%;
height: 100%;
}
<div class="other">
<div class="rightPhotos" onscroll="myFunction()">
<div class="aPhoto">
<img class ="images" id="img1" src="IMAGES/sunglasses.jpeg" alt="Woman with Sunglasses">
</div>
<div class="aPhoto hidden">
<img class="images" src="IMAGES/dancer1.jpg" alt="A Dancer">
</div>
</div>
</div>
`
The page you linked actually looks very nice, so I took a while to make something looking a bit closer to it than what other answers do.
I added a properly working transition, similar to one on franshalsmuseum.nl.
I styled the page to deal relatively well with being resized:
The sizing of panes and images is all ralative,
Scroll steps are relative to page height,
Images are shown using <div> with background-image instead of <img> tag. Depending on the size of the window, they are slightly cropped to adjust to changing aspect ratio of viewport.
I made the number of image sets very simple to change. It could be improved by creating the html elements in Javascript, but that doesn't look necessary. At least, it wouldn't be for the original page.
How it works
HTML
Images are put into special envelop elements (.img-wrapper), that provide proper sizing and positioning position: relative is important there). Each image element gets url (as background image url) and image set number to be used by javascript:
<div class="img visible" data-imageset="1"
style="background-image: url('http://placeimg.com/640/480/people');">
</div>
Class visible is set to show imageset 1 at the beginning.
CSS
The key points are these definitions (and similar for #bottom-image). As the element enveloping the image has overflow: hidden, we can hide the image by moving it outside of visible area. When we set coordinates back to normal, the image will slide back, using the smooth transition.
/* hiding images in #top-image */
#left-pane #top-image .img {
top: 100%;
}
#left-pane #top-image .img.visible {
top: 0;
}
JS
The Javascript code is very minimal, the interaction with DOM is really one line. However, it uses some tricks that may not be obvious, so there is this line with some links to documentation:
document.querySelectorAll('#left-pane .img').forEach((img) => {
    img.classList.toggle('visible', img.dataset.imageset <= currentSet);
}
It just finds all images and adds or removes class visible depending on the data-imageset attribute of the image.
Full snippet with demo
See snippet below. Demo looks much better if you use "Full page" link after running the snippet.
let currentSet = 1;
function updateSelectedImgSet() {
const currentScroll = document.scrollingElement.scrollTop;
const scrollMax = document.scrollingElement.scrollHeight - document.scrollingElement.clientHeight;
const setsCount = 3;
const scrollPerSet = scrollMax / setsCount;
const scrolledSet = Math.floor(currentScroll / scrollPerSet) + 1;
if (scrolledSet == currentSet) {
return;
}
currentSet = scrolledSet;
document.querySelectorAll('#left-pane .img').forEach((img) => {
img.classList.toggle('visible', img.dataset.imageset <= currentSet);
});
}
window.onscroll = updateSelectedImgSet;
window.onresize = updateSelectedImgSet;
/* Left pane, fixed */
#left-pane {
position: fixed;
height: 100%;
width: 40vw;
}
#left-pane .img-wrapper {
position: relative;
height: 50%;
width: 100%;
overflow: hidden;
}
#left-pane .img-wrapper .img {
position: absolute;
width: 100%;
height: 100%;
/* Sizing and cropping of image */
background-position: center;
background-size: cover;
/* Transition - the slow sliding of images */
transition: 0.5s all ease-in-out;
}
/* hiding images in #top-image */
#left-pane #top-image .img {
top: 100%;
}
#left-pane #top-image .img.visible {
top: 0;
}
/* hiding images in #bottom-image */
#left-pane #bottom-image .img {
bottom: 100%;
}
#left-pane #bottom-image .img.visible {
bottom: 0;
}
/* Right pane, scrolling with the page */
#right-pane {
margin-left: 40vw;
}
.scrollable-content {
font-size: 40vw;
writing-mode: vertical-rl;
white-space: nowrap;
}
<div id="left-pane">
<div id="top-image" class="img-wrapper">
<div class="img visible" data-imageset="1"
style="background-image: url('http://placeimg.com/640/480/people');">
</div>
<div class="img" data-imageset="2"
style="background-image: url('http://placeimg.com/640/480/animals');">
</div>
<div class="img" data-imageset="3"
style="background-image: url('http://placeimg.com/640/480/any');">
</div>
</div>
<div id="bottom-image" class="img-wrapper">
<div class="img visible" data-imageset="1"
style="background-image: url('http://placeimg.com/640/480/nature');">
</div>
<div class="img" data-imageset="2"
style="background-image: url('http://placeimg.com/640/480/tech');">
</div>
<div class="img" data-imageset="3"
style="background-image: url('http://placeimg.com/640/480/arch');">
</div>
</div>
</div>
<div id="right-pane">
<div class="scrollable-content">Scrollable content!</div>
</div>
see code bellow:(I set 60 insteed 1000 (in function)for see changes)
I use one image and onscroll change the src of image
window.onscroll = function() {
var img1 = document.getElementById('img1');
var img2 = document.getElementById('img2')
if ( window.pageYOffset > 60 ) {
document.getElementById("img1").src = "https://material.angular.io/assets/img/examples/shiba2.jpg";
} else {
document.getElementById("img1").src = "https://material.angular.io/assets/img/examples/shiba1.jpg";
}
}
.rightPhotos
{
max-width: 50%;
height:50%;
overflow: auto;
}
.aPhoto
{
max-height: 100%;
}
.images
{
width: 100%;
height: 500px;
}
<div class="other">
<div class="rightPhotos" onscroll="myFunction()">
<div class="aPhoto">
<img class ="images" id="img1" src="https://material.angular.io/assets/img/examples/shiba1.jpg" alt="Woman with Sunglasses"/>
</div>
</div>
</div>
You can use the CSS properties to show/ hide the elements; instead of having custom CSS with hidden class.
if ( window.pageYOffset > 1000 ) {
img1.style.visibility = 'hidden';
img2.style.visibility = 'visible';
} else {
img2.style.visibility = 'hidden';
img1.style.visibility = 'visible';
}
The above would hide the element, but the DOM element would still occupy space.
For it now to have space occupied (like to remove it)
if ( window.pageYOffset > 1000 ) {
img1.style.display = 'none';
img2.style.display = 'block';
} else {
img1.style.display = 'block';
img2.style.display = 'none';
}
//window.pageYOffset
var scrollingDiv = document.getElementById('scrollContainer');
var img1 = document.getElementById('img1');
var img2 = document.getElementById('img2');
scrollingDiv.onscroll = function(event) {
if (scrollingDiv.scrollTop < 500) {
img1.src = "https://placeimg.com/250/100/arch";
img2.src = "https://placeimg.com/250/100/animals";
}
if (scrollingDiv.scrollTop > 500) {
img1.src = "https://placeimg.com/250/100/nature";
img2.src = "https://placeimg.com/250/100/people";
}
if (scrollingDiv.scrollTop > 1000) {
img1.src = "https://placeimg.com/250/100/tech";
img2.src = "https://placeimg.com/250/100/any";
}
}
.container{
display: table;
width: 100%;
height: 100%;
}
body{
margin: 0;
}
.container > div {
vertical-align:top;
}
.left, .middle, .right {
display: table-cell;
height: 100vh;
box-sizing: border-box;
}
.left, .right{
width:40%;
background: gray;
}
.middle{
overflow: auto;
position: relative;
}
.in-middle{
background: tomato;
position: absolute;
width: 100%;
height: 100%;
box-sizing: border-box;
margin: 0;
}
.in-in-middle{
height: 500px;
background: tomato;
}
.in-in-middle:nth-child(2){
background: pink;
}
.in-in-middle:nth-child(3){
background: skyblue;
}
.left img{
width: 100%;
transition: all 0.5s;
}
<div class="container">
<div class="left">
<img id="img1" src="https://placeimg.com/250/100/arch">
<img id="img2" src="https://placeimg.com/250/100/animals">
</div>
<div class="middle" id="scrollContainer">
<div class="in-middle">
<div class="in-in-middle" id="1"></div>
<div class="in-in-middle" id="2"></div>
<div class="in-in-middle" id="3"></div>
</div>
</div>
</div>

Remove the parent node in javascript starting from a string

I need to parse a string. The string is a callback from an adserver, and this is the format
<div style="background-color: yellow">
<div>
<div style="left: 10px; width: 100%; height: 0px; position: relative; padding-bottom: 80%;"><iframe allowfullscreen="" frameborder="0" src="https://www.youtube.com/embed/5DkrwfY2jw4" style="top: 0px; left: 0px; width: 100%; height: 100%; position: absolute;"></iframe></div>
</div>
</div>
I need to remove the parent div only if he style has yellow as background color. Of course I cannot use jquery.
I try to transform the string in an HTML fragment using
var div = document.createElement('div');
div.innerHTML = a.response.html;
var elements = div.childNodes;
but I cannot find a way to check for the presence of the attribute and, if true, remove the parent node keeping the childs.
The div itself shouldn't be a problem, so you can just set the background to transparent if its original background color is yellow:
var s = `<div style="background-color: yellow">
<div>
<div style="left: 10px; width: 100%; height: 0px; position: relative; padding-bottom: 80%;"><iframe allowfullscreen="" frameborder="0" src="https://www.youtube.com/embed/5DkrwfY2jw4" style="top: 0px; left: 0px; width: 100%; height: 100%; position: absolute;"></iframe></div>
</div>
</div>`
var div = document.createElement('div');
div.innerHTML = s; // replace with response...
if (div.childNodes[0].style.backgroundColor == 'yellow') div.childNodes[0].style.backgroundColor = 'transparent'
document.body.appendChild(div);
Here's a fiddle
you can iterate over the childNodes and check if the div has a specific style.
function checkandAppend(nodes) {
for(node in nodes){
if (nodes.hasOwnProperty(node))
if(nodes[node].getAttribute("style") == 'background-color: yellow')
{
if(nodes[node].childNodes[0].nodeType == 3) // some browser interpret line break as first child
document.querySelector("body").appendChild(nodes[node].childNodes[1]);
else
document.querySelector("body").appendChild(nodes[node].childNodes[0]);
}
else
{
document.querySelector("body").appendChild(nodes[node]);
}
}
}
var div = document.createElement('div');
div.innerHTML = '<div style="background-color: yellow"> <div> <div style="left: 10px; width: 100%; height: 0px; position: relative; padding-bottom: 80%;"> <iframe allowfullscreen="" frameborder="0" src="https://www.youtube.com/embed/5DkrwfY2jw4" style="top: 0px; left: 0px; width: 100%; height: 100%; position: absolute;"></iframe> </div> </div> </div>'
checkandAppend(div.childNodes);
Since the style is set inline, you can simply read the style property of the div. Create a div, insert the HTML, then check the first div. I guess that you want to insert this in the document, so if the first div has been set to yellow, insert its first div child node (i.e. the second in the tree) in the document. Otherwise, insert the first div.
This method is not robust, but without further information on how to select the div, or what to do with it once selected, there's not much more you can do.
I've replaced the iFrame with some text, I don't think it's relevant to the answer.
var response = '<div style="background-color: yellow"><div><div style="left: 10px; width: 100%; height: 0px; position: relative; padding-bottom: 80%;">iframe</div></div></div>';
var div = document.createElement('div');
div.innerHTML = response;
var divs = div.getElementsByTagName('div');
if (divs[0].style.backgroundColor == 'yellow') {
document.body.appendChild(divs[1]);
} else {
document.body.appendChild(divs[0]);
}
You could replace the if..else with:
document.body.appendChild(divs[+(divs[0].style.backgroundColor == 'yellow')]);
but that might be a bit obfuscated.

How to change the percentage width of multiple images based on their order of appearance?

Let's say there are three 9* images on the page:
<img src="...">
<img src="...">
<img src="...">
<img src="...">
<img src="...">
<img src="...">
<img src="...">
<img src="...">
<img src="...">
*Just an example, there won't always be 9 images - could be 5 or 6, etc
How would I make it so that the percentage width of the images correspond to this order:
1st image: width: 100%;
2nd image: width: 70%;
3rd image: width: 30%;
Repeat
Similar to what has been done here:
Overall, for every image on the page, the width has to be:
100% for the first image,
70% for the second image,
30% for the third image,
Repeat in this order for every other image, e.g:
100% for the fourth image,
70% for the fifth image,
30% for the sixth image,
I believe scripts would need to be used though I am not sure how to do so
Basic Implementation:
<!DOCTYPE html>
<html>
<head>
<style>
img:nth-of-type(3n+0) { width: 100%; }
img:nth-of-type(3n+1) { width: 70%; }
img:nth-of-type(3n+2) { width: 30%; }
</style>
</head>
<body>
<div class="page">
<div class="i">
<img src="http://e794d552b4c822b8205c-27b9cc3fb8731a4a7598943b8a8a6a91.r73.cf1.rackcdn.com/1/1/large.jpg">
</div>
<div class="i">
<img src="http://e794d552b4c822b8205c-27b9cc3fb8731a4a7598943b8a8a6a91.r73.cf1.rackcdn.com/1/1/large.jpg">
</div>
<div class="i">
<img src="http://e794d552b4c822b8205c-27b9cc3fb8731a4a7598943b8a8a6a91.r73.cf1.rackcdn.com/1/1/large.jpg">
</div>
</div>
</body>
</html>
A few fancy CSS3 selectors should do the trick:
img:nth-of-type(3n+0) { width: 100%; }
img:nth-of-type(3n+1) { width: 70%; }
img:nth-of-type(3n+2) { width: 30%; }
See the documentation for nth-of-type on MDN.
Note that this will not work in IE8 or earlier, for which you may need to use a JavaScript solution.
This will set the width accordingly to all images in the page, so adjust the query in $("img") to match only the desired images.
var sizes = ["100%", "70%", "30%"];
$("img").each(function (idx, elem) {
elem.width = sizes[idx % sizes.length];
});
This would work in IE8, though is less maintainable and not very sexy. This assumes that your images are the only items inside of an element (eg. a DIV):
img:first-child { width: 100%; }
img:first-child + img { width: 70%; }
img:first-child + img + img { width: 30%; }
img:first-child + img + img + img { width: 100%; }
img:first-child + img + img + img + img { width: 70%; }
img:first-child + img + img + img + img + img { width: 30%; }
img:first-child + img + img + img + img + img + img { width: 100%; }
img:first-child + img + img + img + img + img + img + img { width: 70%; }
img:first-child + img + img + img + img + img + img + img + img { width: 30%; }

Categories

Resources