How to change the source of a child element with JavaScript? - javascript

I'm looking to change the source attribute of an image element when my parent element is clicked. The child/image element is actually nested within two div's which complicates things slightly and I have a suspicion this is where i'm going wrong in my code.
The JavaScript is as follows:
<script src="js/jquery-1.7.2.min.js"></script>
<script>
$(document).ready(function () {
$('.slideContent').hide();
$('.slideHeader').toggle(
function () {
$(this).next('.slideContent').slideDown();
$(this).children('.dropDownIcon').children('img').src = "./images/dropDownIconUp.png";
},
function () {
$(this).next('.slideContent').fadeOut();
$(this).children('.dropDownIcon').children('img').src = "./images/dropDownIconDown.png";
}
); // end toggle
}); // end ready
And the HTML is:
<div class="slideHeader">
<div class="dropDownIcon">
<img class="dropDownClass" src="./images/dropDownIconDown.png"/>
</div>
<div>
<p>2014</p>
</div>
</div>
<div class="slideContent">
<div>
<p>2014</p>
</div>
</div>
The slideDown and fadeOut functions from jQuery work fine. However the image change does not happen. So i'm confident my eror is within the following code:
$(this).children('.dropDownIcon').children('img').src = "./images/dropDownIconUp.png";
But as far as I can see, I select the correct elements in my chain. If anyone can shine any light on this it would be much appreciated. As everything else on the internet verifys the code above should work (Whilst a be little messy).
Thanks in advance.

src is an attribute of the img tag, so use .attr()
Try,
$(this).children('.dropDownIcon').children('img').attr('src', "./images/dropDownIconUp.png");

instead of using children selector twice use $(this).find('img').attr('src','./images/dropDownIconUp.png')

I know you have accepted the answer but let me tell you some points in brief
.src = "blah" would not work for jquery objects.$() always returns a jquery object and you must use .attr() or .prop() to work with jquery objects
However jquery provides a simple way to convert to javascript object
if you still want to use as a javascript object you could it this way
$(".slideHeader").children('.dropDownIcon').children('img')[0].src = "./images/dropDownIconDown.png";

Related

JsFiddle Javascript not firing?

I've got a huge feeling I'm simply being idiotic here, but is it me or is Js not firing in JsFiddle?
I built this snippet here but can't seem to get it to fire. Im probably missing something super obvious, but would be grateful for any assistance.
HTML
<div id="col">
<h3 class="txt spacer">Dynamic input, based on select value...</h3>
<input type="text" name="field-one" class="txt stretch" />
<div class="boxes">
<input type="checkbox" id="box-2" onChange="myFunction()" checked>
<label for="box-2">Apply a name?</label>
</div>
</div>
</div>
Javascript
function myFunction() {
// Text field element.
var a = document.getElementByName('field-one');
// Checkbox element.
var b = document.getElementById('box-2');
if (b.checked) {
a.disabled = false;
a.placeholder = 'Not Applicable';
alert('Checkbox State Changed.');
} else {
a.disabled = true;
a.placeholder = 'Enter Your Full Name';
alert('Checkbox State Changed.');
}
}
JS FIDDLE
Thanks in advance for the assistance.
Regards,
-B.
EDIT
I'm an idiot. Thanks guys.
Couple of things here, it should be document.getElementsByTagName (plural) and you need to change the settings, that will embed the JS code in before the body closes.
var a = document.getElementsByName('field-one')[0];
I am using [0] here to access the very first element of the array as document.getElementsByName() will return you an array of elements if encountered multiple matching elements. If you want to select a specific one, make sure you select the DOM element in a more specific way.
And change the Load Type to
No wrap - in <body> (<head> will work as well)
Demo
The Javascript Load Type for your jsFiddle is set to onLoad. This will nest your myFunction function, and therefore won't be available in the global scope.
You can either change the Load Type, or set the variable on the window:
window.myFunction = function()....
NB: You then receive another error for getElementByName. This isn't a function of document. You're probably looking for getElementsByName.
Open the DevTools and you'll see
Uncaught ReferenceError: myFunction is not defined
at HTMLInputElement.onchange ((index):192)
Now why isn't the function defined? Perhaps it's not defined at the right spot?
Look at where you load your JavaScript and change it to:
Here's an updated fiddle. Note that I fixed a typo on line 3 getElementsByName.
First, set your seeting of javascript LOAD TYPE to head.
last, is getElementsByName not getElementByName and it would return array so you need to parse.
let a = document.getElementsByName('field-one')[0];
hope it's helpful.

