Using a javascript "random quote" script but across two separate elements - javascript

I'm trying to teach myself a bit of javascript by writing a basic Web site (using Twitter Bootstrap) that presents a random quote from a Project Gutenberg novel, some discussion of it, and then further down the page has a link to go directly to the novel on Project Gutenberg.
I've used this JavaScript Source script to great effect... for the quote itself. But when it comes to linking the second element -- the link to the quoted book -- the text in the button doesn't appear.
The HTML looks something like this:
<div class="childquote">
<p>
<span id="ran1">“Quote from a first novel.”<br>
- Bram Stoker, <em>Dracula</em></span>
<span id="ran2">“Quote from a second novel.”<br>
- Herman Melville, <em>Moby Dick</em></span>
and later down the page, the button HTML looks like this:
<div class="btn pull-right bookbutton">
<span id="ran1">Read the book</span>
<span id="ran2">Read the book</span>
...obviously, all appropriate divs are closed, etc.
The CSS for the page sets display to "none" for all the random options on the page:
#ran1,#ran2,#ran3,#ran4,#ran5,#ran6,#ran7,#ran8,#ran9,#ran10,#ran11,#ran12,#ran13,#ran14,#ran15,#ran16,#ran17,#ran18 {
display:none;
}
And the JavaScript itself looks like this:
function messageLoad() {
var wch=Math.floor(Math.random()*18+1);
document.getElementById('ran'+wch).style.display='inline';
}
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
if (oldonload) {
oldonload();
}
func();
}
}
}
addLoadEvent(function() {
messageLoad();
});
As far as I understand it, because I don't understand JavaScript at all, the JavaScript somehow "deactivates" the "display:none" CSS for a randomly selected "ranXX" so that the first part -- the quote -- will display as though "display:none" was not set for that random number.
But why doesn't this same logic apply on down to the link? I get the random quote just fine, but the button text doesn't appear at all.

The function is called getElementById, so it will only ever return at most one element. In fact, IDs should be unique on a page - that's the concept of IDs.
You could give the link IDs an affix (say, ran1link) so that they are uniquely identifiable, and have both elements set their display to inline.
Note that your window.onload trick is not really necessary. There is addEventListener which can attach multiple functions to an event. That way you never have clashes with other code adding onload functions.

Related

How to change add and remove tags with JS in django template

I have a quiz Django app which consists of two parts. One is showing 10 sentences with their audio to remember, one per page, and the second is asking questions for the same set of sentences. First part was set up with js function which creates pagination in my html the following way:
my_template.html
<button id="prev">prev</button>
<button id="next">next</button>
<ul class="list-articles" id="dd">
</ul>
<script>
var my_objects = `{{ my_objects|safe}}:` #list of items from my view function
function paginate(action) {
console.log(action)
if (action ==='next') {
page_number++;
}
else{
page_number--;
}
const audio = document.createElement('audio');
audio.src =`/media/${my_objects[page_number].fields.audio}`;
$('#dd').empty();
$('#dd').append('<li><h1>'+ my_objects[page_number].fields['content'] +'</h1></li>');
$('#dd').append(audio);
$('#page_number').val(page_number);
}
document.addEventListener('DOMContentLoaded', function() {
document.querySelector('#next').onclick = function() {
paginate('next'); #same goes for 'prev' button.
}
})
</script>
Now when the user paginated through all the sentences I want to show the continue button and if the user clicks it, start the second part. The second part has absolutely same page except I need to hide content of my objects and leave only audio or vice versa and add textarea tag for the user's input. After that I need to loop over my objects again - now in the form of questions. I need to do that without page re-rendering so I don't need to store the list of objects or query the DB again.
I tried to make it with tag disabling and activating the second loop after the first ends but that looks quite messy and I suppose there is a smarter way of doing that. I'm not a JS developer so any help would be appreciated!
Thanks for all who viewed and not commented! I found the answer myself. Just need to add JS functions which will empty the main tag and refill with necessary field.
Details: By accessing elements of DOM in the following way you can empty any element on a web page. For example, if we have a div like:
<div class= id="maindiv">
<h2> Hello, world! </h2>
</div>
We can empty and refill it with a new header:
var container = document.getElementById("maindiv");
container.empty();
new_header = document.createElement('h2');
new_header.innerHTML = 'Hello, brave new world!'
container.append(new_header);
Same applies to the whole web-page. The only thing is, if it is too big, you probably going to be tired of manipulating the DOM each time. So, you may want to check out some frameworks like React to make it easier .

