I am trying to customize this button that loads a background image in from the user input. Once they have added a background image, when they go to add another image (i.e. click Choose the second time), I want the first one to be removed from the background when the prompt re-opens to add another.
$(switchBackground);
var oFReader = new FileReader(),
rFilter = /^(?:image\/bmp|image\/cis\-cod|image\/gif|image\/ief|image\/jpeg|image\/jpeg|image\/jpeg|image\/pipeg|image\/png|image\/svg\+xml|image\/tiff|image\/x\-cmu\-raster|image\/x\-cmx|image\/x\-icon|image\/x\-portable\-anymap|image\/x\-portable\-bitmap|image\/x\-portable\-graymap|image\/x\-portable\-pixmap|image\/x\-rgb|image\/x\-xbitmap|image\/x\-xpixmap|image\/x\-xwindowdump)$/i;
oFReader.onload = function(oFREvent) {
localStorage.setItem('b', oFREvent.target.result);
switchBackground();
};
function switchBackground() {
$('body').css('background-image', "url(" + localStorage.getItem('b') + ')');
}
function loadImageFile(testEl) {
if (! testEl.files.length) { return; }
var oFile = testEl.files[0];
if (!rFilter.test(oFile.type)) { alert("You must select a valid image file!"); return; }
oFReader.readAsDataURL(oFile);
}
<input id="test" type="file" onchange="loadImageFile(this)" />
Here is a JS Fiddle of this code.
The simplest way is to add a click listener to the same input, which means whenever the user clicks anywhere inside the input it will call to empty the background. In your JS Fiddle, it is setting the background on the body, so I'll go with that in this example: -
function emptyBg() {
document.body.style.backgroundImage = 'none';
}
Register the click event (using the same syntax you used - although this should be attached using JavaScript and not HTML, see DOM Event Listeners).
<input id="test" type="file" onchange="loadImageFile(this)" onclick="emptyBg()"/>
Related
I have an image gallery on my site and when you click on it, it opens into a lightbox kind of effect.
I want them to be able to click off of the preview image on the lightbox background and close the preview but not if they click on the actual preview image itself.
function get_image_preview(){
var lightbox = document.getElementById("lightbox");
var image_src = document.getElementById("gallery_image").src;
lightbox.style.display = "block";
lightbox.setAttribute("onclick", "end_image_preview()");
var new_image = document.createElement("img");
new_image.setAttribute("id", "preview_image");
new_image.setAttribute("src", image_src);
new_image.setAttribute("onclick", "return false");
lightbox.appendChild(new_image);
}
function end_image_preview(){
var lightbox = document.getElementById("lightbox");
lightbox.style.display = "none";
lightbox.innerHTML = "";
}
So basically this line:
lightbox.setAttribute("onclick", "end_image_preview()");
does what it is supposed to do and close the preview.
However, the preview is a child of this and I want them to be able to click on the image without ending the preview, so I tried this:
new_image.setAttribute("onclick", "return false");
I think you mignt want to use event.stopPropagation():
function new_image_click(e) {
e.stopPropagation();
}
new_image.setAttribute("onclick", "new_image_click(event)");
in your end image preview click listener make sure that the element does not have in its ancestor the preview element it self, lets say that you gave the preview element the id "preview"
in end_image_preview
function end_image_preview(e) {
if (e.closest('#preview')) {
return
}
// here do what you already doing
}
I have a song submission form on my site. When an artist uploads a song, I developed JS to calculate the beats per minute (BPM) and duration of the song. Once calculated, it populates the two corresponding input boxes (Duration and BPM) on the form. The code I have works perfectly if a single song is submitted, however, the form allows multiple song uploads per form submission. Since these new input boxes are added dynamically, I'm not quite sure how I can get the new songs to dynamically update the value of the bpm/duration since the new input boxes are loaded by JS. There's a decent amount of code below, please let me know if you need more clarification:
The user can dynamically add another song by clicking the "Add another song" button loaded through JS:
<div id="dynamicInput"></div>
<input type="button" id="add-song-btn" value="Add another song" onClick="addInput('dynamicInput');">
Corresponding JS:
var counter = 1;
var limit = 20;
function addInput(divName)
{
if(counter == limit)
{
alert("You have reached the limit of adding " + counter + " inputs");
}
else
{
var newdiv = document.createElement('div');
{
newdiv.innerHTML = "<hr>Song #" + (counter + 1) + " " + "<input type='hidden' role='uploadcare-uploader' data-max-size='120000000' name='song-submission'data-crop='disabled' /><input type='text' id='duration' name='submit-duration' placeholder='Duration: '3:11'><input type='number' id='bpm' name='submit-bpm' placeholder='BPM: 128'>";
document.getElementById(divName).appendChild(newdiv);
}
counter++;
setTimeout(function () {
uploadcare.initialize();
}, 0);
}
};
When a user uploads a song by using the "Choose a file" button, this is the corresponding input box:
<input name="song-submission" type="hidden" role="uploadcare-uploader" data-max-size="120000000" data-file-types="mp3" data-crop="disabled">
When uploaded, the submission creates a src url that I add to an audio HTML src tag that triggers two different JS functions. When the upload completes the JS code widget.onUploadComplete runs. Here's that audio tag and the corresponding code that loads the src url into that html code:
<audio id="myAudio" controls onloadedmetadata="setDuration()">
<source src="">
</audio>
JS
var widget = uploadcare.Widget('[role=uploadcare-uploader]');
widget.onUploadComplete(function(info) {
var previewUrl = info.cdnUrl;
document.getElementById('myAudio').src = info.cdnUrl;
//code to calculate BPM is found here///
document.getElementById('bpm').value = Math.round(top[0].tempo);
};
};
request.send();
});
When the src url is added to the HTML audio id="myAudio" tag, the JS waits until onloadedmetadata to run a function ( setDuration()) to determine the duration:
function setDuration() {
var time = document.getElementById('myAudio').duration;
// code to calculate duration //
ret += "" + mins + ":" + (secs < 10 ? "0" : "");
ret += "" + Math.round(secs);
document.getElementById('duration').value = ret;
return ret;
}
So here is where I'm at, and my code does not work with dynamically loaded input boxes. First thing is that once a new song submission input is added, there would be two input boxes with role=uploadcare-uploader which would cause issues with the widget JS variable right off the bat, I think that's where we need to start first. Any thoughts?
PROBLEM
When you initialize new uplaodcare instance (deferred) it doesn't register onUploadComplete events for those newly created widgets, because only on that moment when you execute uploadcare.Widget('[role=uploadcare-uploader]'); first child only (another problem of your code) gets the event listener registered.
Element argument can be a DOM element, a jQuery object, or a CSS selector. >If element’s argument is a CSS selector, only the instance for the first >matched element will be returned. To make sure you get the right instance >when there are multiple widgets on the page, select by id or pass in a DOM element.
SOLUTION
Execute your code after each uploadcare instance creating and use unique selector to get proper widget:
setTimeout(function () {
uploadcare.initialize();
var widget = uploadcare.Widget('#song-uploader-<1..N>'); // Generate this when DIV adding
widget.onUploadComplete(function(info) {
var previewUrl = info.cdnUrl;
document.getElementById('myAudio').src = info.cdnUrl;
//code to calculate BPM is found here///
document.getElementById('bpm').value = Math.round(top[0].tempo);
};
};
request.send();
});
}, 0);
You can omit the handler into its own function to keep code cleaner and write widget.onUploadComplete(calculateBPM)
Have a look at the API documentation:
There it says:
Initializes widget instances once (either single-upload, or
multi-upload) on every element with role="uploadcare-uploader"
attribute in a container, specified by selector or DOM element. If
container is absent the document is used. Returns array of new
initialized widgets, or empty array if no new instances were
initialized.
var widgets = uploadcare.initialize('#my-form');
widgets; // [widget1, widget2, multipleWidget1, ...]
var widgets = uploadcare.initialize();
So from that point you can go on. (e.g. giving the input box an id and call your js function on every input box with that id).
I have a very simple javascript which turns book isbns in to clickable URL links to Amazon.com. What I am trying to do is add a function that when "clicked" opens all the URL links in new tabs. This saves me the time of clicking every single link.
Is this doable? =)
<html>
<head>
</head>
<div><b>ISBN Hyperlinker</b></div>
<textarea id=numbers placeholder="paste isbn numbers as csv here" style="width:100%" rows="8" >
</textarea>
<div><b>Hyperlinked text:</b></div>
<div id="output" style="white-space: pre"></div>
<script>
//the input box.
var input = document.getElementById('numbers');
var output = document.getElementById('output')
var base =
'https://www.amazon.com/s/ref=nb_sb_noss?url=search-alias%3Daps&field-keywords='
//adding an event listener for change on the input box
input.addEventListener('input', handler, false);
//function that runs when the change event is emitted
function handler () {
var items = input.value.split(/\b((?:[a-z0-9A-Z]\s*?){10,13})\b/gm);
// Build DOM for output
var container = document.createElement('span');
items.map(function (item, index) {
if (index % 2) { // it is the part that matches the split regex:
var link = document.createElement('a');
link.textContent = item.trim();
link.setAttribute('target', '_blank');
link.setAttribute('href', base + item);
container.appendChild(link);
} else { // it is the text next to the matches
container.appendChild(document.createTextNode(item))
}
});
// Replace output
output.innerHTML = '';
output.appendChild(container);
}
handler(); // run on load
</script>
</html>
You can trigger a click event manually, like:
container.appendChild(link);
link.click();
But that's just an example to show you easily that it would work with your given code. I would suggest having a button like "Open All Links" and having that button use a selector to gather up all the links and then loop through them and call the click method on each one. You would be making things easier on yourself giving the outer container (the output div) an ID that you could use as the initial outer selector.
It works but there's a pesky bug I can't understand how to fix (i'm a beginner).
What happens is there are 3 image buttons (only showing code for 1 here) and when i hover over them, they change image, and revert when i take mouse off. This is the html.
When I click any of the 3 image buttons (javascript), it changes its own image, and sets the other 2 image buttons to the normal image.
After this point (clicking the image) the hovering html code doesn't work anymore.
function changeImage3() {
document.getElementById('MageBTN').src = 'images/Character/NotSelected_Mage.png';
document.getElementById('WarriorBTN').src = 'images/Character/NotSelected_Warrior.png';
}
<a href="#" onclick="changeImage3()"><img id="RogueBTN" src="images/Character/NotSelected_Rogue.png" alt="image"
onclick="this.src='images/Character/Selected_Rogue.png';
this.onmouseover = false; this.onmouseout = false;"
onmouseover="this.src='images/Character/Selected_Rogue.png';"
onmouseout="this.src='images/Character/NotSelected_Rogue.png';">
</a>
just suggestion.. Use simple css property..
#yourID a:hover{
//your image which want to show on hover
}
If I have understand correctly you want to lock the selected state of a button on click and unlock/reset to not-selected when another button is clicked. Therefore you have to store the state of the buttons so I suggest to move all functionality to a script. Since you have all images well ordered it's enough to change Sel/NotSel in the url.
window.onload = function() { // ensures that all elements are there
var buttons = {
RougeBTN: document.getElementById("RougeBTN"),
VertBTN: document.getElementById("VertBTN"),
BleuBTN: document.getElementById("BleuBTN")
},
locked;
function clicked() {
for (var btn in buttons) { // iterate over the buttons
var b = buttons[btn];
// if this button was clicked save the state
if (btn == b.id) locked = btn;
else {
b.src = b.src.replace('/Sel', '/NotSel');
}
}
}
function mover() { // works only when button is not locked
if (locked != this.id) this.src = this.src.replace('/NotSel', '/Sel');
}
function mout() { // works only when button is not locked
if (locked != this.id) this.src = this.src.replace('/Sel', '/NotSel');
}
for (var btn in buttons) { // now set the functions to all buttons
var b = buttons[btn];
b.onclick = clicked; b.onmouseover = mover; b.onmouseout = mout;
}
}
In html all buttons look like this:
<img id="RougeBTN" src="images/Character/NotSelected_Rouge.png" alt="image">
I have a problem with changing onmouseover and onmouseout attributes on dynamic pictures. The way i want it to work is whenever i put my mouse over images the images must change and when i take my mouse away it must be changed to the original picture. and whenever i select any image, that image must be changed to the image which was displayed while moving the mouse across the image. and when i select any other image the same process must take place but the previous image that was changed must be changed back to the original picture.
I have accomplished all of the above but my problem is when i select multiple pictures and put my mouse over images that were previously selected, those images do not change (onmouseover attribute does not work on them anymore).
<script language="javascript">
function changeleft(loca){
var od=''
var imgs = document.getElementById("leftsec").getElementsByTagName("img");
for (var i = 0, l = imgs.length; i < l; i++) {
od=imgs[i].id;
if(od==loca){
imgs[i].src="images/"+od+"_over.gif";
imgs[i].onmouseover="";
imgs[i].onmouseout="";
}else{
od = imgs[i].id;
imgs[i].src="images/"+od+".gif";
this.onmouseover = function (){this.src="images/"+od+"_over.gif";};
this.onmouseout = function (){this.src="images/"+od+".gif";};
}
}
}
</script>
<div class="leftsec" id="leftsec" >
<img id='wits' class="wits1" src="images/wits.gif" onmouseover="this.src='images/wits_over.gif'" onmouseout="this.src='images/wits.gif'" onclick="changeleft(this.id)" /><br />
<img id='city' class="city1" src="images/city.gif" onmouseover="this.src='images/city_over.gif'" onmouseout="this.src='images/city.gif'" onclick="changeleft(this.id)" /><br />
<img id='organise' class="city1" src="images/organise.gif" onmouseover="this.src='images/organise_over.gif'" onmouseout="this.src='images/organise.gif'" onclick="changeleft(this.id)" /><br />
<img id='people' class="city1" src="images/people.gif" onmouseover="this.src='images/people_over.gif'" onmouseout="this.src='images/people.gif'" onclick="changeleft(this.id)" /><br />
</div>
I would recommend to use an Ajax library (jQuery, YUI, dojo, ExtJS, ...). In jQuery I would do something like:
Edit: Extended the example with .click() ability.
var ignoreAttrName = 'data-ignore';
var imgTags = jQuery('#leftsec img'); // Select all img tags from the div with id 'leftsec'
jQuery(imgTags)
.attr(ignoreAttrName , 'false') // Supplying an ignore attribute to the img tag
.on('click', function () {
jQuery(imgTags).attr(ignoreAttrName, 'false'); // Resetting the data tag
jQuery(this).attr(ignoreAttrName, 'true'); // only the current will be ignored
// Do whatever you want on click ...
})
.on('mouseover', function () {
// This will be called with the img dom node as the context
var me = jQuery(this);
if (me.attr(ignoreAttrName) === 'false') {
me.attr('src', me.attr('id') + '.gif');
}
})
.on('mouseout', function () {
// This will be called when leaving the img node
var me = jQuery(this);
if (me.attr(ignoreAttrName) === 'false') {
me.attr('src', me.attr('id') + '-over.gif');
}
});
With a library it's cleaner and more scalable I think and the chance that it's working in other browsers is increased too :).
Hope this helps you out!