Polymer - Get data-bound attribute value in repeating template

I'm having a bit of an issue here. I had a small amount of success with event.target.templateInstance.model.thing syntax to get the value of attributes from within a repeating template but I keep getting back undefined from this bit of code I have here:
downloadFunction: function (e) {
console.log("dl function clicked");
//get particular id of thing
var fu = e.target.templateInstance.model.s.soundId;
console.log(fu);
//^ returns "TypeError: Cannot read property 'soundId' of undefined"
}
And my repeating template is here:
<div layout horizontal wrap center center-justified>
<template repeat="{{s in carddata}}">
<sound-card image="{{s.imgurl}}"
quotetext="{{s.quote}}"
soundsrc="{{s.soundurl}}"
soundref="{{s.soundId}}"
downloadfunction="{{downloadFunction}}">
</sound-card>
</template>
</div>
Where carddata is just an array with my data in it. All of the values are generated fine so I know it's not an issue with my array. I'm just confused how exactly I'm supposed to target someting from within the repeating template? Am I calling it at the wrong time? Or am I messing up the syntax of the templateInstance bit?
If it matters, I'm trying to get it to work in an Android 4.4 webView using Apache Cordova. 4.4 webView doesn't appear to enjoy the shadowDOM terribly much.
Thanks!
edit: After some jiggery pokery with console logs, it appears that the sender value is referring to the div that I apply the on-click="{{downloadFunction}} to. Here's the template that I am repeating, if this provides any insight.
<div class="soundcard-container" vertical layout>
//can't target this one either on WebView 4.4, works on ChromeOS
<img src="{{image}}" on-tap="{{playAudio}}">
<div class="soundcard-bottom-container" horizontal layout center justified>
<span>{{quotetext}}</span>
//I have an 'a' tag for desktop browsers and the div tag is targeting my Android/iOS
//apps that I am exporting as a webView to using Apache Cordova. Webonly is hidden
//at the point where I'm trying to get my downloadfunction to work.
//console.log(sender) in my downloadfunction returns this div v
<div on-tap="{{downloadfunction}}" class="mobileonly"></div>
</div>
//just a hidden audio thing for web
<div style="display: none">
<audio id="{{soundref}}" src="{{soundsrc}}" controls preload="auto"></audio>
</div>
</div>
edit2 some console logs..
console.log(sender) and console.log(event.target) are both the same div that has the on-click event for my downloadFunction.. not sure if this should be the case.
console.log(e.target.templateInstance.model) returns my <sound-card> object, I believe like it should(?)
It's just when I add the specific .s.soundId that it's undefined. I'm not sure why it's unable to find it.. Maybe there's another way to get the specific soundId (or s.soundId rather) of that particular <sound-card> object?
I'll bet you want to refer to the "sender" of the event—not e.target. See the part about inSender at https://www.polymer-project.org/0.5/docs/polymer/polymer.html#declarative-event-mapping:
inSender: A reference to the node that declared the handler. This is
often different from inEvent.target (the lowest node that received the
event) and inEvent.currentTarget (the component processing the event),
so Polymer provides it directly.
This might fix it:
downloadFunction: function (e, detail, sender) {
console.log("dl function clicked");
//get particular id of thing
var fu = sender.templateInstance.model.s.soundId;
console.log(fu);
}
Alright I was able to fit this in a different way. I wasn't able to get e.target.templateInstance.model.s.soundId bit to work, so instead on the div that I call the event on (event.target) I gave it an attribute called data-soundid and passed it {{soundref}} from my original template and then where I repeat that template I simply made a function like so:
downloady: function (e) {
console.log(e.target.getAttribute('data-soundurl'));
}
Ta da! Very nice solution. Thanks to Eyal who suggested this to me in a previous question. It works like a charm. :-)
Here is working example of using templateInstance, with included selecting by dynamic ID: Plunk .
As for your code, can't tell why it's not working.
handleEvent: function(e, detail, sender) {
console.log('handleEvent');
console.log(sender.id);
//How to catch full_obj here,
//..as if first item is clicked: full_obj = {"firstName":"John", "lastName":"Doe"}
//console.log(e);
console.log(e.target.templateInstance.model.item.firstName);
//console.log(detail);
//console.log(sender);
this.instance_firstName = e.target.templateInstance.model.item.firstName;
this.instance_lastName = e.target.templateInstance.model.item.lastName;
//Selecting by dynamic ID
var clicked_element = this.shadowRoot.querySelector('#'+this.instance_firstName);
console.log('Selecting');
console.log(clicked_element);
//var second_element = sender.templateInstance.model.querySelector('my-second-element');
//var second_element = this.$.second_element;
}
Edit:
Event handling and data binding Docs

