How to change the css file, without editing the html - javascript

I am having a issue where I am able to supposed to change my css file using javascript to edit the "href" attribute. The problem that I am having is that I cannot differentiate when a button is pressed or not. I have 2 buttons one for StyleA and one for StyleB. I am not allowed to edit the html file at all, I am wondering what did I do wrong.
Java Script
"use strict";
window.onload = function() {
let elements = document.getElementsByTagName('button');
document.getElementById('styleA').addEventListener('click', () => {
document.getElementById('styleSheet').setAttribute('href', 'styleA.css');
});
document.getElementById('styleB').addEventListener('click', () => {
document.getElementById('styleSheet').setAttribute('href', 'styleB.css');
});
};
Html
<link id="styleSheet" href="styleA.css" rel="stylesheet" type="text/css">
<!-- ... -->
<form>
<button id="styleA" type="submit">Use styleA</button>
<button id="styleB" type="submit">Use styleB</button>
</form>
My approach is to use the "addEventListener" to know when a button is pressed and accurately change the css file.

Related

JS appendChild() to a <div> in <form>

I am able to avoid the below issue by making my div a direct child of body and appending a select to the div, but am not able to achieve the same results when the div is a child of a form within body (either when appending to the div or to the form).
I am just making a drop-down table (select element) that is added to the web page when the user clicks a button. The drop-down select shows when the div is the direct child of body, but not when it is a child of a form that is a child of body. When the button is clicked using the below method, the dropdown appears for like 0.25s and then the page returns to the original layout. The same occurs when trying to append directly to the form.
<!DOCTYPE html> <!--text_index.html-->
<html>
<head>
<meta charset="UTF-8">
<title>Add Drop Down Menu to HTML w/ JS on Button Click</title>
<link rel="stylesheet" type="text/css" href="test_styles.css">
</head>
<body>
<form id="form-button">
<div id="user-area">
<button id="dropdown-button">Add a dropdown menu!</button><br /><br />
</div>
</form>
<script src="test_script.js"></script>
</body>
</html>
Now the JS is shown below. The console returns no error but the select element does not remain in the browser window.
let materialArray = ['Select Your Material:',
                    'Kryptonite',
                    'Odium',
                    'Quartz'];