Is there a to change the value of an element using JavaScript

I'm trying to change the value of an element on a third-party web page using a JavaScript Add-on to display a hyperlink
I already have the link on the page i would like to be able to click it
I think I'm on the right track using document.getElementById although I'm not sure how to then change the id into a "a href" and then how to pass it back into the value.
Sorry, this is a bit of a tricky situation so I'll try my best to explain it. On a third-party web-page which we use for our HR related tasks, there is a section titled "File Link" although this isn't a link. When you copy and paste the address into a browser it displays the file. What i am trying to do is create a hyperlink on the "File Link" section to remove the need to copy and paste the link. Because this is a third party website. We have access to the JavaScript on the website and need to change the address into a hyperlink. I'm not entirely sure this is possible.The element id is "__C_cb_file_link" and i would like to insert the link address into the element using a variable then add the link parameters into the variable then reinsert it into the element/value.
function linkIt() {
var intoLink = document.getElementById("__C_cb_file_link");
var hLink = "<a href="+intoLink+"</a>;
intoLink.value = hLink;
}
window.onload = linkIt();
<td><div class="sui-disabled" title="">m-files://view/37FF751C-A23F-4233-BD8B-243834E67731/0-46524?object=C46A7624-D24B-45F3-A301-5117EFC1F674</div>
<input type="hidden" name="__C_cb_file_link" id="__C_cb_file_link" value="m-files://view/37FF751C-A23F-4233-BD8B-243834E67731/0-46524?object=C46A7624-D24B-45F3-A301-5117EFC1F674"/></td></tr>
In below code first we read input value with new link (however we can read this value from other html tags), then we remove this element (and button) and add to parent element (of removed input) the new link
function linkIt() {
let intoLink = __C_cb_file_link.value;
let parent = __C_cb_file_link.parentNode;
__C_cb_file_link.remove();
btn.remove();
parent.innerHTML += `${intoLink}`;
}
<input id="__C_cb_file_link" value="https://example.com">
<button id="btn" onclick="linkIt()">Link It</button>
There are a number of issues with your code:
1) The code snippet in your question doesn't run because of a missing " at the end of the second line of the linkIt() function.
2) intoLink is a hidden field so anything you add to it will not be visible in the page
3) Even if point 2 were not true, setting the value of a form field will not cause HTML to appear on the page (at best you might get some plain text in a textbox).
4) "<a href="+intoLink+"</a>" doesn't work because intoLink is a complex object which represents the entire hidden field element (not just its value property). You can't convert a whole object into a string directly. You need to extract the value of the field.
A better way to do this is by creating a new element for the hyperlink and appending it to the page in a suitable place. Also I recommend not adding your event via onload - when written using this syntax only one onload event can exist in a page at once. Since you're amending another page which isn't under your control you don't want to disable any other load events which might be defined. Use addEventListener instead, which allows multiple handlers to be specified for the same event.
Demo:
function linkIt() {
var intoLink = document.getElementById("__C_cb_file_link");
var hLink = document.createElement("a");
hLink.setAttribute("href", intoLink.value);
hLink.innerHTML = "Click here";
intoLink.insertAdjacentElement('beforebegin', hLink);
}
window.addEventListener('load', linkIt);
<td>
<div class="sui-disabled" title="">m-files://view/37FF751C-A23F-4233-BD8B-243834E67731/0-46524?object=C46A7624-D24B-45F3-A301-5117EFC1F674</div>
<input type="hidden" name="__C_cb_file_link" id="__C_cb_file_link" value="m-files://view/37FF751C-A23F-4233-BD8B-243834E67731/0-46524?object=C46A7624-D24B-45F3-A301-5117EFC1F674" /></td>
</tr>
P.S. m-files:// is not a standard protocol in most browsers, unless some kind of extension has been installed, so even when you turn it into a hyperlink it may not work for everyone.
[UPDATE] I supose that your "__C_cb_file_link" was a paragraph so I get the previous text http://mylink.com and create a link with, is it what you want, right?
function linkIt() {
let fileLink = document.getElementById("__C_cb_file_link");
let hLink = fileLink.textContent;
fileLink.innerHTML = ""+hLink+"";
}
linkIt();
<div>
<p id="__C_cb_file_link">http://myLink.com</p>
</div>