Listen for changes in DOM

I am working on a reflection of part of my website. This is the relevant HTML:
<div id = "original">
<img src = "picture.png" alt = "A picture" id = "picture">
<p id = "text">Some text</p>
</div>
<div id = "reflection"></div>
My Idea is copying the content of div#original to div#reflection like this:
<script>
function reflect()
{
var original = document.getElementById("original");
var reflection = document.getElementById("reflection");
reflection.innerHTML = original.innerHTML;
}
</script>
I am aware, that this will make the HTML invalid, in the whole project I iterate through the elements copied and set the IDs to not have that side effect. I just thought that this would be unnecessary to include here.
The problem I have is that the HTML I want to reflect is dynamic, so it may change. Then the reflection is wrong. I have searched for an event handler for this, but haven't found one. The only one near I found was onchange, but apparently this listens to changes in the attributes, not the child elements. Is there another one for this, or did I just use onchange wrong?
Thank you for your help!
GeF
I am aware that I could add onchange to every element, but this seemed not good style to me.
The simplest thing you can do is add a callback to reflect() every time you change the contents of the #original.
If this is not an option, you can look into a MutationObserver (documetation), as suggested here: Is there a JavaScript/jQuery DOM change listener?

If i have a script inside a div, how do i get the id of that particular div? <br>

