Can't fire event "Uncaught ReferenceError: killMedia is not defined" - javascript

Im making WYSIWYG editor for web magazine with Riot.js.
I want to disply instagram image with delete icon when I click add button and delete instagram image when I click delete icon.
I can disply instagram image with delete icon but cant delete them because function killMedia doesnt work.
When I click delete icon, I get this error message.
Uncaught ReferenceError: killMedia is not defined
Im working on below code.
Does anyone know what problem is?
<div id='body-text' class='body-text' contenteditable=true data-placeholder='Body Contents'></div>
<label>
<input type='text' name='instagram' placeholder='Input Instagram embed code'>
<button onclick={ addInstagram }>add</button>
</label>
<script>
addInstagram(e) {
var embedCode = this.instagram.value
var instagram = document.createElement('div')
instagram.setAttribute('class', 'media-frame')
instagram.setAttribute('show', '{showMedia}')
instagram.innerHTML = embedCode
var i = document.createElement('i')
i.setAttribute('id', 'media-killer')
i.setAttribute('class', 'fa fa-times-circle-o media-killer')
i.setAttribute('aria-hidden', 'true')
i.setAttribute('show', '{showMedia}')
i.setAttribute('onclick', '{killMedia}')
var target = document.getElementById('body-text')
instagram.appendChild(i)
target.appendChild(instagram)
this.instagram.value = ''
this.update()
this.modal = false
}
this.showMedia = true
killMedia(e) {
this.showMedia = false
this.update()
}
</script>

The syntax you are using to define the function killMedia is incorrect. It seems like Riot.js has some alternative syntax for event handlers, which is why it works for addInstagram.
There are several ways to properly declare and define a function in JavaScript. One would be:
// declare variable killMedia and assign a function to it
var killMedia = function( e ){
this.showMedia = false;
this.update();
}
Also, I don't know anything about how Riot.js will call event functions, so, since you are using this inside your killMedia function, you may need to bind the proper this to the function as you declare it. One way to do this is with the bind function:
// declare variable killMedia and assign a function to it
var killMedia = function( e ){
this.showMedia = false;
this.update();
}.bind( this );
If the syntax is not the problem and Riot.js is handling the special declaration of killMedia, you may just need to declare killMedia before addInstagram, i.e. move that function above addInstagram. This is just a guess, since I don't know anything about Riot.js.

