I'm working on a midterm project for my Intro to Javascript class, and I've got the required part down (an image gallery where you click a thumbnail to change the central image), but I would also like to change the text in a paragraph below the central image (not a requirement of the project, and not something we've been taught in class, but I would like to know how to do it because it would enhance the project) when the thumbnail is clicked.
I've looked at several answers related to this, and they all seem to rely on the manual population of an array, but my paragraph text is going to be rather long so I'd like to automatically populate the array with members of a class (.text), if that's possible. (Or find some other workaround.) We've learned a bit of JQuery but we're not allowed to use it for this project, which is a shame since I'm sure it would be much easier with it. Here's the relevant part of my project:
HTML:
<ul id="gallery">
<li>
<a href="images/charactername.gif" title="Character Name" id="first_link">
<img src="images/thumbs/charactername.png"></a>
<p class="text">Character Information</p>
</li>
<li>
<a href="images/charactername.gif" title="Character Name">
<img src="images/thumbs/charactername.png"/></a>
<p class="text">Character Information</p>
</li>
(several more similar blocks for different characters)
</ul>
<p><img src="images/character.gif" id="image"></p>
<h2 id="caption">Character Name</h2>
<p id="blurb">Large amount of text summarizing character's backstory/traits/etc.</p>
Javascript:
window.onload = function () {
var listNode = $("gallery");
var captionNode = $("caption");
var imageNode = $("image");
var imageLinks = listNode.getElementsByTagName("a");
var i, linkNode, image;
for ( i = 0; i < imageLinks.length; i++ ) {
linkNode = imageLinks[i];
linkNode.onclick = function (evt) {
var link = this; // link is the linkNode
imageNode.src = link.getAttribute("href");
captionNode.firstChild.nodeValue = link.getAttribute("title");
};
};
I can set the Character Name easily using the title, but changing the #blurb text below to match each character's info paragraph onclick is evading me. I feel like if I can find a way to automatically populate the array with the paragraph #text, I should be able to set the text of #blurb to array[i] or something similar, but I'm not sure. I'd vastly appreciate some help. Thank you.
I don't know if this is how you would do it in your class, but I thought I would add an example of how you might do it.
var listNode = document.getElementById('list-node');
var imageLinks = listNode.getElementsByTagName("a");
var i;
var characterText;
for (i = 0; i < imageLinks.length; i += 1) {
// Add a click event listener
imageLinks[i].addEventListener("click", function (evt) {
// Prevent the default functioning
evt.preventDefault();
// Get the character text
characterText = getCharacterText(this.parentNode);
// Update the blurb
document.getElementById('blurb').innerText = characterText;
});
}
/**
* Returns the character text of an item in list-node.
*
* #param parentNode, the list item that contains the character
* description node.
* #return characterText, the text of the character description
*/
function getCharacterText(parentNode) {
return parentNode.getElementsByClassName('text')[0].innerText;
}
JS fiddle, for what it's worth: http://jsfiddle.net/9ekcgeyq/
Related
I have javascript that will open this window, but I need after opening this chat to insert text there and send it. Also would appreciated if you could help me improve my code.
setInterval(function acceptor() {
var btn = document.getElementsByClassName('button green');
for (var i = 0; i < btn.length; i++) {
if (btn[i].innerText.indexOf('Accept') > -1) {
btn[i].click();
console.log('Accepted in to IMs');
}
}
}, 1000);
console.log('Acceptor started');
setInterval(function getnick() {
var cnt = document.getElementsByClassName('notificationsSlider');
for (var j = 0; j < cnt.length; j++) {
if (cnt[j].innerText.indexOf('is now your contact') > -1) {
var nickname = cnt[j].innerText;
var onlynickname = nickname.split(' is now your contact').shift();
console.log(onlynickname);
var contactlist = document.getElementsByClassName('userName');
for (var k = 0; k < contactlist.length; k++) {
if (contactlist[k].innerText.indexOf(onlynickname) > -1) {
contactlist[k].click();
console.log('Opened chat');
}
}
}
}
}, 3500);
console.log('Openner started');
EDIT:
I just found out that it won't be that easy I guess. At first point: I am trying to make JS to accept contact request, open chat wih it and post/send auto message to the accepted contact.
Today I found out that that "text box" - thing where I need to insert my custom auto message text is changing dynamically.
When my code that so far opens the chat with the contact it looks like this. <br data-text="true">
After I insert there some text by myself it changes to this: <span data-text="true">I inserted text here</span>
Could anyone help me out how to write js that will after oppening chat also insert my custome message there?
The question asks how to insert text into a particular span element. Inserting text into an element can be done by the e.g. el.innerHTML='The text';
To do that you first have to find the element. Looking at the screenshot provided it seems as though the span element needed is the only one with a data-text="true". We therefore need to find that.
You ask for suggestions to improve your code. If this bit is your code and you are able to add things to your HTML I would suggest you think about giving elements which are unique and which you want to use unique identifiers. For example:
<span id="datatext"></span>
JavaScript can then find it quite simply:
el=document.getElementById('datatext');
If you aren't in a position to do that then the only way I can think of is to look at all the span elements in the document and find those which have data-text="true"
Here is an example of doing that on a document with a few spans - just one of which has that attribute. (thanks to #Adriani6 for the querySelectorAll information)
<span data-text='false']></span>
<span data-text='true']></span>
<span data-somethingelse='true']></span>
<span data-number='3']></span>
<script>
var spans = document.querySelectorAll("[data-text='true']");
if (spans.length==1) {
console.log('Success I have found the span element required.');
spans[0].innerHTML='The text you want to put in';
}
else {
console.log('Help, there are '+ spans.length + ' span elements with data-text="true" so I do not know where to put the text');
}
</script>
It isn't really possible to be of great help with your Javascript code as there isn't enough information to know exactly what it is trying to do. One thing I noted was that you are simulating clicks (rather than waiting for the user to click) the green buttons and I wonder if that is what you intended - and if it is why you need a seconds pause before doing so? [the OP has clarified that].
I have 3 inputs that are nestled inside a span tag (I'm using span and not li because I have many li's in my code). I have a javascript function that appends each span tag (which includes the 3 inputs). I need each input to have a specific id name. Not sure how to do this, I'm learning javascript right now so forgive me for I'm a noob.
In my function I have the appendchild working for the span tag. At the bottom of the code I have a for loop that I wrote to append an ul/li and that name works. But I can't get that same functionality to work for the span tags.
How can I append child and each time I appendchild that the inputs get a new id name?
Here is my code so far:
function budgetList(){
var elmnt = document.getElementsByTagName("SPAN")[0];
var cln = elmnt.cloneNode(true);
var budgetListing = document.getElementById("budget-listing");
var append = budgetListing.appendChild(cln);
var expenseName = document.getElementById('expenseName');
var expectedExpense = document.getElementById('expectedExpense');
var actualExpense = document.getElementById('actualExpense');
var ul = document.createElement("ul");
document.body.appendChild(li);
for(var i = 0; i <= 0; i++){
var li = document.createElement("li");
li.className = "budget-list" + i;
var a = document.createElement("a");
a.innerHTML = "<input type='text'>";
// a.innerHTML = "Subfile " + i;
var att = document.createAttribute("class");
att.value = "budgeting" + i;
li.appendChild(a);
ul.appendChild(li);
}
}
Here is the html
<button onclick="budgetList()">Add New Row</button>
<input type="button" value="save" onclick="save()" />
<ul id="budget-listing">
<span>
<input type="text" id="expenseName">
<input type="text" id="expectedExpense">
<input type="text" id="actualExpense">
</span>
</ul>
A few things...
1) <ul> stands for Unordered List and <ul> elements expect their children to be <li> elements (which you can remember as List Item). So, while some browsers may be forgiving of you appending spans to your <ul> tag, it's not considered good practice. And is technically a violation of the standard
2) Your loop will only run exactly once. You'll see it's starting with variable i initialized at 0 and will only run as long as i<=0 which will only ever be true on the first iteration because afterwards you increment (i++) which means the second time through i will equal 1 and 1 is NOT less than or equal to 0. So, in this case there's no need to use a loop at all.
3) Your code is a little disjointed from what you requested and what the page context is suggesting. It appears to me, when the user clicks the button you want to duplicate the span with 3 inputs. If this is indeed the case, then I offer the following solution...
function budgetList(){
// You get the span that will serve as a template, good
var elmnt = document.getElementsByTagName("SPAN")[0];
// you clone it, good
var cln = elmnt.cloneNode(true);
//next we want to modify the IDs of the child spans.
// A good way to do this is to use a unique number that will change with every step
// There a few ways to get a unique number each time
// I propose taking the number of span groups
var budgetListing = document.getElementById("budget-listing");
var uniqueNumber = budgetListing.childNodes.length;
// Now we update all the ids using the unique number
cln.getElementsByTagName('INPUT')[0].setAttribute('id', "expenseName_"+uniqueNumber);
cln.getElementsByTagName('INPUT')[1].setAttribute('id', "expectedExpense_"+uniqueNumber);
cln.getElementsByTagName('INPUT')[2].setAttribute('id', "actualExpense_"+uniqueNumber);
// and write our new span group into the container
budgetListing.appendChild(cln);
}
Let me know if I made any incorrect assumptions or if this is close to what you're requesting. JavaScript and its interaction with HTML can be confusing at first, but stick with it!
EDIT: Didn't realize getElementById wasn't a function... Replaced with getElementsByTagName
Say I have something like this:
<p>Here are several words in a sentence.</p>
I'm trying to figure out how to display each word, one by one, via keypress or mouseclick, till it reaches the end.
So for example:
Here (click)
Here are (click)
Here are several , etc.
This may be basic, but I'm not very good and I'd love some help!
Thanks!
I just want to make some interventions on #Dean.DePue answer and make the code so you paste it in your project and does the trick:
Your html should look like this:
<div id="adiv"></div>
And you should add this javascript code too:
var index, newsentence, sentence, words;
sentence = "Here are several words in a sentence";
words = sentence.split(" ");
index = 0;
newsentence = "";
$(document).click(function(e) {
if (e.button === 0 && index < words.length) {
newsentence += words[index];
newsentence += " ";
$("#adiv").html(newsentence);
index = index + 1;
}
});
If you've got any doubt of the code just ask!
This has been turned into a jQuery Plugin: word-reveal.
While the other two answers will work (sort of), they aren't very reusable. What happens when you have more than one container you'd like to reveal with more than one sentence? I created a jQuery plugin that can easily be reused throughout the page.
The Setup
Include jQuery on the page
Download the plugin from GitHub, and include it on the page
You're set and ready to go!
The HTML
Set an id for each div or p tag. An example of multiple uses:
<p id="firstRevealer"></p>
<p id="secondRevealer"></p>
<p id="thirdRevealer"></p>
The jQuery
$(document).ready(function() {
$("#firstRevealer").wordReveal({text:"This reveals one word at a time."});
$("#secondRevealer").wordReveal({text:"Adding more text is easy!"});
$("#thirdRevealer").wordReveal({text:"It <b>also</b> works on <em>some</em> tags, since it splits on <b>spaces</b>!"});
});
The CSS
I added CSS on the example, to make clear where you're clicking to reveal the next word. A different answer registered clicks on the document, but any clicks (for a expandable menu, for example) would add a word.
p {
padding: 10px;
margin:10px;
min-height:25px;
background-color:#BADA55
}
The fiddle.
Note
This can easily be extended to act on other events (keypress).
<script type="text/javascript">
var sentence = "Here are several words in a sentence";
var words = sentence.split(" ");
var index = 0;
var newsentence = "";
function clickit() {
newsentence += sentence[index];
index = index + 1;
}
Sorry in advance for the extremely banal question, I'm positive I am missing something extremely simple. Without further adieu;
I'm getting a type error when I try to pull a block of text, and a button, from a div in my HTML. The div has an id that I am accurately referencing. For oversight, I am attempting to retrieve the text, apply coloring to each word (cycling through red, blue, and green), and replace the original text with my colored text. It works fine in JSFiddle, but I cannot get the data to retrieve in espresso - transcribeText is null.
var transcribeText = document.getElementById("divideTranscript");
transcribeText.onclick = function() {
var words = document.getElementById("transcriptText");
var textArray = words.innerHTML.split(" ");
var count = 0;
var colorArr = ["red", "blue", "green"];
var newWords = document.createElement("div");
for(var i = 0; i < textArray.length; i++){
var item = textArray[i];
var newSpan = document.createElement("span");
var newText = document.createTextNode(item);
var dotNode = document.createTextNode(" ");
newSpan.className = colorArr[count % 3];
newSpan.id = "word"+i;
newSpan.appendChild(newText);
newSpan.appendChild(dotNode);
count++;
};
words.parentNode.replaceChild(newWords, words);
}
<div id="transcriptText"> It’s that time of year when you clean out your
closets, dust off shelves, and spruce up your floors. Once you’ve taken
care of the dust and dirt, what about some digital cleaning? Going
through all your files and computers may seem like a daunting task, but
we found ways to make the process fairly painless.</div>
<br>
<div id="divideTranscript" class="button"> Transform the
Transcript! </div>
Your problem is that the javascript runs before the HTML exists, therefore, you cannot get any ids. There are several ways around this. First is my favorite:
window.onload = function name() {
//code to be excuted
}
The function will be called after HTML has loaded. body.onload = function name() also works.
The second method (no pun intended haha) is to put the script tag at the end of the body tag.
<body>
<script></script>
</body>
Personally, I use the first one more commonly because I have a template I religiously use, and I don't like moving tags around. That's just me, whatever works for you! Hope this Helps!
I have a small question.
For a task we have to make in Javascript I need some help.
We have a text and some words we give an id (html). In javascript we have to make a function that when it's clicked, all the words with the id become invisible. I know, I can do this too. But there's one more thing. If we put the word invisible, it has to become clear there was a word there before! It would look like a fill-in text, if you can understand.
Now I have this:
function toggle_woordjes() {
var e = document.getElementsByClassName('invul');
for(i = 0; i < e.length; i++){
if (e[i].style.display !== ''){
e[i].style.display = '';
}
else {
e[i].style.display = 'block';
}
}
}
The code doesn't work properly anymore because I changed it so much that I can't get back to the original.
I hope you people can help me.
Sorry that my English isn't the best!
Cheers
If the parent's background is only 1 color (no design nor pattern), you may write something like the following.
object.style.backgroundColor="same color as parent"
however if the background is more complex:
function toggle_words() {
var doms = document.getElementsByClassName('class_name');
for (var i = 0; i < doms.length; ++i) {
var domStyle = doms[i].style;
if (domStyle.visibility === 'visible') {
domStyle.visibility = 'hidden';
}
else {
domStyle.visibility = 'visible';
}
}
}
I use visibility instead of display because the elements stay in the DOM, thus the user knows there was something before.
For one thing, I think that you need to make it e[i].style.display = 'none'; rather than empty string in order to make them disappear (and change the test accordingly).
But it sounds like that wasn't your real problem but rather displaying text to indicate that there was an element there. I would suggest having a <div> with class 'invul' that contains 2 other <div> elements: 1 is the text to display if the real content is invisible and the other is the real content. Something like this:
<div class="invul">
<div class="msg">Word was here</div>
<div class="word">I am the real message</div>
</div>
Then make them disappear and reappear as needed.