If i have a script inside a div, how do i get the id of that particular div?
(so that i can do like below, but with varying div id's):
<div id="chart_div1" class ="googlepie">
<script type="text/javascript">
drawChart('chart_div1');
</script>
</div>
[edit]:
I have two html views where when one view's button is clicked the second view is shown. some javascript reconstructs html to do this, and I only wanted the charts to be shown on the second view, so i have a click event handling this.
But strangely, i have only managed to load a particular chart in a particular div (of multiple repeated), like above, by putting the script that calls drawChart() in the div itself. For this reason i couldn't relocate the script into a more comfortable position like some have suggested. Also, no matter what suggested methods to fetch the parents div 'ID' i tried, i kept getting an 'undefined container' error.
For example this didnt work for me:
<div class ="googlepie" id="chart_div1" style ="position:absolute; top: -8%; left:63%;">
<script type="text/javascript" class ="chartscript" id="bakegooglepie">
// drawChart($('.chartscript').parent().attr('id')); // this didnt work
// drawChart($('#bakegooglepie').parent().attr('id')); // neither did this
// var parentElementID = $(document.body.lastChild).closest('div').id;
// drawChart(parentElementID); // this didnt either
drawChart('chart_div1'); // only this did
</script>
For this reason my (particular) solution is to construct the ids and call them specifically in drawChart instead of getting the id with javascript.
However, i have chosen the answer to the original question to be one that everyone else seems to work for and so should work for others.
Note: that as others have suggested in most situations you shouldn't need to get the parent ID like my question supposes.
Try this (jQuery):
<div id="chart_div1" class ="googlepie" style ="position:absolute; top: -4%; left:68%;">
<script type="text/javascript">
var parentElement = $(document.body.lastChild).closest('div');
drawChart(parentElement);
</script>
</div>
Or this (basic JavaScript):
<div id="chart_div1" class ="googlepie" style ="position:absolute; top: -4%; left:68%;">
<script type="text/javascript">
var scriptTag = document.scripts[document.scripts.length - 1];
var parentTag = scriptTag.parentNode;
drawChart(parentTag.id);
</script>
</div>
See here for more details: how to select parent of <script> element
Although this answers your question on how to achieve it, I believe this is not the best approach. You should place your JavaScript code at the end of the HTML document and use proper selectors to target your elements.
Cheers!
to get the id of the parent div using jQuery :
$(this).parent().attr('id')
in your case :
<div id="chart_div1" class ="googlepie" style ="position:absolute; top: -4%; left:68%;">
<script type="text/javascript" id='example'>
drawChart($('#example').parent().attr('id'));
</script>
</div>
It makes no difference where the script tag is on the page. you still have to use
document.getElementById('chart_div1');
You can't get elements relative to the <script> tag. Plus your ID's should be unique anyway so it shouldn't matter.
Well actually there are a few ways you can do this but it is not even slightly worth it. By doing it with document.body.lastChild it could break your whole script if the page loads even slightly different to normal.

Can't change background of div region using javascript?

This should be so simple, but I'm making heavy weather of it.
Div region set out as:
<div class="maincontent">
Stuff in my div
</div>
CSS for that div:
.maincontent{
height: 100%;
background-size: 100%;
margin-left:1%;
margin-right:1%;
font-size:16px;
}
Then I have:
onLoad=changeBackground();
But before that I have the function:
function changeBackground(){
document.getElementByAnything('maincontent').style.backgroundColor="yellow";
}
I know its making the call to the function because if I put an alert box in there that shows. But no matter what combination of getElementBy I can't make any changes to the background?
Please help as its driving me insane!
TIA
Have you tried giving your div an id and using document.getElementById('divId') instead? I think if you want to get the element by class you have to use jquery.
getElementById('maincontent')
and change your div to have an id="maincontent"
Try giving the element an id and doing document.getElementById and then do console.log in firebug or other developer tools and verify that you are actually getting a dom element back.
Once you have verified that you should then be able to switch the background color
You're trying to select the div using its class. This isn't quite as straightforward as getting it by id. Try this:
<div class="maincontent" id='mainContent'>
Stuff in my div
</div>
function changeBackground(){
document.getElementById('mainContent').style.backgroundColor="yellow";
}
You can see a working example here: JSFiddle
If you want to get the element using its class, I would recommend using Jquery or another library.
If you're using in line Javascript then use, instead:
onchange="changeBackground(this)"
And:
function changeBackground(elem){
elem.style.backgroundColor = "yellow";
}
Edited as I suddenly remembered you were discussing events based on div elements. As a div doesn't natively support the onchange event, I'd suggest amending your code to the following (though changing the event-type onmouseover to whatever event you find most appropriate):
function changeBackground(elem){
elem.style.backgroundColor = 'yellow';
};
JS Fiddle demo.
Also, to remove the events from in-line code, and to make the JavaScript more portable and less 'intrusive':
function changeBackground(elem){
elem.style.backgroundColor = 'yellow';
}
var maincontents = document.getElementsByClassName('maincontent');
for (var i=0,len=maincontents.length; i<len; i++){
maincontents[i].onmouseover = function(){
changeBackground(this);
}
}
JS Fiddle demo.
Bear in mind, though, that some browsers (such as Internet Explorer 8 and below) don't support getElementsByClassName().
I recommend using jQuery if you want to select a DOM by class name.
Put this code in your <head> part of your html
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
and change your function to
function changeBackground() {
$(".maincontent").css("background-color","yellow");
}

Categories

Resources