I added this as a comment but now I had time to implement this.
I think that is not working because you are trying to load the elements dynamically so is not compiled by Riot compiler.
A more Riot.js way to do what you want is to build another tag called instagram_image that you can remove, and have an array to iterate the images in the parent tag.
I simplified your code, but the idea is this:
(here is the plunker version http://plnkr.co/edit/EmkFhq0OyVtwSNIJqeJF?p=preview)
<my-tag>
<span each={img in instagram_images} >
<instagram_image embed_code={img.embed_code}></instagram_image>
</span>
<label>
<input type='text' name='instagram' placeholder='Input Instagram embed code'>
<button onclick={ addInstagram }>add</button>
</label>
<script>
this.instagram_images = []
addInstagram(e) {
var instagram_image = {embed_code: this.instagram.value}
this.instagram_images.push(instagram_image)
this.instagram.value = ''
}
</script>
</my-tag>
<instagram_image>
<div onclick={remove}>
{opts.embed_code}
</div>
<script>
this.remove = function() {
this.unmount()
this.update()
}
</script>
</instagram_image>

Related

How to read specific value from button in js function

I have several buttons contain some values:
<button class="Hotspot" onclick="ChangeView()" slot="hotspot-1" camera.Orbit='2.895deg 85deg 27.92m' ;>
and I need to create function that read camera.Orbit value from button's container after click on it:
function ChangeView() {
const modelViewer = document.querySelector('#orbit-demo');
modelViewer.cameraOrbit = camera.Orbit ???
}
I have no idea how to solve this. I do not use getElementbyId because it has to work for all buttons (not specific one).
I barely can JS.
Thank you for help.
You can use Element.getAttribute:
function ChangeView() {
const modelViewer = document.querySelector('#orbit-demo');
let orbit = modelViewer.getAttribute('camera.Orbit')
console.log(orbit)
}
<button class="Hotspot" onclick="ChangeView()" slot="hotspot-1" camera.Orbit='2.895deg 85deg 27.92m' id="orbit-demo">Click</button>
The onclick function passes the click event to the method. You can take the target of this event (the button element) and acquire tha attribute like that.
onclick(e => changeView(e))
ChangeView(e) {
// do things with e.target.???
}

Variable doesn't update after having event listener

I cannot update the value for userPickColor for some reason, it is always undefined. But I try to console.log inside the functions and my values are actually changing. But for some reasons, once I call it outside the function, it doesn't update at all.
I'm still new to Javascript so Please Help me
Here is my code:
var white = document.getElementById("white");
var black = document.getElementById("black");
var userPickColor;
white.addEventListener("click", whiteshirt);
black.addEventListener("click", blackshirt);
function whiteshirt(){
userPickColor= "white";
}
function blackshirt(){
userPickColor= "black";
}
ShirtDescrp.innerHTML = userPickColor;
As others have said, you need to place the line that updates the .innerHTML inside of the callback functions so that after the variable has been updated, you can update the page with the most current variable value as well.
But, taking this one step further... There is a common coding methodology called DRY (Don't Repeat Yourself) and you've got two callback functions that largely do the same thing. The only difference is the actual text that gets set. Those two functions run when one of two elements on your page get clicked and those two elements have the text you want to use as their ids. We could easily combine the two callbacks into just one like this:
var ShirtDescrp = document.getElementById("des");
// There's nothing wrong with variables if they help you read the code
// more easily, but if you won't be using the value they store more than
// once, they don't really add much.
document.getElementById("white").addEventListener("click", changeColor);
document.getElementById("black").addEventListener("click", changeColor);
function changeColor() {
// No variable needed. Just set the text to the id of the element that got clicked
// "this" here refers to the object that initiated the call for the current function
// which will be one of the two buttons.
ShirtDescrp.innerHTML = this.id;
}
<button id="white">white</button>
<button id="black">black</button>
<p id="des"></p>
you have to put ShirtDescrp.innerHTML = userPickColor; inside your event listener as well since you change the variable but you didn't tell the dom to update the content
You should update the DOM same as the variable:
var white = document.getElementById("white");
var black = document.getElementById("black");
var ShirtDescrp = document.getElementById("des");
var userPickColor = null;
white.addEventListener("click", whiteshirt);
black.addEventListener("click", blackshirt);
function whiteshirt() {
userPickColor = "white";
ShirtDescrp.innerHTML = userPickColor;
}
function blackshirt() {
userPickColor = "black";
ShirtDescrp.innerHTML = userPickColor;
}
<button id="white">white</button>
<button id="black">black</button>
<p id="des"></p>
You have already got your answer... Change doesn't affect as update is not happening inside event listener. This is just a recommendation how I would do it (especially if i had more color options):
<p id="color-name">none</p>
<div class="color-buttons">
<button id="white">White</button>
<button id="black">Black</button>
<button id="orange">Orange</button>
<button id="blue">Blue</button>
<button id="green">Green</button>
<button id="red">Red</button>
</div>
JavaScript like:
var buttons = document.querySelectorAll(".color-buttons button");
var color_name = document.getElementById("color-name");
buttons.forEach(function(btn){
btn.addEventListener("click", function(){
color_name.style.background=this.id;
color_name.innerHTML=this.id;
});
});
Here is the fiddle to play around.
I would also probably generate those buttons dynamically as well. And also wouldn't use id to store color but i would use something else like data-color='red' for example.

Variable value not accumulating?

Hey I'm very new to JS but cannot figure out why the 3 variables at the top aren't accumulating?
var xe = 0;
var reckon = 0;
var books = 0;
document.getElementById('#go').addEventListener('click', function(){
questionOne();
});
document.getElementById('#macos').addEventListener('click',function(){
addXe();
questionThree();
});
document.getElementById('#windows').addEventListener('click',function(){
questionThree();
});
document.getElementById('#linux').addEventListener('click', function(){
questionThree();
});
document.getElementById('#large').addEventListener('click', function(){
questionFour();
addXe();
});
function addXe(){
xe++;
};
function addReckon(){
reckon++;
};
function addBooks(){
books++;
};
The rest of the code is simply a series of functions that toggles divs display on and off.
If Ive missed and important info out let me know,
Thanks!
EDIT:
github.com/daffron/accountingsoftware
I thought it would be easier to attach the whole site, the problem is each time the addXero function is executed , it doesn't accumulate the value of var xero, I have it printing to console in the other functions. Thanks –
Your parameters for document.getElementById() are wrong.
If your HTML code for a button is like this:
<input type="button" id="go" />
<!-- OR like this: -->
<button id="go" ></button>
Then your javascript code must access the button using the method getElementById() as:
document.getElementById("go");
So, one of your functions will be like:
document.getElementById('go').addEventListener('click', function(){
questionOne();
});
BUT, if you've used '#go' because you were referring to a CSS Selector then you've to use querySelector method instead of getElementByIdas:
document.querySelector("#go");
So, a function call as per your code will be:
document.querySelector('#go').addEventListener('click', function(){
questionOne();
});
you should have html label example
<label id="xeLbl">test</label>
and after changing value you should apply it to html label.
function addXe(){
xe++;
document.getElementById('xeLbl').innerHTML = xe;
};

Get variables from button css in Javascript and use them as id

Hi I need a bit of help modifying my script. What I want to do:
I have a small and easy script. It changes the class of an container so I have influence on the behaviour and looking of the container. In my scenario the buttons open a div with a music player.
My problem is that I need to declare all buttons as a script. The button ID is in my case the onclick function (see code).
So when I have 10 or twenty links I need also everytime to modify the script. My idea is to have a script wich gets feed their variables by id's and classes of containers. So I need not to modify the script file.
// JavaScript Document
function AudioFF() {
var FFplayer = document.getElementById(x);
if (FFplayer.classList.contains("audio-hidden")) {
FFplayer.classList.remove("audio-hidden");
FFplayer.classList.add("audio-shown");
} else {
FFplayer.classList.remove("audio-shown");
FFplayer.classList.add("audio-hidden");
Array.prototype.slice.call(document.querySelectorAll('audio')).forEach(function(audio) {audio.pause();});
}
};
dbbtn.onclick = function() {
x = "deepblue";
AudioFF();
};
swbtn.onclick = function() {
x = "spacewalk";
AudioFF();
};
fbtn.onclick = function() {
x = "forest";
AudioFF();
};
drbtn.onclick = function() {
x = "dreamrhythm";
AudioFF();
};
My idea was to use the same class of a button as an id for the container who needs to fade in with a string. The button has e.g. the class btn_a, btn_b … etc. The containers has the id btn_a, btn_b … I wanted the script to catch the class of the button and use this classname as a variable for getElementById. The closebutton is also using the same script to close the container. Thanks for help :-)
I will recommend to use data attribute instead
example like this:
//register listener like this
var btns = document.querySelectorAll('[data-music]');
btns.forEach(function(elm) {
elm.addEventListener('click', function(e) {
//your function
console.log(this.dataset.music);
})
})
<!--your links-->
<div id="m1"></div>
<div id="m2"></div>
<div id="m3"></div>
<!--just add data-music attribute make it the same with your div id and all set-->
<button data-music="m1">play m1</button>
<button data-music="m2">play m2</button>
<button data-music="m3">play m3</button>
You should be able to set a data tag attribute to the buttons and just read the variable from that:
<button id="myButton" data="variableForMyButton" />
document.getElementById(myButton).onClick = function(e){
x = e.target.getAttribute('data')
}
If multiple params are required you add additional data tags:
<button id="myButton" data="variableForMyButton" data-action="someSweetAction" />
Thanks guys, that was what I was looking for. My function is now like this:
The play button and closebutton are working.
<button data-music="m1">Deep Blue</button>
<div id="m1">Container Content</div>
var btns = document.querySelectorAll('[data-music]');
btns.forEach(function(elm) {
elm.addEventListener('click', function(e) {
//function
var FFplayer = document.getElementById((this.dataset.music));
if (FFplayer.classList.contains("audio-hidden")) {
FFplayer.classList.remove("audio-hidden");
FFplayer.classList.add("audio-shown");
} else {
FFplayer.classList.remove("audio-shown");
FFplayer.classList.add("audio-hidden");
Array.prototype.slice.call(document.querySelectorAll('audio')).forEach(function(audio) {audio.pause();});
}
})
})
And here in jquery. Thanks to you all. You show me the way :-)
jQuery (document).ready(function($){
var btns = $('[data-music]');
$(btns).each(function() {
$('[data-music]').on('click', function(e) {
var FFplayer = $(this).data('music');
$("#" + FFplayer).toggleClass("audio-hidden audio-shown");
});
});
})

