Essentially I'm adding some JS to a site that allows the same set of buttons to load images(colour options) based on the ONLY image found within an ID. WIP to illustrate:
http://www.twistfurniture.co/collections/product-test/
So what I've done thus far:
<div id="switchgallery">
<img src="/wp-content/uploads/Chair.jpg" id="switchimage">
</div>
<p>
<input id="Button1" type="button" value="Show black" onclick="ShowBlack()"/>
<input id="Button2" type="button" value="Show red" onclick="ShowRed()"/>
</p>
JS
function ShowBlack()
{document.getElementById("switchimage").src = "/wp-content/uploads/Chair_Black.jpg";}
function ShowRed()
{document.getElementById("switchimage").src = "/wp-content/uploads/Chair_Red.jpg";}
Now this works but if I have lots of colours and lots of products it'll take ages and require coding each time a new product is adding (productname=Chair in the above example).
What I'd like to accomplish is the following.
function ShowBlack()
{document.getElementById("switchimage").src = "***Dynamically generate the SRC of the image based on the ID of switchimage and and add _Black before the file extension =(/wp-content/uploads/Chair_Black.jpg)***";}
That way I can add lots of products and so long as they have the correct ID and the buttons are on the page I will get an easy method to switch their colour (assuming I have uploaded the appropriately named files in the right directory ;D)
Like I mentioned this is a work in progress and I will continue to fiddle until either I solve this myself or you guys flip over the ICT Hero card.
I've learned a lot by reading these forums, but now need direct assistance! Many thanks in advance
What you need is to setup a function with a parameter color :
function showImage(color) {
document.getElementById("switchimage").src = "/wp-content/uploads/Chair_"+color+".jpg";
}
this color can easily be a parameter of the button that you load with a function like that
function showImage() {
{
var color = jQuery(this).attr("color");
document.getElementById("switchimage").src = "/wp-content/uploads/Chair_"+color+".jpg";
}
with button definition like
<input id="Button1" type="button" value="Show black" onclick="showImage()" color="black"/>
Since your site is a Word Press site, I would recommend using one of the many plugins available, like this.
While I will be the first to want to use my own custom code, Word Press plugins are the best way to work within Word Press. While it may seem straight forward, there are a lot of things to consider. For example, how to determine what the product is and what images are available for said product. Javascript is a client side library and won't give you the best solution for something like a product catalog unless you have full control over the site.
You have a couple options:
Use data.
You can use the data attribute to store which color to load.
<button data-color="Red">Red</button>
jsfiddle: http://jsfiddle.net/PThwj/
Use arguments
<button onlick="loadImage('black');">Black</button>
jsfiddle: http://jsfiddle.net/gt6BS/1/
The load image function looks like this:
function loadImage(color) {
document.querySelector("#image").innerHTML =
"/wp-content/uploads/Chair_" + color;
// Change source of image here by using img.src
}
To bind events dynamically (if you use option 1) do this:
var buttons = document.querySelectorAll(".chair-button");
for (var i = 0; i < buttons.length; ++i) {
buttons[i].addEventListener("click", loadImageEvent);
}
Now you can add <button>s and specify a data-color and the rest will take care of itself.
This should work:
function ShowBlack()
{
source = document.getElementById("switchimage").src;
if (source.lastIndexOf("_") != -1){
source = source.substring(0,source.lastIndexOf("_"));
}else{
source = source.substring(0,source.lastIndexOf("."));
}
source += "_Black.jpg"
console.log(source);
document.getElementById("switchimage").src = source;
}
function ShowRed()
{
source = document.getElementById("switchimage").src;
if (source.lastIndexOf("_") != -1){
source = source.substring(0,source.lastIndexOf("_"));
}
else{
source = source.substring(0,source.lastIndexOf("."));
}
source += "_Red.jpg"
document.getElementById("switchimage").src = source;
}
Here is a fiddle : http://jsfiddle.net/TQhJk/1/
Related
I'm trying to hack together a video player to play local files in a cool interface, it's literally only ever going to be used by my family so the code doesn't have to be beautiful or anything. I've basically got a table full of DVD covers, and when clicked each one of them is supposed to open a modal with a video player for Chrome.
I've managed to do all of this, except I'm struggling to get it so the same button/image can be pressed and a different video file gets shown. Basically this is what I've got inside every table cell:
<th>
<div class="imageBox">
<div class="imageInn">
<img id="standardDVD" src="images/dvdCover1.jpg" alt="Snow">
<div class="hoverImg">
<img id="buttonPlay" src="images/play.png" alt="play">
</div>
</div>
</div>
</th>
I've then got the following JavaScript code to show the modal when that's clicked (I basically took it from here and modified it to show a video instead):
var playButton = document.getElementById('buttonPlay');
playButton.onclick = function(){
modal.style.display = "block";
document.getElementById("videoModal").src = videoToPlay;
}
var dvdCover = document.getElementById('standardDVD');
dvdCover.onclick = function(){
modal.style.display = "block";
document.getElementById("videoModal").src = videoToPlay;
}
(I've got two basically identical ones so it works if either the DVD cover or the button is clicked)
My thinking was to try and somehow get the src of the image (which should be doable if it's the image that's clicked, but I'm not too sure about how to get the dvd cover src if the button is the one getting clicked. From there I was thinking of having a simple (but long) JavaScript if function to convert each DVD cover to the src of the right video file, and simply change the videoToPlay variable used in the modal:
var videoToPlay = "movies/a Movie.mp4";
Edit since I don't think I was clear: I have a table with 55 different DVD covers, each in one cell and each with the identical HTML code except with a different dvdCover1.jpg image. What I'm trying to do is get it so each one plays the correct video, without having to make a new function for each.
I realize this is definitely not best practice, and any suggestions to improve the overall setup are appreciated - although I'm trying to get this together for Christmas and my knowledge of HTML and CSS is basically zero which is why I'm currently going for simplicity: only 5 people will ever see this anyway so best practice isn't necessarily important!
One option is to create an array with all your movies paths:
var videosToPlay = [
"movies/a Movie.mp4",
"movies/movie a.mp4",
"movies/a new Movie.mp4"
];
Then you need to get all handlers like this:
var dvdsCover = document.getElementsByClassName('standard-dvd-class-in-all-table');
Then just define the click event to all of them using the matching index. Your array must match the full table order of DVDs:
[...dvdsCover].forEach((dvdCover, index) => {
dvdCover.onclick = () => {
modal.style.display = "block";
document.getElementById("videoModal").src = videosToPlay[index];
};
});
Hope it helps.
I'm having an issue where my textarea value is returning an empty string. I have a modal which opens on a dblclick event where there's a textarea and a button. I want that when the button is clicked the text written in the textarea is fetched and stored in a variable to be used in other functions. By the way when I click on the button the returned text is "".
the textarea html is:
<textarea id="text-comment" placeholder="Insert a new comment" style="min-width:100%"></textarea>
the button html is:
<button class="btn btn-default" data-dismiss="modal" id="edit">Edit</button>`
the function code is:
$(document).on('click', '#edit', function(){ //edits the selected note
var classes = $(selectedNote).attr("class").toString().split(' ');
var id = classes[2];
var newText = $("#text-comment").val();
console.log("new text is: "+newText);
$(selectedNote).attr("title", newText);
for(var i = 0; i < temporaryNotes.length; i++) {
if(temporaryNotes[i]["ref"] == id) {
temporaryNotes[i]["text"] = newText;
}
}
for(var i = 0; i < notes.length; i++) {
if(notes[i]["ref"] == id) {
deleteNotes.push(notes[i]);
notes[i]["text"] = newText;
}
}
})
I'm going to go on a limb here. The limb might break but who knows?
I believe your modal's contents are defined within the HTML itself. Perhaps you have <div class="modal-content"> or something - I don't know what modal plugin you're using (but if I ever write one, it will use <script type="text/html"> specifically to prevent this issue...)
The problem with defining modals in this way is that the "template" contents are themselves part of the document, even if the "base" one is never shown. The modal plug-in can then call cloneNode on the template and render that as the modal. Simple, right?
Not quite. IDs must be unique on the page, so any modal plug-in that uses cloneNode to render will end up with duplicate IDs all over the place.
To find out if this is the case, try running this code when your modal is visible on-screen:
alert($("[id='text-comment']").length);
This will show how many elements have that ID (whereas #text-comment may just stop after the first one). This value should be exactly 1. If it is 2 (or worse, more!) then you do indeed have a badly implemented modal plugin.
Without knowing exactly which plugin you're using nor how it works, I would suggest finding some way to uniquely identify the displayed modal as opposed to the template, and don't use IDs inside the template.
You'll need to use your browser's Developer Tools to do this, but as an example if your modal appears with class="modal-display" then you could do something like this:
var button = $(this),
container = button.closest(".modal-display"),
textarea = container.find("textarea"),
value = textarea.val();
This kind of "relative search" for elements is much more flexible, and it will help you in future to learn this kind of thing. But for now, it should work around the issue of the duplicate IDs.
For some practice this week, I tried creating the front end of a blog page. I added a few "fake" Like buttons (they don't attach to facebook, just raise a counter that's placed next to them.)
Everything works, though I think there's a more direct and re-usable way to write the jQuery/JavaScript code I used to build those counters.
Here's the JavaScript code:
<script>
var whichButton = "";
var counter = 0; // Adds counters next to each
var counter2 = 0; // "Like" button, and raises
$("button").on("click", function(){ // their values separately.
whichButton = this.id;
if (whichButton === "button1") {
counter++;
$("#span1").html(counter);
} else {
counter2++
$("#span2").html(counter2);
}
});
</script>
...and here's the html it affects:
<button id="button1">Like</button>
<span id="span1"></span>
<button id="button2">Like</button>
<span id="span2"></span>
Is there a less hands-on way to write this code? Something that would allow me to
add new buttons alongside new spans, both with complementary ids, and, without updating my JavaScript code, have my site allow each button to function automatically?
I'm trying to write this in the most efficient way I can.
Thanks!
To make this a more reusable component, take advantage of classes instead of unique IDs.
$(".like_button button").on("click", function() {
var $count = $(this).parent().find('.count');
$count.html($count.html() * 1 + 1);
});
In your markup, create as many like_button instances as you want, and use the HTML to set the default value of 0.
<div class="like_button">
<button>Like</button>
<span class="count">0</span>
</div>
Note: $(this).parent().find('.count'); is a very literal traversing example. You could use $(this).next(); instead to find the button's next sibling, which would remove the need for the "count" class. Check out the jQuery Docs on Traversal for many other wonderful methods.
Here's a fiddle showing that in action: http://jsfiddle.net/bw5LU/
Sure, mark all the like buttons with a class or other attribute so we can select like:
$(".like-button").on("click", function(e){
var $counter = $(this).find(".count");
var count = $counter.text() | 0; //corose current count to an int
$counter.text(count + 1);//set new count
});
Now to create new like buttons add the following snippet anywhere in your html document:
<div class="like-button">
<button>Like</button>
<span class="count"></span>
</div>
Couldn't find a punctual answer for this simple task and your help is highly appreciated
We have an image we want to switch based on user's color selection.
Tried several methods, none worked.
This is the idea:
$('#YourButton').click(function() {
var oldSrc = 'images/Image1.png';
var newSrc = 'images/Image2.png';
$('img[src="' + oldSrc + '"]').attr('src', newSrc);
});
Just change the image source with javascript by clicking your button with another color
Note: it´s jquery so you have to include the js file..
Just bind a click listener to your button and change the src attribute of your image.
$('#colorButton').click( function() { //choose a new color
$('#imageIcon').attr('src', 'path/to/new/image.png'); //change the img's source
});
EDIT (response to questions):
If you want this code to apply to all of your buttons, give each of your buttons a similar class instead of an ID:
<div class="colorButton"></div>
Then you can use the following selector to apply the above click listener to all of these divs:
$('.colorButton')
Naturally, you want to change your image as simply as possible. You could map all of your colors to their corresponding image file, but as far as design goes this might get messy and unwieldy. I would create a directory that stores all of your image files (for example, /your/color/swatches) and give each of them a name consistent with their color, like 'ff0000.png' for red, '0000ff.png' for blue, etc.
Why would we do this? So that we can switch your image based on the background-color attribute of your buttons. Let's say that you have the following buttons:
<div class="colorButton" style="background-color: '#ff0000'"></div>
<div class="colorButton" style="background-color: '#0000ff'"></div>
You can use the same click listener, but it will have to be modified a bit since we are mapping the background color to an image:
$('.colorButton').click( function() {
var color = $(this).css('backgroundColor');
//(You'll need to modify your color string here)
$('#imageIcon').attr('src', 'your/color/swatches/' + color + '.png');
});
BUT this won't work yet. Since most browsers return "rgb(xx, yy, zz)" from .css('backgroundColor'), you need to convert that string into hex. This post on SO gives a more or less effective way to do so, but you'll need to modify it to fit your model where I have indicated.
Here's some low-hanging fruit for those more comfortable with Javascript than I...
I want to improve a Moodle plugin's admin UI. (Moodle is a PHP-based web app). What I need to do is take what is currently a text box, with semi-colon delimited entries and replace that with a editable list.
The HTML elements I would use is a select list, a text input field and another hidden textfield. I guess a couple of submit buttons too, one for adding, and the other for removing of entries.
The behaviour would be:
Entries can be added to the select list from the visible textbox upon some kind of submit (this cannot reload the page).
The hidden textbox would contain all the entries from the select list, just semi-colon delimited
There's a function to remove entries from the select list that also does not reload the page.
The hidden textbox is updated with add/remove actions
This seems to me like something that's easy enough. Though I'm having a hard time finding a close enough example to rip off.
This sample code is as close as I've found thus far. There's got to be some good examples of precisely this sort of thing out there. Any decent pointers will be rewarded with + votes.
What you want to do is use JavaScript and manipulate with the DOM of the webpage. Basically, the HTML of a webpage is parsed and rendered by the browser into a tree of elements. Each HTML tag like <select> is an element in the tree. You use JavaScript to interact with this tree by performing operations like removing elements from this tree or adding elements to this tree. (Note that preforming operations on the tree will not refresh the page.)
The standardized API to do these sorts of manipulation in JavaScript is known as the DOM. However, many people, myself included, think that this API is very clunky and not nearly expressive enough. Doing even trivial things require tons of lines of code. For this reason, many developers do not use the DOM directly instead using more powerful libraries, such as jQuery, to make their lives easier.
Below is an example of some HTML + JavaScript that I think mimics most of your requirements. Ideally for learning purposes, this would be written purely using the standard W3C DOM API, but since your problem is not that trivial, I resorted to using jQuery instead.
The HTML:
<select id="list" multiple="multiple"></select>
<input id="removeButton" type="button" value="Remove"></input>
<div>
<input id="optionAdder" type="text"></input>
<input id="addButton" type="button" value="Add"></input>
</div>
<br>
<input id="clearButton" type="button" value="Clear All"></input>
<div>Not So Hidden: <input id="hidden" type="text"></input></div>
The JavaScript:
// Uses jQuery to define an on document ready call back function
$(function(){
// The code in this function runs when the page is loaded
var options = []; // contains all the options
// add new option to drop-down
var addOption = function(optText) {
// Create new option element and add it to the <select> tag
$('<option></option>')
.attr('value', optText).text(optText)
.appendTo( $('#list') );
};
// writes the names of all the options in the "hidden" text box
var fillHidden = function() {
$('#hidden').val('');
var hiddenText = "";
for(var i=0; i< options.length; i++) {
if(hiddenText) {
hiddenText += "; ";
}
hiddenText += options[i];
}
$('#hidden').val(hiddenText);
}
// Bind the click event of the "Add" button to add an option on click
$('#addButton')
.click(function(){
var optText = $('#optionAdder').val();
if(optText) {
addOption(optText);
}
$('#optionAdder').val('');
options.push(optText);
fillHidden();
});
// Bind the click event of the "Remove" button to remove the selected options on click
$('#removeButton')
.click(function(){
$('#list option:selected').each(function(){
var optIndex = $.inArray($(this).val(), options);
if(optIndex > -1) {
options.splice(optIndex, 1);
$(this).remove();
}
fillHidden();
});
});
// Bind the click event of the "Clear" button to clear all options on click
$('#clearButton')
.click(function(){
$('#list').children().remove();
options = [];
fillHidden();
});
});
Here is a jsfiddle demonstrating the code