Edit: This is what my code currently looks like. It's still not working.
<head>
<script>
window.onload = myload()
var ids[]
function myload() {
alert("hi")
ids = [document.getElementById('bs'),
document.getElementById('cs'),
document.getElementById('ds')
]
}
function border(){
ids[1].style.border = "9px";
}
</script>
</head>
<body> //elements definded here </body>
I'm trying to write a function that changes the border of a list of images at a certain interval. However, I can't seem to make it work.
I am trying to do the following:
<head>
<script>
var ids = [document.getElementById('a'),
document.getElementById('b'),
document.getElementById('c')]
function(x){
ids[x].border = "9px";
}
</script>
</head>
<body> //elements definded here </body>
but it doesn't run. However, when I run:
document.getElementById('a').border = "9px"
it does work. I'm guessing I'm not calling it properly from the array. What am I doing wrong?
Edit: fixed 'a' twice in the array.
Answering the original question before the function(x) appeared
[1] is the b since JS arrays start at 0
I would expect style.border.
The array has to be defined AFTER the objects have rendered.
If you have the array in a script tag before the elements with ids
a,b,c exist then you will get the ids equal to
[undefined,undefined,undefined]
window.onload = function() { // or addEventHandler OR put script before </body>
var ids = [document.getElementById('a'),
document.getElementById('b'),
document.getElementById('a')
]
ids[1].style.border = "9px solid black"; // the second element
}
<div id="a">A</div>
<div id="b">B</div>
<div id="c">C</div>
Using a function:
var ids=[]; // this is now global in scope
function setIt(idx) {
ids[idx].style.border = "9px solid black";
}
window.onload = function() { // or addEventHandler OR put script before </body>
ids = [document.getElementById('a'),
document.getElementById('b'),
document.getElementById('a')
]
setIt(1); // the second element
}
<div id="a">A</div>
<div id="b">B</div>
<div id="c">C</div>
Fixing your code
window.onload = myload; // removed ()
var ids=[]; // missing an equals
function myload() {
alert("hi")
ids = [document.getElementById('bs'),
document.getElementById('cs'),
document.getElementById('ds')
]
border();
}
function border() {
ids[1].style.borderWidth = "9px"; // just setting border is not enough
}
div { border: 1px solid red }
<div id="bs">A</div>
<div id="cs">B</div>
<div id="ds">C</div>
Arrays in JavaScript are indexed from 0, so doing ids[0].style.border = "9px"; or ids[2].style.border = "9px"; Will give you the desired effect. You'll also want to access the style property on the element (I've fixed that in the code)
Related
Using the HTML below, how can I get a list of the functions in the <script> tag that is IN the #yesplease div. I don't want any other functions from other script tags. I don't want any global functions or native functions. What I'd like is an array with "wantthis1" and "wantthis2" only in it. I'm hoping not to have to use regex.
I am going to be emptying and filling the #yesplease div with different strings of html (including new script tags with new functions), and I need to make sure that I delete or "wantthis1 = undefined" each function in the script tag before filling it, programmatically, since I won't know every function name. (I don't want them to remain in memory)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script>
function dontCare() {
// don't care
}
</script>
</head>
<body>
<div id="notthisone">
<p>
Hello
</p>
<script>
function dontwantthis () {
// nope
}
</script>
</div>
<div id="yesplease">
<p>
Hello again
</p>
<script>
function wantthis1 () {
// yes
}
function wantthis2 () {
// yes
}
</script>
</div>
<script>
// this function can be called by whatever, but this will look to
// see if functions exist, then call them, otherwise do something
// else
function onSaveOrWhatever () {
if (wantThis1 !== "undefined") {
wantThis1();
}
else {
// do something else (won't get called with above example)
}
if (wantThis3 !== "undefined") {
wantThis3();
}
else {
// do something else (will get called with above example)
}
}
</script>
</body>
</html>
Take innerHTML of all script tags you need
Create an iframe
Get a list of built-in functions of iframe.contentWindow object
Write the content of the script to the iframe created
Get a new list of the functions of iframe.contentWindow object
Find new functions added to the new list
Somehow it doesn't work in stack snippets but it works in Codepen link
var code = document.querySelector("#target script").innerHTML;
var iframe = document.createElement("iframe");
document.body.appendChild(iframe);
var builtInFunctions = getFunctionsOfWindowObject();
var html = `<html><head><script>${code}</script></head><body /></html>`;
iframe.srcdoc = html;
var allFunctions = getFunctionsOfWindowObject();
var result = allFunctions.filter(function(n) {
return builtInFunctions.indexOf(n) < 0;
});
console.log(result);
function getFunctionsOfWindowObject() {
var functions = [];
var targetWindow = iframe.contentWindow;
for (var key in targetWindow) {
if (
targetWindow.hasOwnProperty(key) &&
typeof targetWindow[key] === "function"
) {
functions.push(key);
}
}
return functions;
}
iframe {
display: none;
}
<div id="target">
<script>
function wantthis1() {}
function wantthis2() {}
</script>
</div>
The are a few ways to solve this problem
Architect your application. Use react or vue (or even jquery) to add more control to your code/dom
AST parsing, which would be overkill
Hack it
If you hack it, the problem that you will face is that you are adding functions to global scope. This is shared by everyone, so you can't really monitor it in a nice way.
You can however take advantage of javascript singlethreadedness, and know that things won't happen in the background while you are doing monitoring tasks.
<script>
// take a cache of what is present before your script
window.itemsPresentBeforeScript = {};
foreach (var item in window) {
window.itemsPresentBeforeScript[item] = window[item];
}
</script>
<script> .... your other script </script>
<script>
// use your first cache to see what changed during the script execution
window.whatWasAddedInTheLastScript = {};
foreach (var item in window) {
if (!window.itemsPresentBeforeScript[item]) {
window.whatWasAddedInTheLastScript[item] = window[item];
}
}
delete window.itemsPresentBeforeScript;
// not you have a global list of what was added and you can clear it down when you need to
</script>
I am wondering if is possible to do this.
I have my javascript function
function doSomething(){
return "Hello World"; //its actually more complicated method but the logic is the same..
}
so, at my html I have this.
<div class="someClass">
<script type="text/javascript">
doSomething();
</script>
</div>
So, basically, I want to is to print that hello world inside the div where is called.
Any idea how to do this?
AFAIK JavaScript cannot easily determine the location of its script declaration. As Marc B suggested in a comment--it works for printing to the document stream, but other applications won't work. Not to mention if you want the same behavior in multiple places, you've violated the "don't repeat yourself" (DRY) principle. You should instead inspect the dom document and find the element you wish to print "hello" in. This is easily accomplished with jQuery:
$(document).ready(function () {
$('.someClass').text('hello');
});
As laugri suggests, you should add an id to your div if you want only the one div changed.
<div id="someId".../>
...
$(document).ready(function () {
$('#someId').text('hello');
});
You can generate a unique div to find wherever you're code is executing
http://jsfiddle.net/190p77wu/
var doSomething = function (id) {
var targ = document.getElementById(id).parentNode;
targ.innerHTML = "This was inserted for id " + id;
}
and your html:
<div>
You shouldn't see this text.
<script>
var uniqueId = "tmp_" + Math.round(Math.random() * 100000000);
document.write('<div id="' + uniqueId + '"></div>');
doSomething(uniqueId);
</script>
</div>
Edit: or even cooler, if you have a properly cached JS file, you can do something like this:
http://jsfiddle.net/190p77wu/1/
var doSomething = function (script) {
var targ = script.parentNode;
targ.innerHTML = "This was inserted dynamically";
}
and this html:
<div>
You shouldn't see this text.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js" onload="doSomething(this)"></script>
</div>
Try setting an id at script element , calling script.parentElement within doSomething
<div class="someClass">
<script type="text/javascript" id="someClass">
function doSomething() {
var elem = document.getElementById("someClass");
elem.parentElement.appendChild(
document.createTextNode("Hello World")
)
}
doSomething();
</script>
</div>
If I use two buttons it works fine now I wonder if I could use just one and how, this is the code for two buttons however I want to use only one button to execute the code that changes the style of the div, for instance the buttons code that I wrote is:
<title></title>
<style>#ok{width:100px;height:100px;background-color:black;}</style>
</head>
<body>
<div id="ok">ok</div>
<button id="a">on</button>
<button id="b">off</button>
<script>
var a=document.querySelector("#a");
var b=document.getElementById("ok");
a.addEventListener("click",k,false);
var c=document.querySelector("#b");
c.addEventListener("click",g,false);
function k(){
b.style.backgroundColor="yellow";
};
function g(){
b.style.backgroundColor="black";
};
</script>
I think what do you want to do is:
document.querySelector("#a").addEventListener("click", k, false);
function k() {
var a = document.querySelector("#a");
var ok = document.getElementById("ok");
if(ok.style.backgroundColor=="yellow"){
a.innerHTML = "on";
ok.style.backgroundColor = "black";
}
else{
a.innerHTML = "off";
ok.style.backgroundColor = "yellow";
}
};
This your working DEMO.
I'm trying to write a simply image gallery element for a website and I'm having trouble with the code for silly reasons. I've never gotton on with JavaScript and have always found it a headache. I've tried various other image galleries but can't for the life of me get them to actually work correctly either
My current HTML code is like this:
<!DOCTYPE html>
<html>
<head>
<title> Test of slider </title>
<script type="text/javascript" src="slider.js"></script>
</head>
<body>
<div class="slider" id="main">
<img src="#" class="mainImage" />
<div class="sliderImages" style="display: none;">
<img src="companion.jpg"/>
<img src="cookie.jpg" />
<img src="orange.jpg" />
<img src="orangeWhole.jpg" />
</div>
<div class="sliderButtons">
Previous
Next
</div>
</div>
</body>
</html>
with the javascript like this:
this.Slider = new function(){
// Stores the indices for each slider on the page, referenced by their ID's
var indices = {};
var limits = {};
var images = {};
// Call this function after a major DOM change/change of page
this.SetUp = function(){
// obtain the sliders on the page
// TODO restrict to those within body
var sliders = document.getElementsByClassName('slider');
// assign the indices for each slider to 0
for(var i = 0; i < sliders.length; i++){
indices[sliders[i].id] = 0;
var sliderImages = document.getElementsByClassName('sliderImages');
var imagesTemp = sliderImages[0].getElementsByTagName('img');
images[sliders[i].id] = imagesTemp;
limits[sliders[i].id] = imagesTemp.length;
}
}
// advances a certain slider by the given amount (usually 1 or -1)
this.Slide = function(id, additive){
if(indices && id){
indices[id] = indices[id] + additive;
// Check limits
if(indices[id] < 0){
indices[id] = limits[id] - 1;
}
if(indices[id] >= limits[id]){
indices[id] = 0;
}
// alter img to be the new index
document.getElementById(id).getElementsByClassName('mainImage')[0].src = images[id][indices[id]].src;
}
}
}
for(var slider in sliders)
{
// here slider is the index of the array. to get the object use sliders[slider]
}
then you can use 'getElementsByClassName' function
edit
U have included the slider.js on the top of the html. So first it loads the the js and tries to access the elements which are not yet created..Move the tag to the bottom of the page.
sliderImages is an array of divs with classname sliderImages. there is only one that satisfies.
var sliderImages // is a array with 1 item.
// to get the images use sliderImages[0].getElementsByTagName('img');
change
this.Slide = new function(id, additive){
to
this.Slide = function(id, additive){ // otherwise it will be called when the page is loaded with undefined values.
onclick of the link call with quotes
Slider.Slide('main', 1)
You are using a methode I do not know (or you forgot the "s")
var sliderImages = slider.getElementByClassName('sliderImages');
I would use something like the code below. It is important sliderImages will be an array of anything that is of the class "silderImages"
var sliderImages =slider.getElementsByClassName("sliderImages")
I've got a button with an image inside that I want to swap when clicked. I got that part working, but now I also want it to change back to the original image when clicked again.
The code I'm using:
<button onClick="action();">click me<img src="images/image1.png" width="16px" id="ImageButton1"></button>
And the Javascript:
function action() {
swapImage('images/image2.png');
};
var swapImage = function(src) {
document.getElementById("ImageButton1").src = src;
}
Thanks in advance!
While you could use a global variable, you don't need to. When you use setAttribute/getAttribute, you add something that appears as an attrib in the HTML. You also need to be aware that adding a global simply adds the variable to the window or the navigator or the document object (I don't remember which).
You can also add it to the object itself (i.e as a variable that isn't visible if the html is viewed, but is visible if you view the html element as an object in the debugger and look at it's properties.)
Here's two alternatives. 1 stores the alternative image in a way that will cause it to visible in the html, the other doesn't.
<!DOCTYPE html>
<html>
<head>
<script>
function byId(e){return document.getElementById(e);}
window.addEventListener('load', mInit, false);
function mInit()
{
var tgt = byId('ImageButton1');
tgt.secondSource = 'images/image2.png';
}
function byId(e){return document.getElementById(e);}
function action()
{
var tgt = byId('ImageButton1');
var tmp = tgt.src;
tgt.src = tgt.secondSource;
tgt.secondSource = tmp;
};
function action2()
{
var tgt = byId('imgBtn1');
var tmp = tgt.src;
tgt.src = tgt.getAttribute('src2');
tgt.setAttribute('src2', tmp);
}
</script>
<style>
</style>
</head>
<body>
<button onClick="action();">click me<img src="images/image1.png" width="16px" id="ImageButton1"></button>
<br>
<button onClick="action2();">click me<img id='imgBtn1' src="images/image1.png" src2='images/image2.png' width="16px"></button>
</body>
</html>
You need to store the old value in a global variable.
For example:
var globalVarPreviousImgSrc;
var swapImage = function(src)
{
var imgBut = document.getElementById("ImageButton1");
globalVarPreviousImgSrc = imgBut.src;
imgBut.src = src;
}
Then in the action method you can check if it was equal to the old value
function action()
{
if(globalVarPreviousImgSrc != 'images/image2.png')
{
swapImage('images/image2.png');
}else{
swapImage(globalVarPreviousImgSrc);
}
}
It's not a good idea to use global variables in javascripts use a closure or object literal. You can do something like using a closure
(function(){
var clickCounter = 0;
var imgSrc1 = "src to first image";
var imgSrc2 = "src to second image"
functions swapImage (src)
{
var imgBut = document.getElementById("ImageButton1");
imgBut.src = src;
}
function action()
{
if(clickCounter === 1)
{
swapImage(imgSrc1);
--clickCounter;
}else{
swapImage(imgSrc2);
++clickCounter;
}
}
})();
(I haven't run this code though)
This nice w3documentation gives you best practices.
Check this a working example just copy paste and run-
HTML
<button onClick="action();">click me<img src="http://dummyimage.com/200x200/000000/fff.gif&text=Image+1" width="200px" id="ImageButton1"></button>
JAVASCRIPT
<script>
function action()
{
if(document.getElementById("ImageButton1").src == 'http://dummyimage.com/200x200/000000/fff.gif&text=Image+1' )
document.getElementById("ImageButton1").src = 'http://dummyimage.com/200x200/dec4ce/fff.gif&text=Image+2';
else
document.getElementById("ImageButton1").src = 'http://dummyimage.com/200x200/000000/fff.gif&text=Image+1';
}
</script>
Check this working example - http://jsfiddle.net/QVRUG/4/