I would like to know what is wrong in my code.
I'd like to delete all "link" tags if there is within the attribute "rel = "stylesheet"
This is my HTML code
<html>
<head>
<title>teset</title>
<meta charset="utf-8" />
<meta name="description" content="test." />
<meta name="author" content="Me" />
<link rel="author" href="www.mysite.uk" />
<link rel="stylesheet" type="text/css" href="www.mysite.uk/css/style.css />
<link rel="stylesheet" type="text/css" href="www.mysite.uk/css/style2.css />
</head>
<script src = "deleteCSS.js"></script>
<body onload="noCSS()">
<p> test !!</p>
</body>
</html>
This is my JS called "deleteCSS.js"
function noCSS(){
//I save tag "link"
var CSSlink = document.getElementsByTagName("link");
var CSSatt = CSSlink.getAttribute("rel");
for (i=0; i < CSSlink.length; i++){
if (CSSatt[i] == "stylesheet"){
CSSlink[i].remove(); }
}
}
with jquery try this
$("link[rel='stylesheet']").remove();
http://jsfiddle.net/7Fcxx/
function noCSS() {
var links = document.getElementsByTagName("link");
for (var i = links.length - 1; i >= 0; --i) {
if (links[i].rel === "stylesheet") {
links[i].parentNode.removeChild(links[i]);
}
}
}
You have to check the rel attribute of each <link> in the loop;
You can remove them in a reversed order (when you remove links[0], links[1] takes the place of it and when you remove links[1] it actually removes the second one of the rest;
Or you can just use while (links.length) instead, and always remove links[0] (the first one of the rest).
If you want a pure JavaScript implementation:
(function() {
var links = document.getElementsByTagName('link');
for(var i=0; i<links.length; i++) {
links[i].getAttribute('rel') === 'stylesheet' && links[i].remove();
}
})();
Copy this to a file no-css.js and put it at the end of your HTML file.
Your code is not working because getElementsByTagName is returning a NodeList, so calling getAttribute('rel') of it will return an error TypeError: Object #<NodeList> has no method 'getAttribute'. So you have to iterate through all the links (nodes) and if they have the rel attribute set to stylesheet, remove them.
Hope this helps!
This is another JavaScript implementation:
function noCSS(){
var CSSlink = document.getElementsByTagName("link");
for (i=0; i < CSSlink.length; i++ )
{
if (CSSlink[i].getAttribute("rel") === "stylesheet")
{
CSSlink[i--].remove();
}
}
}
Make sure you enter the quotation marks at the end of the href tags like
href="www.mysite.uk/css/style.css"
Related
I'm learning JS and I'm trying to create a web game with javascript. The goal is simple: a flag is displayed at random, and the player must guess the name of the country associated with the flag.
The flag is randomly selected and displayed correctly, but I have a problem with the user interaction. I'd like to display "bad answer" in a <p> and if it's correct, display "good answer" (in a <p>), regenerate a flag and start again, indefinitely. The problem is that I can get the user's answer but i can't compare it to real answer and then display true or false.
I would like to know if someone could explain to me what is wrong and correct me please. Here is my code :
function getRandomInt(max) {
return Math.floor(Math.random() * max);
}
function getVal() {
const inputValue = document.querySelector('input').value;
console.log(inputValue);
}
function getData() {
var json = 'https://cdn.jsdelivr.net/npm/country-flag-emoji-json#2.0.0/dist/index.json'
fetch(json)
.then(data => data.json())
.then(data => {
const randomInt = getRandomInt(data.length);
console.log(data[randomInt]);
var image = document.getElementById("flag");
image.src = data[randomInt].image;
});
if (inputValue != data[randomInt].name.toLowerCase()) {
document.getElementsByClassName('result').class.add("result-false");
document.getElementsByClassName('result').innerHTML = 'Mauvaise Réponse';
} else if (inputValue == data[randomInt].name.toLowerCase()) {
document.getElementsByClassName('result').class.add("result-true");
document.getElementsByClassName('result').innerHTML = 'Bonne Réponse';
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Guess The Flag - </title>
<link rel="stylesheet" href="style.css">
<!-- <script type="text/js" src="app.js"></script> -->
</head>
<body>
<h1>GuessTheFlag</h1>
<div class="flagCanva">
<img id="flag" src="https://cdn.jsdelivr.net/npm/country-flag-emoji-json#2.0.0/dist/images/KH.svg" alt="">
</div>
<input type="text" name="flagName">
<button type="submit" onclick="getVal()">Je valide</button>
<p class="result"></p><br>
<button onclick="getData()">Next</button>
</body>
</html>
The reason is because the scope of inputValue is inside the function getVal only.
So in function getData it doesn't know inputValue.
The scope is the perimeter where the variable is known, it could be globally, local to a function, or at other level. It depends where and how you declare the variable.
It's an important thing to understand in most of the computer langage.
Here's a refactored working version with some comments to help clear things out:
function getRandomInt(max) {
return Math.floor(Math.random() * max);
}
let flag = "Cambodia"; // <= We need a global variable so that it can be set and accessed inside getVal() and getData()
function getVal() {
const inputValue = document.querySelector('input').value;
//>> Move the flag vs input comparison inside the input event handler:
if ( inputValue.toLowerCase() !== flag.toLowerCase()) { // <= Lowercasing both input and flag name to avoid case sensitive comparison failures
// Use `classList` instead of `class` to have access to the add() method
// Use `querySelector` to pick a single element instead of getElementsByClassName which returns a list of elements:
document.querySelector('.result').classList.add("result-false");
document.querySelector('.result').innerHTML = 'Mauvaise Réponse';
// No need for an else if here:
} else {
document.querySelector('.result').classList.add("result-true");
document.querySelector('.result').innerHTML = 'Bonne Réponse';
}
}
// TIP: Ideally the next function should be split into 2 functions:
// 1) fetchData(), runs once to grab the JSON
// 2) getRandomFlag(), runs on 'Next' click to get a random flag
// without re-fetching the JSON.
function getData() {
var json = 'https://cdn.jsdelivr.net/npm/country-flag-emoji-json#2.0.0/dist/index.json'
fetch(json)
.then(data=>data.json())
.then(data=> {
const randomInt = getRandomInt(data.length);
console.log(data[randomInt]);
var image = document.getElementById("flag");
image.src = data[randomInt].image;
flag = data[randomInt].name; // <= Set the value for the newly fetched flag name
});
}
Working demo:
function getRandomInt(max) {
return Math.floor(Math.random() * max);
}
let flag = "Cambodia"; // <= We need a global variable so that it can be set and accessed inside getVal() and getData()
function getVal() {
const inputValue = document.querySelector('input').value;
//>> Move the flag vs input comparison inside the input event handler:
if(inputValue.toLowerCase() != flag.toLowerCase()) {
// Use `classList` instead of `class` to have access to the add() method
// Use `querySelector` to pick a single element instead of getElementsByClassName which returns a list of elements:
document.querySelector('.result').classList.add("result-false");
document.querySelector('.result').innerHTML = 'Mauvaise Réponse';
} else {
document.querySelector('.result').classList.add("result-true");
document.querySelector('.result').innerHTML = 'Bonne Réponse';
}
}
function getData() {
var json = 'https://cdn.jsdelivr.net/npm/country-flag-emoji-json#2.0.0/dist/index.json'
fetch(json)
.then(data=>data.json())
.then(data=> {
const randomInt = getRandomInt(data.length);
console.log(data[randomInt]);
var image = document.getElementById("flag");
image.src = data[randomInt].image;
flag = data[randomInt].name;
});
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Guess The Flag - </title>
<link rel="stylesheet" href="style.css">
<!-- <script type="text/js" src="app.js"></script> -->
</head>
<body>
<h1>GuessTheFlag</h1>
<div class="flagCanva">
<img width="100" id="flag" src="https://cdn.jsdelivr.net/npm/country-flag-emoji-json#2.0.0/dist/images/KH.svg" alt="">
</div>
<input type="text" name="flagName">
<button type="submit" onclick="getVal()">Je valide</button>
<p class="result"></p><br>
<button onclick="getData()">Next</button>
</body>
</html>
There's a lot of refactoring that we can do (e.g. caching the selected elements, cache the json response to avoid re-fetching the data, removing global variables, etc.) to improve the code, but this is just a good start for a functional code.
I'm trying to check paragraphs to see if it contains a certain word (Apple), and if so, add that to a list.
<p>Orange</p>
<p>Grape</p>
<p>Apple</p>
<ul id=ulist>
</ul>
<script>
var i;
var x = document.getElementsByTagName("P");
for (i = 0; i < x.length; i++) {
document.getElementById("ulist").innerHTML = "<li>" + x[i].innerHTML + "<li>";
}
</script>
I'm unsure how to check for words, but first I'm trying to go through each paragraph and add each word to the list, but it's only adding Apple. I don't understand why even though I set i=0.
Expected output:
- Apple
New to Javascript so I'd appreciate if the solution uses simple code even if it's long.
Try this code:
var paragraphs = [...document.getElementsByTagName("P")];
var list = document.getElementById("ulist")
paragraphs.forEach(el => {
if (el.innerText.toLowerCase().includes("apple")) {
var li = document.createElement("LI")
li.innerText = el.innerText
list.appendChild(li)
}
})
<p>Orange</p>
<p>Grape</p>
<p>Apple</p>
<p>Not Apple</p>
<ul id="ulist"></ul>
It checks if each <p> has the word apple in it, and if so, it dynamically adds it to the list.
If you want to check if it's Apple just by itself, use ==, and if you want to make the search case-sensitive, remove the .toLowerCase() and change the word apple to Apple.
If you want to add every element, simply remove the if condition.
You should use += instead of =. Also forgot to close the list element (should be </li>). Also, for better performance you can first generate string for all the items the update the DOM only once.
You can check the text of the current element in each iteration based on which you can create items.
Demo:
<p>Orange</p>
<p>Grape</p>
<p>Apple</p>
<ul id=ulist>
</ul>
<script>
var i;
var x = document.getElementsByTagName("p");
var elString = "";
for (i = 0; i < x.length; i++) {
if(x[i].textContent.toLowerCase().includes('apple')){ // check if text contains the word
elString += "<li>"+x[i].textContent+"</li>";
}
}
document.getElementById("ulist").innerHTML = elString;
</script>
Using Document.querySelectorAll(), NodeList.prototype.forEach(),Document.getElementById(),
,Document.createElement() and RegExp.prototype.test().
const fruits = document.querySelectorAll("p"),
lists = document.getElementById("ulist");
fruits.forEach((fruit) => {
if (/apple/i.test(fruit.textContent)) {
const list = document.createElement("li");
list.textContent = fruit.textContent;
lists.append(list);
}
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Fruits</title>
</head>
<body>
<p>Orange</p>
<p>Grape</p>
<p>Apple</p>
<ul id="ulist"></ul>
</body>
</html>
Does anyone know how to exclude specific links from the random_all javascript generator.
I have an archive blog page with a list of links, where I am creating a random button. However, the random link script below takes ANY links from the page. I would like to exclude a few links so that they wouldn't be included as a possibility in the script ( for instance: my home page, or contact page ... just the blog posts displayed on the page)
http://www.eointhomassharkey.com/tester - page can be found here
<script>
function random_all(){
var myrandom=Math.round(Math.random()*(document.links.length-1))
window.location=document.links[myrandom].href
}
//-->
</script>
Any help is greatly appreciated.
-Eoin Thomas
First, since Math.random() gets a number between 0 and .9 repeating (never 1), you want change that to a logical expression. Then you run a loop... or better yet, make an inArray function. If there aren't too many exclusions then you can use recursion.
//<![CDATA[
/* external.js */
var doc, bod, I, inArray, randLinker, old; // for use on other loads
onload = function(){
if(old)old(); // change old var if using technique on other pages
doc = document; bod = doc.body;
I = function(id){
return doc.getElementById(id);
}
inArray = function(v, a){
for(var i=0,l=a.length; i<l; i++){
if(a[i] === v){
return true;
}
}
return false;
}
randLinker = function(){
var exclude = [].slice.call(arguments), lnx = doc.links;
var randLink = lnx[Math.floor(Math.random()*lnx.length)];
var randHref = randLink.href;
if(randLink === this || inArray(randHref, exclude)){
return randLinker.apply(this, exclude);
}
this.href = randHref;
}
I('frm').onsubmit = function(){
return false;
}
var rand_link = I('rand_link');
rand_link.onclick = function(){
randLinker.call(this, 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Text_formatting', 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions');
}
}
//]]>
/* external.css */
html,body{
padding:0; margin:0;
}
body{
background:#000; overflow-y:scroll;
}
.main{
width:940px; background:#ccc; padding:20px; margin:0 auto;
}
#frm>a{
float:left; clear:left;
}
.cb{
clear:both;
}
<!DOCTYPE html>
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
<head>
<meta http-equiv='content-type' content='text/html;charset=utf-8' />
<meta name='viewport' content='width=device-width' />
<title>Random Link</title>
<link type='text/css' rel='stylesheet' href='external.css' />
<script type='text/javascript' src='external.js'></script>
</head>
<body>
<div class='main'>
<form id='frm' name='frm'>
<a href='https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Loops_and_iteration'>Loops and iteration</a>
<a href='https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions'>Functions</a>
<a href='https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators'>Expressions and Operators</a>
<a href='https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Numbers_and_dates'>Numbers and dates</a>
<a href='https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Text_formatting'>Text formatting</a>
<a href='https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions'>Regular Expressions</a>
<a id='rand_link' href=''>Random Link</a>
</form>
<div class='cb'></div>
</div>
</body>
</html>
Note that randLinker takes any amount of arguments. Every one will be excluded. Make sure to call this function in the context of the random link.
What I would recommend doing is setting up an array of pages / sites that you wish to exclude. Then you can run your code that redirects (or runs console.log() in my example) inside of an if condition that checks that the array does not include the randomly-generated link's href value.
This can be done with the ES6 method includes(). Because you don't want the array to include the value, you simply need to check that includes() returns false.
This can be seen in the following, where the logic will only trigger for StackOverflow and Twitter:
var exclusions = ['http://www.facebook.com/', 'http://www.google.com/']
function random_all() {
var myrandom = Math.round(Math.random() * (document.links.length - 1));
if (!exclusions.includes(document.links[myrandom].href)) {
//window.location = document.links[myrandom].href;
console.log(document.links[myrandom].href);
}
else {
console.log('The random link is on the exclusion list!');
}
}
random_all();
Facebook<br>
Google<br>
StackOverflow<br>
Twitter
Hope this helps! :)
This will filter out all blacklisted links from document.links and then randomize only whitelist:
var blacklist = ["javascript:random_all()", "https://google.com/"];
function random_all(){
var whitelist = Array.from(document.links).filter(item => !blacklist.includes(item.href));
if (whitelist.length === 0) {
alert('No whitelisted links!')
return;
}
// 0<->(whitelist.length-1)
var myrandom=Math.round(Math.random()*(whitelist.length-1))
console.log(whitelist[myrandom].href);
//window.location=whitelist[myrandom].href
}
Google
Stackoverflow
Github
Random
I have index.html file with code:
<DOCUMENT!>
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="utf-8">
<script type="text/javascript" src="js\script.js"></script>
<link rel="stylesheet" type="text/css" href="css\style.css"></link>
<title> mchy i porosty </title>
</head>
<body>
<p id="demo"></p>
</body>
</html>
In the same folder I have folder "js" with file script.js inside. The code inside this file is:
var cars = ["BMW", "Volvo", "Saab", "Ford"];
var text = "";
var i;
for (i = 0; i < cars.length; i++) {
text += cars[i] + "<br>";
}
document.getElementById("demo").innerHTML = "text";
When I open file index.html in Firefox I see blank page.
When I put code from script.js into index.html using script markup and open index.html in Firefox I see list of cars.
Can someone explain me, what did I do wrong?
Looks like you have a syntax error in your javascript path (and your css).
<script type="text/javascript" src="js\script.js"></script>
<link rel="stylesheet" type="text/css" href="css\style.css"></link>
Should be:
<script type="text/javascript" src="js/script.js"></script>
<link rel="stylesheet" type="text/css" href="css/style.css"></link>
You also need to load or fire your function. You can do this with a simple window.onload. What you currently have will only output "text" in your html, so remove the "" from "text" in your function.
window.onload = function(){
var cars = ["BMW", "Volvo", "Saab", "Ford"];
var text = "";
var i;
for (i = 0; i < cars.length; i++) {
text += cars[i] + "<br>";
}
document.getElementById("demo").innerHTML = text;
}
Alternatively, you can load your function in your body tags with <body onLoad="foo();"> and updating the function from window.onload = function() to function foo().
Is it possible to insert/generate <Script> and <Link> tag inside the <Header> using only Javascript or DOM (not JQuery) when the page load or by just including one <Script> tag inside the <Header> and do it from there? And would still allow us to debug it and avoid duplicates if just in case we already added one similar <Script> or <Link> in the <Header>?
For example:
Before
<Header>
<script src="Scripts/Generate.js" type="text/javascript"></script>
</Header>
After
<Header>
<script src="Scripts/Generate.js" type="text/javascript"></script>
<script src="Scripts/Script1.js" type="text/javascript"></script>
<script src="Scripts/Script2.js" type="text/javascript"></script>
<link href="CSS/Css1.css" rel="stylesheet" type="text/css" />
<link href="CSS/Css2.css" rel="stylesheet" type="text/css" />
</Header>
Any advice or answers would help me.
HTML:
<head>
<script src="Scripts/Generate.js"></script>
</head>
Scripts/Generate.js:
if(!document.getElementById('id1')) {
var script = document.createElement('script');
script.id = 'id1';
script.src = 'Scripts/Script1.js';
document.head.appendChild(script);
}
if(!document.getElementById('id2')) {
var link = document.createElement('link');
link.id = 'id2';
link.rel = 'stylesheet';
link.href = 'CSS/Css1.cs';
document.head.appendChild(link);
}
Afterwards, the HTML is:
<head>
<script src="Scripts/Generate.js"></script>
<script id="id1" src="Scripts/Script1.js"></script>
<link id="id2" rel="stylesheet" href="CSS/Css1.cs">
</head>
The easiest way is like this:
> document.head.innerHTML += '<link rel="stylesheet" type="text/css" href="styles.css" />';
I'll presume that "duplicate" means having the same src attribute value. Note that this will only prevent the addition of a duplicate by the script, so it must be run after all other scripts have been added:
function conditionallyAddBySource(tagName, src) {
tagName = tagName.toLowerCase();
var elements = document.getElementsByTagName(tagName);
var propToCheck = {script:'src', link: 'href'}[tagName];
for (var i=0, iLen=elements.length; i<iLen; i++) {
// If find a "matching" element, do nothing
if (elements[i][propToCheck].indexOf(src) != -1) {
return;
}
}
// Otherwise, add an element of the required type
var element = document.createElement(tagName);
element[propToCheck] = src;
document.getElementsByTagName('head')[0].appendChild(element);
}
conditionallyAddBySource('script', 'myJSLib.js');
The new element doesn't have to be added to the head, could just be written immediately using document.write or attached to the body (or any other element that can have child nodes other than the HTML and document element). Link elements probably should be in the head though.
Edit
Determine whether to check src or href depending on whether tagName is script or link.
Using Paul's suggestion of querySelector, you can use:
function conditionallyAddBySource(tagName, src) {
tagName = tagName.toLowerCase();
var propToCheck = {script:'src', link: 'href'}[tagName];
var element = document.querySelector(tagName + '[' + propToCheck + '$="' + src + '"]');
if (!element) {
element = document.createElement(tagName);
element[propToCheck] = src;
document.getElementsByTagName('head')[0].appendChild(element);
}
}
provided querySelector support is avilable (IE 8 in standards mode and higher, dunno about others).