let formButton = document.getElementById('form-button');
let divUserArea = document.getElementById('user-area');
let dropdownBtn = document.getElementById('dropdown-button');
/***********************************************************************/
/****BEGIN LOOP W/ BUTTON CLICK AND NAMED FUNCTION****/
//NOTE: YOU CANNOT appendChild() ON A <DIV> INSIDE A <FORM>.
////IF YOU CAN THEN THERE IS SOME LOGIC THAT I AM MISSING.
////YOU CANNOT appendChild() DIRECTLY ON A FORM EITHER.
let newSelect = document.createElement("select");
let newOption = [];
function onClickDropdownBtn () {
    for (let i = 0; i < materialArray.length; i++) {
        newOption[i] = document.createElement("option"); //create the new option for the new HTML select element
        newOption[i].text = materialArray[i]; //add the appropriate text to the new option
        newSelect.add(newOption[i], i); //add the completed option to the HTML select element
    }
divUserArea.appendChild(newSelect); //also tried formButton.appendChild(newSelect); and got same
result
return true;
}
dropdownBtn.addEventListener('click', onClickDropdownBtn);
if (onClickDropdownBtn === false) {
newSelect.style.display = 'hidden';
dropdownBtn.style.display = 'block';
} else {
newSelect.style.display = 'block';
dropdownBtn.style.display = 'hidden';
}
/****END LOOP W/ BUTTON CLICK AND NAMED FUNCTION ****/
Is there a way to append to the div inside the form, or to the form directly?
Thanks!
For gits and shiggles, here is the CSS. Maybe the issue is here?
select {
width: 200px;
height: 25px;
text-align: center;
}
button {
width: 200px;
height: 25px;
text-align: center;
}
When you put a <button> inside a form, the default type is submit, which makes the page "refresh" (that's why you only see your dropdown for a second).
You can either change your button type, like this:
<button type='button' id="dropdown-button">Add a dropdown menu!</button>
Or you can add the event.PreventDefault() in your click function to avoid the form submission, like this:
function onClickDropdownBtn (event) {
for (let i = 0; i < materialArray.length; i++) {
newOption[i] = document.createElement("option"); //create the new option for the new HTML select element
newOption[i].text = materialArray[i]; //add the appropriate text to the new option
newSelect.add(newOption[i], i); //add the completed option to the HTML select element
}
divUserArea.appendChild(newSelect); //also tried formButton.appendChild(newSelect); and got same
event.preventDefault();
return true;
}
That will keep your dropdown component in the page and you can go from there.
Forms have the default behaviour of reloading the page (they evolved in an era before SPAs). Your code works just fine, except that it also reloads the page and you lose the state (in your case, the select element).
Just change onClickDropdownBtn() to
function onClickDropdownBtn (event) {
event.preventDefault()
...
and it should be ready to go!

Toggle hide/show not working on childs div

I have a script that gets data from a Google Sheet and displays it as a webpage - using JS and Tabletop.js.
There are multiple entries in the Sheet thus multiple entries in the webpage. To organise the Data I have a hide/show button. When the button is clicked on the first entry it works. However when the any of the other buttons are clicked it hides or shows the first entries data, not its own!
How do I hide/show each individual entries data? Below is the code I am working with!
I am new to JavaScript - Thanks in advance!
P.S - I struggled writing the Title to the questions!
<link href="../common/cats-copy.css" media="screen" rel="stylesheet" type="text/css" />
</head>
<style>
#add-info {
display: none
}
</style>
<body>
<div class="container">
<h1>Resturants</h1>
<div id="content"></div>
<script id="cat-template" type="text/x-handlebars-template">
<div class="entry">
<h5>{{establishment_name}}</h5>
<h6>Area: {{area}}</h6>
<h6>Cuisine: {{cuisine}}</h6>
<button id="btn" class="button-primary" onclick="myFunction()">Hide</button>
<div id="add-info">
<h6>Address: {{address}}</h6>
<h6>Google Maps: {{google_maps_location}}</h6>
<h6>Opening Times: {{opening_times}}</h6>
<h6>Rating: {{rating}}</h6>
<h6>Added By: {{added_by}}</h6>
<h6>Date Added: {{date_added}}</h6>
</div>
</div>
</script>
</div>
<!-- Don't need jQuery for Tabletop, but using it for this example -->
<script type="text/javascript" src="handlebars.js"></script>
<script type="text/javascript" src="../../src/tabletop.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script type="text/javascript">
var public_spreadsheet_url = 'https://docs.google.com/spreadsheets/d/1h5zYzEcBIA5zUDc9j4BTs8AcJj-21-ykzq6238CnkWc/edit?usp=sharing';
$(document).ready( function() {
Tabletop.init( { key: public_spreadsheet_url,
callback: showInfo,
parseNumbers: true } );
});
function showInfo(data, tabletop) {
var source = $("#cat-template").html();
var template = Handlebars.compile(source);
$.each( tabletop.sheets("food").all(), function(i, food) {
var html = template(food);
$("#content").append(html);
});
}
</script>
<script>
function myFunction() {
var x = document.getElementById("add-info");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
</script>
</body>
</html>
Are all the entries on your page filled from the given template, meaning they are divs with the class entry? If so, I think your issue is the following: Your entry div has a child div with the id="add-info". And when you click the button, your handler function (myFunction()) tries to get a reference to that div via document.getElementById("add-info"); Now, if you have multiple such entries on a page, you will have multiple divs with id="add-info". But the id attribute of an element must be unique in your whole document. See the description of id or that of getElementById().
So the root cause of your problem is that the same id is used multiple times in the document when it shouldn't be. You get the behavior you're seeing because getElementById() just happens to be returning a reference to the first element it finds on the page, regardless of which button you click. But I believe you're in undefined behavior territory at that point.
One way to solve the problem is to somehow give myFunction() information about which button was clicked, while making each div you'd like to manipulate unique so they can be found easier. For instance, you can use the order of the restaurant on your page as its "index", and use that as the id of the div you'd like to hide/show. And you can also pass this index as an argument when you call your click handler:
...
<button id="btn" class="button-primary" onclick="myFunction('{{index}}')">Hide</button>
<div id="{{index}}">
<!-- The rest of the code here... -->
...
... add the index into your template context, so Handlebars can fill in the {{index}} placeholder:
...
$.each( tabletop.sheets("food").all(), function(i, food) {
food.index = i // Give your context its 'index'
var html = template(food);
$("#content").append(html);
});
...
... and then alter your function slightly to use the given argument instead of always looking for the div with id="add-info":
function myFunction(indexToToggle) {
var x = document.getElementById(indexToToggle);
// rest of the code is same
With this approach, I expect your DOM to end up with divs that have ids that are just numbers ("3", "4", etc.) and your click handler should get called with those as arguments as well.
Also note that your <button> element has id="btn". If you repeat that template on your page, you will have multiple <button>s with the same id. If you start trying to get references to your buttons via id you will have similar issues with them too since the ids won't be unique.

how to recode my jquery/javascript function to be more generic and not require unique identifiers?

I've created a function that works great but it causes me to have a lot more messy html code where I have to initialize it. I would like to see if I can make it more generic where when an object is clicked, the javascript/jquery grabs the href and executes the rest of the function without the need for a unique ID on each object that's clicked.
code that works currently:
<script type="text/javascript">
function linkPrepend(element){
var divelement = document.getElementById(element);
var href=$(divelement).attr('href');
$.get(href,function (hdisplayed) {
$("#content").empty()
.prepend(hdisplayed);
});
}
</script>
html:
<button id="test1" href="page1.html" onclick="linkPrepend('test1')">testButton1</button>
<button id="test2" href="page2.html" onclick="linkPrepend('test2')">testButton1</button>
<!-- when clicking the button, it fills the div 'content' with the URL's html -->
<div id="content"></div>
I'd like to end up having html that looks something like this:
<button href="page1.html" onclick="linkPrepend()">testButton1</button>
<button href="page2.html" onclick="linkPrepend()">testButton1</button>
<!-- when clicking the button, it fills the div 'content' with the URL's html -->
<div id="content"></div>
If there is even a simpler way of doing it please do tell. Maybe there could be a more generic way where the javascript/jquery is using an event handler and listening for a click request? Then I wouldn't even need a onclick html markup?
I would prefer if we could use pure jquery if possible.
I would suggest setting up the click event in JavaScript (during onload or onready) instead of in your markup. Put a common class on the buttons you want to apply this click event to. For example:
<button class="prepend-btn" href="page2.html">testButton1</button>
<script>
$(document).ready(function() {
//Specify click event handler for every element containing the ".prepend-btn" class
$(".prepend-btn").click(function() {
var href = $(this).attr('href'); //this references the element that was clicked
$.get(href, function (hdisplayed) {
$("#content").empty().prepend(hdisplayed);
});
});
});
</script>
You can pass this instead of an ID.
<button data-href="page2.html" onclick="linkPrepend(this)">testButton1</button>
and then use
function linkPrepend(element) {
var href = $(this).data('href');
$.get(href, function (hdisplayed) {
$("#content").empty().prepend(hdisplayed);
});
}
NOTE: You might have noticed that I changed href to data-href. This is because href is an invalid attribute for button so you should be using the HTML 5 data-* attributes.
But if you are using jQuery you should leave aside inline click handlers and use the jQuery handlers
<button data-href="page2.html">testButton1</button>
$(function () {
$('#someparent button').click(function () {
var href = $(this).data('href');
$.get(href, function (hdisplayed) {
$("#content").empty().prepend(hdisplayed);
});
});
});
$('#someparent button') here you can use CSS selectors to find the right buttons, or you can append an extra class to them.
href is not a valid attribute for the button element. You can instead use the data attribute to store custom properties. Your markup could then look like this
<button data-href="page1.html">Test Button 1</button>
<button data-href="page2.html">Test Button 1</button>
<div id="content">
</div>
From there you can use the Has Attribute selector to get all the buttons that have the data-href attribute. jQuery has a function called .load() that will get content and load it into a target for you. So your script will look like
$('button[data-href]').on('click',function(){
$('#content').load($(this).data('href'));
});
looking over the other responses this kinda combines them.
<button data-href="page2.html" class="show">testButton1</button>
<li data-href="page1.html" class="show"></li>
class gives you ability to put this specific javascript function on whatever you choose.
$(".show").click( function(){
var href = $(this).attr("data-href");
$.get(href,function (hdisplayed) {
$("#content").html( hdisplayed );
});
});
This is easily accomplished with some jQuery:
$("button.prepend").click( function(){
var href = $(this).attr("href");
$.get(href,function (hdisplayed) {
$("#content").html( hdisplayed );
});
});
And small HTML modifications (adding prepend class):
<button href="page1.html" class="prepend">testButton1</button>
<button href="page2.html" class="prepend">testButton2</button>
<div id="content"></div>
HTML code
<button href="page1.html" class="showContent">testButton1</button>
<button href="page2.html"class="showContent">testButton1</button>
<!-- when clicking the button, it fills the div 'content' with the URL's html -->
<div id="content"></div>
JS code
<script type="text/javascript">
$('.showContent').click(function(){
var $this = $(this),
$href = $this.attr('href');
$.get($href,function (hdisplayed) {
$("#content").empty().prepend(hdisplayed);
});
}
});
</script>
Hope it helps.

Could an html editor insert jQuery elements?

I've been playing with making an html editor with javascript functions:
So I have a very basic editor with a "bold" button which with I can make whatever text is selected bold, this is fine (I also have a number of other buttons too, but for simplicity and shortness of code I've missed them all out)
<head>
<script>
var editorDoc;
function InitEditable () {
var editor = document.getElementById ("editor");
editorDoc = editor.contentWindow.document;
var editorBody = editorDoc.body;
if ('contentEditable' in editorBody) {
editorBody.contentEditable = true;
}
else {
if ('designMode' in editorDoc) {
editorDoc.designMode = "on";
}
}
}
function ToggleBold () {
editorDoc.execCommand ('bold', false, null);
}
</script>
</head>
<body onload="InitEditable ();">
<button type="button" onclick="ToggleBold ();">Bold</button>
<iframe contenteditable="true" id="editor"></iframe>
</body>
However, something I was really interested in being able to implement would be adding a button which could insert, say, an accordion when pressed
This would then have to add other bits of script (I imagine) to be able to run each accordion (if you had more than one)
Although I haven't had much of a go at doing this myself yet, I was hoping to get a little insight into whether or not it's possible before starting

Link not showing in dropbox chooser app

I'm struggling trying to get a link to pop up in in the Dropbox chooser drop-in app. I'm using the javascript method and inserting into an html page. The dropbox chooser button shows up, and I'm able to select a file from the dropbox pop-up window, but the result is just a green checkmark and NO link like in the demo (I've tried both the direct and preview method). I've been struggling with this for a few hours. Anyone see anything wrong, or have a good code snipeet they want to share?
Here's my code:
<script type="text/javascript" src="https://www.dropbox.com/static/api/1/dropins.js" id="dropboxjs" data-app-key="XXXXXX"></script>
<!-- Replace data-app-key with yours --> <script type="text/javascript">
// add an event listener to a Chooser button
document.getElementById("db-chooser").addEventListener("DbxChooserSuccess",
function(e) {
alert("Here's the chosen file: " + e.files[0].link)
window.location.href = 'e.files[0].link';
}, false);
</script>
<input data-link-type="direct" id="db-chooser" name="selected-file" type="dropbox-chooser" />
<div id="link-div" style="display: none">Link:</div>
<script type="text/javascript">
document.getElementById("db-chooser").addEventListener("DbxChooserSuccess",
function(e) {
var link = document.getElementById("link");
link.textContent = link.href = e.files[0].link;
document.getElementById("link-div").style.display = "block";
}, false);
</script>
I see two issues in the above code.
The first script references db-chooser before it's actually on the page, so that may not be working at all.
The second script looks for an element called link, but I think you mean link-div.
Finally, you might want to update to the latest version of dropins.js, just because it's the latest. :-) The input tag version has gone away, and instead you can use createChooseButton. Here's a complete working example using the latest version:
<!doctype html>
<html>
<head>
<script src="https://www.dropbox.com/static/api/2/dropins.js" id="dropboxjs" data-app-key="XXXXXX"></script>
</head>
<body>
<div id="container"></div>
<a id="link"></a>
<script>
var button = Dropbox.createChooseButton({
success: function(files) {
var linkTag = document.getElementById('link');
linkTag.href = files[0].link;
linkTag.textContent = files[0].link;
},
linkType: 'direct'
});
document.getElementById('container').appendChild(button);
</script>
</body>
</html>

Categories

Resources