Do I need to create multiple functions for multiple actions or can they all be housed in the same function?

I'm working on a script to simulate a page change in a Questionnaire I'm building. I figured maybe I could use a bunch of "if" statements to house all the logic but it's not working right, before I go and create separate functions I'd like to know if it's possible to put them all in one single function.
So far this is the script
function pageChange(){
var chng1 = document.getElementById("p1next");
var chng2a = document.getElementById("p2back");
var chng2b = document.getElementById("p2next");
var chng3a = document.getElementById("p3back");
var chng3b = document.getElementById("p3next");
var pg1 = document.getElementById("page01");
var pg2 = document.getElementById("page02");
var pg3 = document.getElementById("page03");
if (chng1.click){
pg1.style.display="none";
pg2.style.display="block";
}
if (chng2a.click){
pg1.style.display="block";
pg2.style.display="none";
}
the "p1next, p2back, p2next etc." are IDs I gave the buttons on the pages, which I have in DIVs that I respectively named "page01, page02, page03 etc."
Without the 2nd if statement the script works exactly how I want it, it changes the display for "page01" to none and the div for "page02" to block. When I add the second if statement it doesn't work.
The reason I want to do it like this rather than making actual pages is because I don't want the data to get lost when they load another page. Am I on the right track or do I need to create a new function for each page?
Not exactly on the right track, you should use onclick events, instead of if (x.click) like this:
var chng1 = document.getElementById("p1next");
var pg1 = document.getElementById("page01");
var pg2 = document.getElementById("page02");
// Events
chng1.onclick = function(){
pg1.style.display="none";
pg2.style.display="block";
};
This will save your function until the element is clicked and then execute that function. In your case, it is executed on page load, and at that moment the user is not clicking anything.
Why not try something like this:
HTML:
<div class="page" data-pg="1">...</div>
<div class="page" data-pg="2">...</div>
<div class="page" data-pg="3">...</div>
<input id="btnPrev" type="button" value="Prev" />
<input id="btnNext" type="button" value="Next" />
jQuery:
var pageNum = 1;
$(document).ready(function () {
$("#btnPrev").on("click", function () { ChangePage(-1); });
$("#btnNext").on("click", function () { ChangePage(1); });
ChangePage(0);
});
function ChangePage(p) {
$(".page").hide();
pageNum += p;
$(".page[data-pg='" + p + "']").show();
$("#btnPrev").removeAttr("disabled");
$("#btnNext").removeAttr("disabled");
if (pageNum === 1) $("#btnPrev").attr("disabled", "disabled");
if (pageNum === $(".page").length) $("#btnNext").attr("disabled", "disabled");
}
That way you can easily grow your number of pages without changing the script. My apologies by the way for doing this in jQuery.
Update:
Have a lot of time on my hands today and have not coded for while using vanilla Javascript. Here's the version of the code using plain js: https://jsfiddle.net/hhnbz9p2/

Categories

Resources