How do I removeAttribute() hidden from p2? doesn't seem to do anything as is

I'm trying to change the attribute of an object with removeAttribute to take away the hidden status of it but so far nothing seems to work.
My code seems to have no effect. Am I doing something wrong?
function changePage() {
document.getElementById.("p2");
p2.removeAtribute.("hidden") ;
}
I've also tried it all on one line as well like so
function changePage() {
document.getElementById.("p2").p2.removeAtribute.("hidden") ;
}
I've never seen the use of dots before opening parentheses.
E.g.
document.getElementById.("p2").p2.removeAtribute.("hidden") should be document.getElementById("p2").removeAtribute("hidden")
(You are also referencing the element by id after you just retrieved it, which is unnecessary.)
Your first example didn't work because you retrieved the element and did nothing with it, then tried to access a p2 variable that wasn't declared. Again, you also have the . before parentheses.
Here's the js example:
function changeVisibility()
{
var p2 = document.getElementById('p2');
switch (p2.style.visibility)
{
case 'hidden':
document.getElementById('p2').style.visibility = 'visible';
break;
case 'visible':
document.getElementById('p2').style.visibility = 'hidden';
break;
}
}
<div id="p2" style="visibility:hidden">
test
</div>
<br />
<button onclick="changeVisibility()">
change visibility with basic js
</button>
And here's the jQuery example:
function changePage()
{
$('#p2').toggle();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="p2" style="display:none">
test
</div>
<br />
<button onclick="changePage()">
change visibility with basic js
</button>
The basic JS version uses the visibility style, and you can see that it doesn't collapse the element, it only makes it invisible.
jQuery has a nice built-in .toggle function that changes the display of the element. If it is hidden, it collapses the element. When the element is displayed, it is re-assigned whatever the display style is for that element. Building that in basic js would take a lot more work, as you are then tracking state (if you want to make the method reusable). You can make jQuery work similarly to the basic js version if you use the css properties, but toggle is quite nice and simple.
Your main issue is that you were mixing the getting of the element with methods that are only available on jQuery objects. I suggest reading the jQuery tutorials for basic accessors, which can get elements by id, class name, etc.

Read more opens 1st one all the time

I've a page with about 10 short articles.
Each of them as a "Read More" button which when pressed displays hidden text
The issues I have at the moment is when I press the "Read More" on any of the 10 button it shows the 1st articles hidden content and not the selected one.
I think I need to set a unique ID to each article.. and the read more button be linked to it.. But I don't know how to set it.
I looked at this but couldn't get it working how to give a div tag a unique id using javascript
var WidgetContentHideDisplay = {
init:function() {
if ($('#content-display-hide').size() == 0) return;
$('.triggerable').click(function(e){
var element_id = $(this).attr('rel');
var element = $('#'+element_id);
element.toggle();
if (element.is(':visible')) {
$('.readmore').hide();
} else {
$('.readmore').show();
}
return false;
});
}
}
var div = documentElemnt("div");
div.id = "div_" + new Date().gettime().toString;
$(document).ready(function(){ WidgetContentHideDisplay.init(); });
OP Edit: Sorry, the original code wasn't in caps. I kept getting errors when trying to post, so I copied the code into Dreamweaver and it made it all caps for some reason.
Instead of selecting the element to toggle with an ID (i.e. $('#'+ELEMENT_ID)) you could setup a class for your item and use the class selection (e.g. $('.DETAILED-ARTICLE)') to select the child (or the brother, etc. depending how you built the HTML page).
In theory each ID should point to a single element but each class can be put to as many elements as you want.
If you're getting errors, read the errors and see what they are. Off of a quick read of your code, here are a couple things I noticed that will probably cause issues:
"documentElemnt" is misspelled, which will render it useless. Also, documentElement is a read-only property, not a function like you're using it.
toString is a function, not a property, without the parentheses (.toString()) it isn't going to function like you want it to.
Run the code, look at the errors in the console, and fix them. That's where you start.

replace content of div with another content

I've been building a list of links, all of which should change the content of a div to another specific content (about 4 lines of stuff: name, website, contact etc.) upon a click.
I found this code:
<script type="text/javascript">
function ReplaceContentInContainer(id,content) {
var container = document.getElementById(id);
container.innerHTML = content;
}
</script>
and used it in such a way:
<li class="pl11">
superlink')">Pomorskie</a>
</li>
And it doesn't work as I expected.
It changes hyperlinks text from 'Pomorskie' to 'superlink'.
The plain text works just fine but I need links.
here's the http://xn--pytyfundamentowe-jyc.pl/projektanci/kontakty-p/ (only two of them show anything)
But after trying all of your recomendations, I think I'd jump to different divs with #links, cause nothing worked with this :/
Thanks a lot for trying, and cheers :)
Just as a completely sideways look at this, I'd suggest avoiding the nesting weirdness / complexity, and reducing the problem down.
Setup the content in a hidden (ie. <div id="replacements">...</div>) Grab the innerHTML from the node you want, and be done with it.
Much easier to get replacement content from non-devs that way too, kinda works great if you're in a team.
// Probably better in a separate helpers.js file.
function replaceContentInContainer(target, source) {
document.getElementById(target).innerHTML = document.getElementById(source).innerHTML;
}
Control it with: (lose that href=javascript: and use onClick, better as an event handler, but for brevity I'll inline it as an onClick attribute here, and use a button.)
<button onClick="replaceContentInContainer('target', 'replace_target')">Replace it</button>
We have our target somewhere in the document.
<div id="target">My content will be replaced</div>
Then the replacement content sits hidden inside a replacements div.
<div id="replacements" style="display:none">
<span id="replace_target">superlink</span>
</div>
Here it is in JSBin
Improve the dynamic nature of this by using Handlebars or another nice JS templating library, but that's an exercise for the OP.
edit: Note, you should also name functions with a leading lowercase letter, and reserve the leading uppercase style for Class names e.g. var mySweetInstance = new MySpecialObject();
The quotes are mismatched! So when you click you are getting a JavaScript error.
The browser sees this string:
href="javascript:ReplaceContentInContainer('wojewodztwo', 'superlink')">Pomorskie<
as:
href="javascript:ReplaceContentInContainer('wojewodztwo', '<a href="
Chnage the " inside to #quot;
<li class="pl11">
Pomorskie
</li>
Example fiddle.
Also note, using the href tag for JavaScript is a BAD practice.
You've got a problem with nested quotes. Take a look in your DOM inspector to see what the HTML parser built from it! (in this demo, for example)
You either need to HTML-escape the quotes inside the attribute as " or ", or convert them to apostrophes and escape them inside the JS string with backslashes:
<a href="j[…]r('wojewodztwo', '<a href="http://address.com">superlink</a>')">…
<a href="j[…]r('wojewodztwo', '<a href=\'http://address.com\'>superlink</a>')">…
See working demos here and here.
Better, you should use a onclick attribute instead of a javascript-pseudo-url:
<a onclick="ReplaceContentInContainer('wojewodztwo', …)">Pomorskie</a>
or even a javascript-registered event handler:
<li class="pl11">
<a id="superlink">Pomorskie</a>
</li>
<script type="text/javascript">
function replaceContentInContainer(id,content) {
var container = document.getElementById(id);
container.innerHTML = content;
}
document.getElementBId("superlink").onclick = function(event) {
replaceContentInContainer('wojewodztwo', 'superlink');
event.prevenDefault();
};
</script>
(demo)

Categories