I have a div container with several images. I want the user to select an image (avatar) from the provided list. Then the avatar image will be uploaded and also accessible. Once the user selects the avatar, I want to save the location of the selected avatar to my database. What is the best way to select the image? Is there any easy way to do this?
HTML
<div class="image-container">
<img src="images/gorillaAvatars/brownGorilla.png" id="brownGorilla">
<img src="images/gorillaAvatars/gorilla.png" id="Gorilla">
<img src="images/gorillaAvatars/greenGorilla.png" id="greenGorilla">
<img src="images/gorillaAvatars/kidGorilla.png" id="kidGorilla">
<img src="images/gorillaAvatars/surpriseGorilla.png" id="surpriseGorilla">
</div>
CSS
<style>
.image-container{
width:60%;
border: solid magenta 1px;
padding: 5px;
margin: 30px;
display: flex;
justify-content: space-evenly;
}
img{
width:80px;
}
img:hover,
img:focus,
img:active{
background-color: blue;
border-radius: 20px;
}
<style>
Javascript
const brownGorillaAvatar = "https://brownGorilla.png";
const mainGorillaAvatar ="https://gorilla.png"
const greenGorillaAvatar ="https://greenGorilla.png"
const kidGorillaAvatar ="https://kidGorilla.png"
const surpriseGorillaAvatar ="https://surpriseGorilla.png"
const avatar = [brownGorillaAvatar,mainGorillaAvatar,greenGorillaAvatar,kidGorillaAvatar, surpriseGorillaAvatar]
brownG.addEventListener('click', avatarSelect);
bigG.addEventListener('click', avatarSelect1);
greenG.addEventListener('click', avatarSelect2);
kidG.addEventListener('click', avatarSelect3);
surpG.addEventListener('click', avatarSelect4);
function avatarSelect (){
console.log(avatar[0])
}
function avatarSelect1 (){
console.log(avatar[1])
}
function avatarSelect2 (){
console.log(avatar[2])
}
function avatarSelect3 (){
console.log(avatar[3])
}
function avatarSelect4 (){
console.log(avatar[4])
}
Rather than attaching an event to each image object, it would be better to attach an event to the container surrounding it.
You can avoid overlapping codes and respond flexibly even if image objects increase.
for example
const imageContainer = document.getElementById("image-container");
imageContainer.onclick = function(e) {
console.log(e.target.id); // you can get img tag's id
}
Have a look at how Event Bubbling and delegation work in javascript to get a better understanding but you want to add the event to the parent container not to each element. So by adding new elements to your array they will be clickable.
const avatars = [
'brownGorillaAvatar',
'mainGorillaAvatar',
'greenGorillaAvatar',
'kidGorillaAvatar',
'surpriseGorillaAvatar'
]
const avatarContainer = document.querySelector('#avatarContainer');
avatars.forEach((avatar) => {
const span = document.createElement('span');
span.innerHTML = avatar;
avatarContainer.appendChild(span);
})
avatarContainer.addEventListener('click', (evt) => {
console.log(evt.target);
})
<html>
<head></head>
<body>
<section id="avatarContainer">
</section>
</body>
</html>
Related
I'm trying to make a window that slide up when the X button(close.png) is clicked.
I added the Wrap element with JavaScript, and added an img element inside.
Then, I put following JavaScript, but there is no change when I press the X button.
<script>
const parent3 = document.querySelector('#wrap');
const billingField3 = document.querySelector('#woocommerce-input-wrapper');
const newImg = document.createElement('img');
newImg.setAttribute("src", "//t1.daumcdn.net/postcode/resource/images/close.png");
newImg.setAttribute('id', 'btnFoldWrap');
newImg.style.cssText = 'cursor:pointer;position:absolute;right:0px;top:-1px;z-index:1';
newImg.onclick = "offDaumZipAddress();"
parent3.insertBefore(newImg, billingField3);
</script>
function offDaumZipAddress() {
jQuery("#wrap").slideUp();
}
Website structure is
<div class="woocommerce-billing-fields__field-wrapper">
<p class="billing_postcode_find_field">..
<span class="woocommerce-input-wrapper">...
</span>
</p>
<div id="wrap" ..>
<img src="..."></img>
</div>
<p class="billing_address_1_field">
<span class="woocommerce-input-wrapper">
Checking with the console of chrome developer tools doesn't show any errors.
Could someone please let me know what am I missing?
Thank you.
The value of the onclick property must be a function reference, not a JavaScript string.
newImg.onclick = offDaumZipAddress;
You have your answer; here is a working example of that loosely based on your code (so the inserted image actually shows, added some CSS etc. to illustrate)
//gets first one of this type
const billingField3 = document.querySelector('.woocommerce-input-wrapper');
// Get a reference to the parent node/ gets first one of this type
const parent3 = billingField3.parentNode;
//console.log(parent3);
//console.log(billingField3);
// Create the new node to insert
const newImg = document.createElement('img');
newImg.setAttribute("src", "//t1.daumcdn.net/postcode/resource/images/close.png");
newImg.setAttribute('id', 'btnFoldWrap');
newImg.setAttribute('alt', 'folderWrap');
// no not this: newImg.style.cssText = 'cursor:pointer;position:absolute;right:0px;top:-1px;z-index:1';
// this:
newImg.classList.add("inserted-image");
newImg.onclick = offDaumZipAddress;
//console.log("Thing:",newImg);
//console.log("HTML:", parent3.innerHTML);
parent3.insertBefore(newImg, billingField3);
//console.log("New HTML:", parent3.innerHTML);
function offDaumZipAddress() {
console.log('here we go');
jQuery("#wrap").slideUp();
}
.billing_postcode_find_field {
border: solid blue 1px;
padding: 1rem;
}
.woocommerce-input-wrapper {
border: solid 1px lime;
padding: 1rem;
}
.inserted-image {
cursor: pointer;
/* This is odd, makes it not clickable:
position: absolute;
right: 0px;
top: -1px;
z-index: 1;*/
border: solid 1px red;
min-width: 1.5rem;
min-height: 1.5rem;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="woocommerce-billing-fields__field-wrapper">
<p class="billing_postcode_find_field">..
<span class="woocommerce-input-wrapper">...</span>
</p>
<div id="wrap">
<img src="//t1.daumcdn.net/postcode/resource/images/close.png" alt="png"></img>
</div>
<p class="billing_address_1_field">
<span class="woocommerce-input-wrapper"></span>
</div>
When i drag an element onto another element of the same parentNode i want the two elements two swap position.
I keep track of the targets with two addEventListeners and i already tried to swap the important things like the classes and the textContent with storing that data in temporary helper variables but this procedure only worked for the first element to be copied into another but without making the first element like how the second element was.
<style>
.objects > div {
margin: 100px;
width: 100px;
height: 100px;
}
.one { background-color: lightblue;}
.two { background-color: lightcoral;}
.three { background-color: lightgoldenrodyellow;}
</style>
<body>
<div class="objects">
<div draggable='true' class='one' id='o1'>A</div>
<div draggable='true' class='two' id='o2'>B</div>
<div draggable='true' class='three' id='o2'>C</div>
</div>
</body>
var objects = document.querySelector('.objects');
objects.addEventListener('dragstart', function(e) {
objects.addEventListener('dragover', function(e2) { e2.preventDefault() });
objects.addEventListener('drop', function dandd(e2) {
//how can i swap both
var tempText = e.target.textContent;
var tempClass = e.target.classList;
e.target.textContent = e2.target.textContent;
e.target.classList = e2.target.classList;
e2.target.textContent = tempText;
e2.target.classList = tempClass;
objects.removeEventListener('drop', dandd);
});
});
I added an image to the Trix editor, generating the following code:
<figure
data-trix-attachment="{lots of data}"
data-trix-content-type="image/jpeg"
data-trix-attributes="{'presentation':'gallery'}"
class="attachment attachment--preview attachment--jpg">
<img src="http://myhost/myimage.jpg" width="5731" height="3821">
<figcaption class="attachment__caption">
<span class="attachment__name">cool.jpg</span> <span class="attachment__size">4.1 MB</span>
</figcaption>
</figure>
When I display the generated HTML from the editor on my Bootstrap-based page, the image obviously extends the screen (see the width and height) and I'd like to remove these props and also assign the img-fluid class to it.
So basically I thought to use the config:
Trix.config.css.attachment = 'img-fluid'
But that does a) not change the attachment class to img-fluid and it also would not apply the changes to the image but the figure.
I would like to avoid using jQuery each time I display the content and traverse all figures and then manipulate the image's properties at runtime.
Isn't there a solution to define these styles when adding the attachment?
Trix does not have any kind of support to change the image element inside the attachment. One way to do it is by using MutationObserver to check for mutations inside Trix editor that apply to attributes, childList and subtree.
If we have a width or height attributes mutation to an img target node with a figure parent node, then we remove those attributes and we can apply the class img-fluid to the first attribute mutation, for example width.
Run code snippet and try to add some image attachments to see or inspect the HTML
Please read inline comments
// Listen to trix-attachment-add event so we'll get rid of the progress bar just for this demo
// Here we should upload the attachment and handle progress properly
document.addEventListener("trix-attachment-add", event => {
const { attachment } = event.attachment;
// Get rid of the progress bar
attachment.setUploadProgress(100)
});
// Get the Trix editor
const editor = document.querySelector('trix-editor');
// Instantiating an observer
const observer = new MutationObserver(function (mutations) {
mutations.forEach(({ type, target, attributeName }) => {
// If the parent is a figure with an img target
if (target.parentNode.tagName === 'FIGURE' &&
target.nodeName === 'IMG')
{
if (type === 'attributes') {
switch(attributeName) {
// If we have attribute width
case 'width':
// Remove attribute width
target.removeAttribute('width');
// Add img-fluid only once
target.classList.add('img-fluid');
break;
// If we have attribute height
case 'height':
// Remove attribute height
target.removeAttribute('height');
break;
}
}
// Render images HTML code
renderHtmlOutput();
}
});
});
// Observing Trix Editor
observer.observe(editor, {
attributes: true,
childList: true,
subtree: true
});
// Function to render every figure > img HTML code
function renderHtmlOutput() {
const images = editor.querySelectorAll('figure > img');
let output = '';
for(const image of images) {
output += image.outerHTML.replace(/ /g, "\n ") + "\n";
}
document.getElementById('output-html').textContent = output;
}
body {
height: 100vh;
margin: 0;
flex-direction: column;
display: flex;
}
#main {
display: flex;
flex-direction: row;
flex: 1;
margin: 10px;
}
#editor-container {
flex: 3;
}
#output-container {
flex: 2;
margin-left: 20px;
border-left: 1px solid lightgray;
overflow: auto;
}
#output-html {
margin: 0;
padding: 10px;
font-size: small;
color: blue;
}
/* Hide some Trix buttons to free horizontal space */
.trix-button--icon-increase-nesting-level,
.trix-button--icon-decrease-nesting-level,
.trix-button--icon-bullet-list,
.trix-button--icon-number-list { display: none; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/trix/1.2.1/trix.js" integrity="sha256-2D+ZJyeHHlEMmtuQTVtXt1gl0zRLKr51OCxyFfmFIBM=" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/trix/1.2.1/trix.css" integrity="sha256-yebzx8LjuetQ3l4hhQ5eNaOxVLgqaY1y8JcrXuJrAOg=" crossorigin="anonymous"/>
<section id="main">
<div id="editor-container">
<form>
<input id="editor" value="Editor content goes here" type="hidden" name="content">
<trix-editor input="editor"></trix-editor>
</form>
</div>
<div id="output-container">
<pre id="output-html"></pre>
</div>
</section>
I don't believe this has been asked before. If it has I apologise as I couldn't find it.
I have an HTML table with pictures as buttons:
<td>
<button class="trigger">
<img src="D:\Elly Research\ CO2858\Presentation\Calypso_map.jpg">
</button>
</td>
<div class="modal">
<div class="modal-content">
<span class="close-button">× </span>
<img src="D:\Elly Research\CO2858\Presentation\Calypso_map.jpg">
<script src="D:\Elly Research\CO2858\Presentation\modal.js"></script>
</div>
</div>
This is controlled by a script:
var modal = document.querySelector(".modal");
var trigger = document.querySelector (".trigger");
var closeButton = document.querySelector(".close-button");
function toggleModal() {
modal.classList.toggle("show-modal");
}
function windowOnClick(event) {
if(event.target === modal){
toggleModal();
}
}
trigger.addEventListener("click", toggleModal);
closeButton.addEventListener("click", toggleModal);
window.addEventListener("click", windowOnClick);
If I copy the format of the first picture and use it for a second picture in the same table and same page, it stops working.
Does JavaScript not work like CSS where I can use multiple ID's to be controlled by one CSS value?
This is the first time I've used JavaScript with HTML and CSS.
When you do document.querySelector(".modal") you are selecting the first node that has the class "modal". Which in your case would be the div containing the first picture. And later you add the 'click' event to only the first picture.
You can use querySelectorAll, which returns a list of all the matching nodes and loop through all nodes to add the 'click' event listener like so:
const modals = document.querySelector(".modal");
modals.forEach(modal => {
modal.addEventListener('click', toggleModal)
});
I am not sure what exactly you are trying to ask. Based on my assumptions here is a small snippet. Hope it helps you.
var modal = document.getElementById("modal")
window.addEventListener("click", windowOnClick);
document.querySelector(".close-button").addEventListener("click", toggleModal)
function showImage(event){
toggleModal()
modal.getElementsByTagName("img")[0].src =event.srcElement.src
}
function windowOnClick(event){
if(event.srcElement === modal){
toggleModal()
}
}
function toggleModal(){
modal.classList.toggle("show-modal")
}
td > img{
width: 100px;
height: auto;
}
.modal{
display: none;
position: fixed;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.8);
z-index=10;
}
.show-modal{
display: block !important;
}
.modal-content{
width: 60%;
height: auto;
margin: 0 auto;
}
.close-button{
color: white;
cursor: pointer;
}
#viewer{
width:100%;
height: auto;
}
<!doctype>
<html>
<head>
</head>
<body>
<table>
<tr>
<td>
<img src="https://i.imgur.com/GV6086A.jpg" onclick="showImage(event)" />
</td>
<td>
<img src="https://i.imgur.com/opERcp1.jpg" onclick="showImage(event)" />
</td>
</tr>
<tr>
<td>
<img src="https://i.imgur.com/lieUEvQ.jpg" onclick="showImage(event)" />
</td>
<td>
<img src="https://i.imgur.com/B63gaEQ.jpg" onclick="showImage(event)" />
</td>
</tr>
</table>
<div class="modal" id="modal">
<div class="modal-content">
<span class="close-button">× </span>
<img id="viewer">
</div>
</div>
</body>
</html>
If it is a small application, a simple solution to this could be the creation of an object of images, containing its details, like this:
//Here you can add as many properties you want for the objects
images = [{
src: "D:\Elly Research\CO2858\Presentation\Calypso_map.jpg"
},
{
src: "D:\Elly Research\CO2858\Presentation\Calypso_map_alternative.jpg"
}]
Then you could iterate over it to generate your table, or simply create your table with some ID refs, like <button id="0" class="trigger">, therefore you can access them in the event object array index with this code:
var id = event.target.id
So, to generate the img element inside the modal, you'll have something like this:
function toggleModal(event){
var id = event.target.id;
var div = document.getElementsByClassName('modal-content')[0];
div.innerHTML += '<img class="modal-image" src="'+images[id].src+'" />';
modal.classList.toggle("show-modal");
}
But make sure you destroy the img element when it already have one:
var child = div.querySelector("img");
if(child != null){
div.removeChild(child);
}
Hope it helps you!! Good luck with your study!
You can use js multiple times. Check the src of your images.
It's discussed already here -src absolute path problem.
Here is the important part of the code that executes.
Im trying to click on one element with a particular ID that relates to bookmarking the message but the element keeps triggering another click event that hides every div with the class 'messageCase' while at the same time attaching class messageOpen2 to the bookmark images ID which is very odd
the 'hidden' classes just hide all other message instances that contain
The messageCase class.
var openMessageAnimationStrategy = function () {
var openMessage = $(document).ready(function () {
var divTarget = $("div.messageCase");
$(divTarget).click(function (e) {
var target = $(e.target);
target.toggleClass('messageOpen2');
divTarget.addClass('hidden');
target.removeClass('hidden');
});
});
};
Here is what the HTML looks like
<div class="messageCase">
<div class="messageImageBox">
<div id="messageImage">
</div>
</div>
<div id="subjectLine">
Subject Line Text
</div>
<div id="bookMarkImage">
<img id="bookmarkStatus" class="savedMessage" src="notbookMarked64.png" />
</div>
<div class="activeBookmarks">
{38} <br />
Bookmarks <br />
<br />
9:53am
</div>
<div id="bodyPreview">
Body Preview Text is light
</div>
</div>
Every Time I use the Click event on bookmarkStatus to change the src of the image it causes the first click event to execute making everything disappear & the class messageOpen2 to be added to bookmarkStatus. I can include the CSS if necessary but ill list the code for the bookmarking function below
var bookmarkedStrategy = function () {
var bookmarkedStrategy = $(document).ready(function () {
var bookmarkStatus = $("#bookmarkStatus");
var divTarget = $('messageCase');
//below trying to remove the Class that was attached by the initial function while also changing the image SRC for the class bookmark
$(divTarget).click(function (e) {
var target = $(e.target);
divTarget.removeClass('messageCase2');
bookmarkStatus.toggleClass('savedMessage');
});
});
};
I Think the main problem has to do with the initial function but I don't know what else could be wrong any ideas?
edit Here is the CSS that matters.
.savedMessage {
background-image: url("bookmarked64.png");
}
.messageOpen2 {
height: 250px;
}
.messageCase {
margin: 5px;
border-radius: 5px;
background-color: aliceblue;
height: 70px;
}
#bookMarkImage {
float:right;
height:64px;
width:64px;
z-index:9999;
}
.hidden {
display:none;
max-height: inherit;
}
.activeBookmarks {
float: right;
text-align: center;
font-size: 13px;
font-weight: 700;
text-decoration: solid;
}
Calling code
var bookmarkedthings = new MessageHandling(bookmarkedStrategy);
bookmarkedthings.greet();
var openMessage = new MessageHandling(openMessageAnimationStrategy);
openMessage.greet();
There is a missing . in your bookmarkedStrategy function code var divTarget = $('.messageCase'); Add dot and try again