How to reload a page only once is javascript - javascript

The code detects a click outside an element and reloads the page. However, anytime a user clicks outside the page it keeps on reloading the page. How can I reload the page once when the user clicks outside the element?
The reason I want to do this is so when a user inputs text into a form and clicks away the other forms can be rendered with the updated contents. It wouldn't be ideal for the user to click outside the element and the page constantly reloading.
document.addEventListener("click", (evt) => {
const flyoutElement = document.getElementById("flyout-example");
let targetElement = evt.target; // clicked element
do {
if (targetElement == flyoutElement) {
// This is a click inside. Do nothing, just return.
document.getElementById("flyout-debug").textContent = "Clicked inside!";
return;
}
// Go up the DOM
targetElement = targetElement.parentNode;
} while (targetElement);
// This is a click outside.
document.getElementById("flyout-debug").textContent = "Clicked outside!";
location.reload();
});
body {
font-family: "Arial", sans-serif;
}
h6 {
margin: 0;
font-size: .85rem;
font-weight: normal;
color: #999;
}
.flyout {
position: absolute;
top: 50px;
left: 50px;
padding: 1em;
border: 1px solid rgba(16, 152, 173, .3);
background: white;
box-shadow: 0 .1rem .2rem rgba(0, 0, 0, .15);
}
.flyout-title {
font-size: 1em;
margin: 0 0 .5em 0;
}
.flyout-debug {
min-height: 1.5em;
margin: 0 0 .5em 0;
font-size: .8em;
color: #999;
}
.flyout-buttons {
text-align: center;
}
.button {
display: inline-block;
box-sizing: border-box;
margin: 0 .25em;
padding: .5em 1em;
border: .075rem solid rgba(0, 0, 0, .1);
border-radius: .15em;
background-color: #1098ad;
background-image: linear-gradient(rgba(255, 255, 255, .2), rgba(255, 255, 255, 0));
color: white;
text-decoration: none;
font-family: inherit;
font-size: inherit;
line-height: 1;
box-shadow:
0 .075rem .1rem rgba(0, 0, 0, .15),
inset 0 .075rem rgba(255, 255, 255, .3);
}
.button:hover,
.button:focus {
border-color: rgba(0, 0, 0, .5);
background-image: linear-gradient(rgba(255, 255, 255, .1), rgba(0, 0, 0, .1));
}
.button:active {
background-image: linear-gradient(rgba(0, 0, 0, .1), rgba(0, 0, 0, 0));
box-shadow:
inset 0 .075rem .1rem rgba(0, 0, 0, .2);
}
.button-outline {
background-color: transparent;
background-image: none;
border-color: #1098ad;
color: #1098ad;
box-shadow: none;
}
.button-outline:hover,
.button-outline:focus {
background-color: #1098ad;
background-image: none;
color: white;
}
<div class="flyout" id="flyout-example">
<h5 class="flyout-title">This could be a flyout…</h5>
<div class="flyout-debug" id="flyout-debug"></div>
<div class="flyout-buttons">
<button class="button button-outline" type="button">Cancel</button>
<button class="button" type="button">Ok</button>
</div>
</div>

You can use session storage & add a key to maintain if the page was reloaded before.If the key exist in session storage,it mean it was loaded before. If not then add a key a reload it
document.addEventListener("click", (evt) => {
const flyoutElement = document.getElementById("flyout-example");
let targetElement = evt.target; // clicked element
do {
if (targetElement == flyoutElement) {
// This is a click inside. Do nothing, just return.
document.getElementById("flyout-debug").textContent = "Clicked inside!";
return;
}
// Go up the DOM
targetElement = targetElement.parentNode;
} while (targetElement);
// This is a click outside.
yee = document.getElementById("flyout-debug").textContent = "Clicked outside!";
const getIsFirstClick = sessionStorage.getItem('firstClick'); // change from here
if (!getIsFirstClick) {
sessionStorage.setItem('firstClick', true)
location.reload()
}
});

I'm not sure exactly what you're trying to do, but what I understood is that when you click within an area you don't want to reload, but if you click any outside, reload should happen, correct me if I'm wrong. Here's a script to do it:
document.addEventListener("click", (evt) => {
const flyoutElement = "flyout-example";
const targetElement = evt.target; // clicked element
if (targetElement.id === flyoutElement) {
// This is a click inside. Do nothing, just return.
document.getElementById(flyoutElement).textContent = "Clicked inside!";
} else {
// This is a click outside.
document.getElementById(flyoutElement).textContent = "Clicked outside!";
const isReloaded = localStorage.getItem('reloaded');
if (!isReloaded) {
localStorage.setItem('reloaded', true);
location.reload();
}
}
});

Related

Show the data and loader inside carousel

Before appending the loader to my page carousel works fine. But after adding loader to my page data not appending in the carousel. It appends after carousel. I want to show data inside carousel. I have tried but have not been able to figure out the problems. In this code, I am not fetching the data from the server but I have hard-coded data which is showing using local storage.
let movieData = JSON.parse(localStorage.getItem("movies"));
//console.log(movieData)
function sortLH() {
let data = JSON.parse(localStorage.getItem('movies'));
sort_data = data.sort(function(a, b) {
return a.rating - b.rating;
});
displayDOM(sort_data);
console.log(sort_data);
}
function sortHL() {
let data = JSON.parse(localStorage.getItem('movies'));
sort_data = data.sort(function(a, b) {
return b.rating - a.rating;
});
displayDOM(sort_data);
}
function displayDOM(data) {
let parent = document.querySelector('.carousel');
parent.innerHTML = null;
data.forEach(function(el) {
let container = document.createElement("div");
container.className = "carousel-cell";
let poster = document.createElement("img");
poster.src = el.poster;
let name = document.createElement("p");
name.innerText = `Movie: ${el.name}`;
let release = document.createElement("p");
release.innerText = `Year: ${el.release_Date}`;
let rating = document.createElement("p");
rating.innerText = `Rating: ${el.rating}`;
container.append(poster, name, release, rating)
parent.append(container);
});
}
////Loader/////
getme_dataPromise = new Promise(function(resolve, reject) {
setTimeout(function() {
let data = movieData;
if (data != null) {
resolve(data);
} else {
reject(`ERR: Server could not get your data`);
}
}, 5000);
});
//console.log(getme_dataPromise)
getme_dataPromise.then(function(res) {
displayDOM(res);
}).catch(function(err) {
console.log('err:', err);
});
* {
box-sizing: border-box;
}
div>img {
display: block;
margin: auto;
margin-left: 20%;
}
/* changes seen after refresh */
body {
font-family: sans-serif;
background: #0c111b;
}
.carousel {
/* background: #0c111b; */
width: 95%;
margin: auto;
margin-top: 49px;
padding: 8px 8px;
}
.carousel-cell {
width: 24%;
height: 500px;
margin-right: 80px;
margin-bottom: 40px;
/* border: 2px solid red; */
border-radius: 5px;
box-shadow: rgba(0, 0, 0, 0.25) 0px 54px 55px, rgba(0, 0, 0, 0.12) 0px -12px 30px, rgba(0, 0, 0, 0.12) 0px 4px 6px, rgba(0, 0, 0, 0.17) 0px 12px 13px, rgba(0, 0, 0, 0.09) 0px -3px 5px;
}
.flickity-page-dots {
display: none;
}
/* cell number */
.carousel-cell>img {
height: 80%;
width: 100%;
border-radius: 5px;
}
.carousel-cell>p {
color: #fff;
font-size: 0.8em;
text-align: center;
}
<link rel="stylesheet" href="./body-carousel.css">
<link rel="stylesheet" href="https://unpkg.com/flickity#2/dist/flickity.min.css">
<body>
<button onclick="sortLH()">Low to High</button>
<button onclick="sortHL()">High to low</button>
<div class="carousel" data-flickity='{ "cellAlign": "left", "contain": true }'>
<!-- gif image for loader -->
<img src="./uxplanet.gif" alt="gif">
</div>
</body>
<script src="./data.js"></script>
<script src="./body.js"></script>
<script src="https://unpkg.com/flickity#2/dist/flickity.pkgd.min.js"></script>
Why are you calling same function three times?
1.displayDOM(sort_data);inside SortLH()
2.displayDOM(res); inside .then
3.displayDOM(sort_data); inside SortHL().
i am calling the function that generates our html one time only that is inside my .then
I am just mimicking the data with an array of objects & checked cells are appended inside .carousel.
Update:Added Loading Animation Before Promise is Resolved or Timeout
Duration.
The svg will be generated(length of movieData)times.fore.g in this
case we have 2 movies so there are two loading circles.
I don't think there is any other issue. feel free to respond if you think otherwise
/*let svg = `<svg version="1.1" id="L9" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 100 100" enable-background="new 0 0 0 0" xml:space="preserve">
<path fill="#e72f2f" d="M73,50c0-12.7-10.3-23-23-23S27,37.3,27,50 M30.9,50c0-10.5,8.5-19.1,19.1-19.1S69.1,39.5,69.1,50">
<animateTransform
attributeName="transform"
attributeType="XML"
type="rotate"
dur="1s"
from="0 50 50"
to="360 50 50"
repeatCount="indefinite" />
</path>
</svg>`;*/
let movieData = [{
name: "CuttPutlli",
release_Date: "2022",
rating: "5.9/10 ImDb",
poster: "https://img1.hotstarext.com/image/upload/f_auto,t_web_vl_3x/sources/r1/cms/prod/6531/1326531-v-e6302c49fcd9"
},
{
name: "Thor:Love & Thunder",
release_Date: "2022",
rating: "6.5/10 ImDb",
poster: "https://img1.hotstarext.com/image/upload/f_auto,t_web_vl_3x/sources/r1/cms/prod/8317/1328317-v-56412010beba"
}
];
const getme_dataPromise = new Promise(function(resolve, reject) {
/*let parent = document.querySelector(".carousel");
let i = 0;
while (i < movieData.length) {
parent.innerHTML += svg;
i++
}*/
setTimeout(function() {
let data = movieData;
if (data != null) {
resolve(data);
} else {
reject(`ERR: Server could not get your data`);
}
}, 2000);
});
//console.log(getme_dataPromise)
getme_dataPromise
.then(function(res) {
displayDOM(res); //<--------------------Calling The DisplayDom Fuction.
})
.catch(function(err) {
console.log("err:", err);
});
function displayDOM(data) {
let parent = document.querySelector(".carousel");
/*parent.innerHTML = "";*/
data.forEach(function(el) {
let container = document.createElement("div");
container.className = "carousel-cell";
let poster = document.createElement("img");
poster.src = el.poster;
let name = document.createElement("p");
name.innerText = `Movie: ${el.name}`;
let release = document.createElement("p");
release.innerText = `Year: ${el.release_Date}`;
let rating = document.createElement("p");
rating.innerText = `Rating: ${el.rating}`;
container.append(poster, name, release, rating);
parent.append(container);
});
}
* {
box-sizing: border-box;
}
/* changes seen after refresh */
body {
font-family: sans-serif;
background: #0c111b;
}
.carousel {
/* background: #0c111b; */
width: 95%;
margin: auto;
margin-top: 49px;
padding: 8px 8px;
}
.carousel-cell {
width: min-content;
/*let it take the size of the image*/
/*height: 500ox; let it take the space it needs*/
margin-right: 80px;
margin-bottom: 40px;
/* border: 2px solid red; */
border-radius: 5px;
box-shadow: rgba(0, 0, 0, 0.25) 0px 54px 55px, rgba(0, 0, 0, 0.12) 0px -12px 30px, rgba(0, 0, 0, 0.12) 0px 4px 6px, rgba(0, 0, 0, 0.17) 0px 12px 13px, rgba(0, 0, 0, 0.09) 0px -3px 5px;
}
.flickity-page-dots {
display: none;
}
/* cell number */
.carousel-cell>img {
height: 60%;
/*width: 100%; change only one of height or width to maintaint the aspect ratio*/
border-radius: 5px;
}
.carousel-cell>p {
color: #fff;
font-size: 0.8em;
text-align: center;
}
svg {
width: 200px;
height: 200px;
margin-bottom: 100px;
display: block;
}
<link rel="stylesheet" href="https://unpkg.com/flickity#2/dist/flickity.min.css">
<div class="carousel" data-flickity='{ "cellAlign": "left", "contain": true }'></div>
<script src="https://unpkg.com/flickity#2/dist/flickity.pkgd.min.js"></script>

First click is not working in javascript for manipulating DOM elements

I am working on one JavaScript project, where I need to toggle between Dark and Light mode.
The HTML is here.
var btnToggle = document.getElementById("btn-toggle")
var btnToggleIcon = document.getElementById("btn-toggle-icon")
var isDark = true;
btnToggleIcon.addEventListener("click", () => {
if (isDark) {
console.log(btnToggle.style)
btnToggle.style.justifyContent = "flex-start";
isDark = false;
document.documentElement.style.setProperty('--color1', '#10111f');
document.documentElement.style.setProperty('--bg1', 'linear-gradient(145deg, #111221, #0e0f1c)');
document.documentElement.style.setProperty('--color5', '#f1f1f3');
document.documentElement.style.setProperty('--bs', '9px 9px 23px #0f111a, -9px -9px 20px #1a1b32');
document.getElementById("toggle-img").src = "https://img.icons8.com/ios/2x/moon-man.png"
} else {
console.log(btnToggle.style)
btnToggle.style.justifyContent = "flex-end";
isDark = true;
document.documentElement.style.setProperty('--color1', '#f1f1f3');
document.documentElement.style.setProperty('--bg1', '#f1f1f3');
document.documentElement.style.setProperty('--color5', '#10111f');
document.documentElement.style.setProperty('--bs', '20px 20px 60px #bebebe,20px 20px 60px #ffffff');
document.getElementById("toggle-img").src = "https://img.icons8.com/fluent-systems-regular/2x/sun.png"
}
})
:root {
--color1: #10111f;
--color2: #6c6c76;
--color3: #265385;
--color4: #6bc3ff;
--color5: #f1f1f3;
--bg1: linear-gradient(145deg, #111221, #0e0f1c);
--bs: 9px 9px 23px #0f111a, -9px -9px 23px #1a1b32;
}
.keyboard {
width: 80vw;
height: 52vh;
background-color: var(--color1);
position: absolute;
left: 10vw;
right: 10vw;
bottom: 5%;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
padding: 10px;
}
.btn {
color: var(--color5);
font-size: 1.3rem;
cursor: pointer;
border-radius: 8px;
background: var(--bg1);
box-shadow: var(--bs);
padding: 1rem 1.8rem;
transition: all 0.2s ease;
}
<div class="btn-toggle" id="btn-toggle">
<div class="btn-toggle-icon" id="btn-toggle-icon">
<img id="toggle-img" src="https://img.icons8.com/ios/2x/moon-man.png" alt="" />
</div>
</div>
When I click first time on icon but nothing gets changed. But after first click on every click code's running perfectly well.
So please solve this error.
you misinterpret the state, your if(isDark) check the previous state.
i.e. if isDark == true then you should change icon to sun
var btnToggle = document.getElementById("btn-toggle")
var btnToggleIcon = document.getElementById("btn-toggle-icon")
var isDark = true;
btnToggleIcon.addEventListener("click", () => {
if (isDark) {
isDark = false;
//at this point it's not dark
document.getElementById("toggle-img").src = "https://img.icons8.com/fluent-systems-regular/2x/sun.png"
} else {
isDark = true;
//at this point it's dark
document.getElementById("toggle-img").src = "https://img.icons8.com/ios/2x/moon-man.png"
}
})
<div class="btn-toggle" id="btn-toggle">
<div class="btn-toggle-icon" id="btn-toggle-icon">
<img id="toggle-img" src="https://img.icons8.com/ios/2x/moon-man.png" alt="" />
</div>
</div>
Your logic is wrong.
You need to change the variable before the check.
btnToggleIcon.addEventListener("click", () => {
isDark = !isDark;
if (isDark) {
console.log(btnToggle.style)
btnToggle.style.justifyContent = "flex-start";
document.documentElement.style.setProperty('--color1', '#10111f');
document.documentElement.style.setProperty('--bg1', 'linear-gradient(145deg, #111221, #0e0f1c)');
document.documentElement.style.setProperty('--color5', '#f1f1f3');
document.documentElement.style.setProperty('--bs', '9px 9px 23px #0f111a, -9px -9px 20px #1a1b32');
document.getElementById("toggle-img").src = "https://img.icons8.com/ios/2x/moon-man.png"
} else {
console.log(btnToggle.style)
btnToggle.style.justifyContent = "flex-end";
document.documentElement.style.setProperty('--color1', '#f1f1f3');
document.documentElement.style.setProperty('--bg1', '#f1f1f3');
document.documentElement.style.setProperty('--color5', '#10111f');
document.documentElement.style.setProperty('--bs', '20px 20px 60px #bebebe,20px 20px 60px #ffffff');
document.getElementById("toggle-img").src = "https://img.icons8.com/fluent-systems-regular/2x/sun.png"
}
})

Dynamic generated button style class not working

I have 40 dynamically generated buttons that have a class attribute of 'line', the issue is that the style from the line class is not styling the 40 buttons as it is the three buttons that are not dynamically generated. I can see in chrome developer "line" is applied to all 40 buttons.
javascript:
let buttons = [];
const CLS = ["thin", "button"];
let add_btns = document.querySelector('.add-btn');
add_btns.addEventListener("click", function() {
let i = 0;
while (i <= 40) {
let btn = document.createElement("BUTTON");
buttons.push(document.body.appendChild(btn));
i++;
for (let button in buttons) {
btn.setAttribute('id', "button " + button);
btn.classList.add(...CLS);
btn.innerHTML = "Button # " + button;
}
btn.addEventListener("click", function() {
let id = this.id;
alert("my id is: " + id);
});
}
});
css:
html h1,
body h1 {
margin-top: -5rem;
text-align: center;
color: #41403E;
font-size: 3rem;
}
html section,
body section {
display: flex;
flex-direction: row;
justify-content: center;
margin-bottom: 3rem;
}
html section button,
body section button {
align-self: center;
background: transparent;
padding: 1rem 1rem;
margin: 0 1rem;
transition: all .5s ease;
color: #41403E;
font-size: 2rem;
letter-spacing: 1px;
outline: none;
box-shadow: 20px 38px 34px -26px rgba(0, 0, 0, 0.2);
border-radius: 255px 15px 225px 15px/15px 225px 15px 255px;
}
html section button:hover,
body section button:hover {
box-shadow: 2px 8px 4px -6px rgba(0, 0, 0, 0.3);
}
html section button.dotted,
body section button.dotted.thick {
border: dotted 5px #41403E;
}
html section button.thin,
body section button.lined.thin {
border: solid 2px #41403E;
}
I think you're not appending the buttons to your section element. From your CSS, the styles you want will only apply to buttons in the section element. But you're appending the dynamically created buttons to the document body instead.
Try giving your section element an id, reference it, and then append the dynamically created buttons to it.
Something like this should work:
let buttons = [];
let section = document.getElementById("section");
const CLS = ["thin", "button"];
let add_btns = document.querySelector('.add-btn');
add_btns.addEventListener("click", function() {
let i = 0;
while (i <= 40) {
let btn = document.createElement("BUTTON");
buttons.push(section.appendChild(btn));
i++;
for (let button in buttons) {
btn.setAttribute('id', "button " + button);
btn.classList.add(...CLS);
btn.innerHTML = "Button # " + button;
}
btn.addEventListener("click", function() {
let id = this.id;
alert("my id is: " + id);
});
}
});
html h1,
body h1 {
margin-top: -5rem;
text-align: center;
color: #41403E;
font-size: 3rem;
}
html section,
body section {
display: flex;
flex-direction: row;
justify-content: center;
margin-bottom: 3rem;
}
html section button,
body section button {
align-self: center;
background: transparent;
padding: 1rem 1rem;
margin: 0 1rem;
transition: all .5s ease;
color: #41403E;
font-size: 2rem;
letter-spacing: 1px;
outline: none;
box-shadow: 20px 38px 34px -26px rgba(0, 0, 0, 0.2);
border-radius: 255px 15px 225px 15px/15px 225px 15px 255px;
}
html section button:hover,
body section button:hover {
box-shadow: 2px 8px 4px -6px rgba(0, 0, 0, 0.3);
}
html section button.dotted,
body section button.dotted.thick {
border: dotted 5px #41403E;
}
html section button.thin,
body section button.lined.thin {
border: solid 2px #41403E;
}
<section id="section">
<button class="add-btn">
Button
</button>
</section>
As you can see from the example. The selectors work when dynamically generatred. I believe you have a problem with nested selectors in the css.
let buttons = [];
const CLS = ["thin", "button"];
let add_btns = document.querySelector('.add-btn');
add_btns.addEventListener("click", function () {
let i = 0;
while (i <= 40) {
let btn = document.createElement("BUTTON");
buttons.push(document.body.appendChild(btn));
i++;
for (let button in buttons) {
btn.setAttribute('id', "button " + button);
btn.classList.add(...CLS);
btn.innerHTML = "Button # " + button;
}
btn.addEventListener("click", function () {
let id = this.id;
alert("my id is: " + id);
});
}
});
.button {
padding: 10px;
}
.thin {
padding: 0px 10px;
}
<button class="add-btn button">Add</button>

Contents appear in Firefox but not in Chrome

I'm currently working on a search engine. I have implemented a feature in which a user has option to make the search engine as default in his browser on which user works.
Now this feature I have implemented in a type of box in which whenever a user redirects to the search engine site, the box appears at the right-side bottom with options.
The issue I'm struck with it is, that the box only appears in Firefox browser. But in chrome/chromium browser it doesn't.
$(document).ready(function() {
var isFirefox = typeof InstallTrigger !== 'undefined';
if (isFirefox === false) {
$("#set-susper-default").remove();
$(".input-group-btn").addClass("align-search-btn");
$("#navbar-search").addClass("align-navsearch-btn");
}
if (window.external && window.external.IsSearchProviderInstalled) {
var isInstalled = window.external.IsSearchProviderInstalled("http://susper.com");
if (!isInstalled) {
$("#set-susper-default").show();
}
}
$("#install-susper").on("click", function() {
window.external.AddSearchProvider("http://susper.com/susper.xml");
});
$("#cancel-installation").on("click", function() {
$("#set-susper-default").remove();
});
});
#set-susper-default {
width: 250px;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
position: fixed;
right: 10px;
bottom: 60px;
background-clip: padding-box;
display: block;
}
#set-susper-default h3 {
margin: 0;
padding: 8px;
text-align: center;
background-color: #26547c;
color: white;
}
#set-susper-default ol {
font-size: 15px;
background-color: white;
margin: 0;
padding-top: 10px;
padding-bottom: 10px;
}
#set-susper-default button {
background-color: #26547c;
border: none;
color: white;
font-size: 15px;
padding: 3px;
}
#set-susper-default #cancel-installation {
width: 100%;
}
#set-susper-default #install-susper {
padding: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="set-susper-default">
<h3>Set Susper as your default search engine on Mozilla!</h3>
<ol>
<!-- Start ignoring BootLintBear -->
<li><button id="install-susper">Install susper</button></li>
<li>Mark the checkbox to set Susper as your default search engine</li>
<li>Start searching!</li>
</ol>
<button id="cancel-installation">Cancel</button>
</div>
<!-- Stop ignoring BootLintBear -->
<div id="search-bar">
<app-search-bar></app-search-bar>
</div>
Please comment your initial lines in script code. Replace your script with following it works for me:
$(document).ready(function () {
//var isFirefox = typeof InstallTrigger !== 'undefined';
//if (isFirefox === false) {
// $("#set-susper-default").remove();
// $(".input-group-btn").addClass("align-search-btn");
// $("#navbar-search").addClass("align-navsearch-btn");
//}
if (window.external && window.external.IsSearchProviderInstalled) {
var isInstalled = window.external.IsSearchProviderInstalled("http://susper.com");
if (!isInstalled) {
$("#set-susper-default").show();
}
}
$("#install-susper").on("click", function () {
window.external.AddSearchProvider("http://susper.com /susper.xml");
});
$("#cancel-installation").on("click", function () {
$("#set-susper-default").remove();
});
});

Getting all css used in html file

I have to get what are all the CSS styles used in a HTML file using JavaScript.
<html>
<head>
<style type="text/css">
body {
border: 1px solid silver;
}
.mydiv{
color: blue;
}
</style>
</head>
<body>
</body>
</html>
If the above code is my HTML I have to write one JavaScript function inside the head which returns a string like this.
body {
border: 1px solid silver;
}
.mydiv {
color: blue;
}
Is it possible to do?
For inline stylesheets, you can get the content out of the normal DOM like with any other element:
document.getElementsByTagName('style')[0].firstChild.data
For external, linked stylesheets it's more problematic. In modern browsers, you can get the text of every rule (including inline, linked and #imported stylesheets) from the document.styleSheets[].cssRules[].cssText property.
Unfortunately IE does not implement this DOM Level 2 Style/CSS standard, instead using its own subtly different version of the StyleSheet and CSSRule interfaces. So you need some sniff-and-branch code to recreate rules in IE, and the text might not be exactly the same as the original. (In particular, IE will ALL-CAPS your property names and lose whitespace.)
var css= [];
for (var sheeti= 0; sheeti<document.styleSheets.length; sheeti++) {
var sheet= document.styleSheets[sheeti];
var rules= ('cssRules' in sheet)? sheet.cssRules : sheet.rules;
for (var rulei= 0; rulei<rules.length; rulei++) {
var rule= rules[rulei];
if ('cssText' in rule)
css.push(rule.cssText);
else
css.push(rule.selectorText+' {\n'+rule.style.cssText+'\n}\n');
}
}
return css.join('\n');
From Mdn:
const allCSS = [...document.styleSheets]
.map(styleSheet => {
try {
return [...styleSheet.cssRules]
.map(rule => rule.cssText)
.join('');
} catch (e) {
console.log('Access to stylesheet %s is denied. Ignoring...', styleSheet.href);
}
})
.filter(Boolean)
.join('\n');
Here's my solution :
var css = [];
for (var i=0; i<document.styleSheets.length; i++)
{
var sheet = document.styleSheets[i];
var rules = ('cssRules' in sheet)? sheet.cssRules : sheet.rules;
if (rules)
{
css.push('\n/* Stylesheet : '+(sheet.href||'[inline styles]')+' */');
for (var j=0; j<rules.length; j++)
{
var rule = rules[j];
if ('cssText' in rule)
css.push(rule.cssText);
else
css.push(rule.selectorText+' {\n'+rule.style.cssText+'\n}\n');
}
}
}
var cssInline = css.join('\n')+'\n';
In the end, cssInline is a textual list of all the steelsheets of the page and their content.
Example :
/* Stylesheet : http://example.com/cache/css/javascript.css */
.javascript .de1, .javascript .de2 { -webkit-user-select: text; padding: 0px 5px; vertical-align: top; color: rgb(0, 0, 0); border-left-width: 1px; border-left-style: solid; border-left-color: rgb(204, 204, 204); margin: 0px 0px 0px -7px; position: relative; background: rgb(255, 255, 255); }
.javascript { color: rgb(172, 172, 172); }
.javascript .imp { font-weight: bold; color: red; }
/* Stylesheet : http://example.com/i/main_master.css */
html { }
body { color: rgb(24, 24, 24); font-family: 'segoe ui', 'trebuchet MS', 'Lucida Sans Unicode', 'Lucida Sans', sans-serif; font-size: 1em; line-height: 1.5em; margin: 0px; padding: 0px; background: url(http://pastebin.com/i/bg.jpg); }
a { color: rgb(204, 0, 51); text-decoration: none; }
a:hover { color: rgb(153, 153, 153); text-decoration: none; }
.icon24 { height: 24px; vertical-align: middle; width: 24px; margin: 0px 4px 0px 10px; }
#header { border-radius: 0px 0px 6px 6px; color: rgb(255, 255, 255); background-color: rgb(2, 56, 89); }
#super_frame { min-width: 1100px; width: 1200px; margin: 0px auto; }
#monster_frame { -webkit-box-shadow: rgb(204, 204, 204) 0px 0px 10px 5px; box-shadow: rgb(204, 204, 204) 0px 0px 10px 5px; border-radius: 5px; border: 1px solid rgb(204, 204, 204); margin: 0px; background-color: rgb(255, 255, 255); }
#header a { color: rgb(255, 255, 255); }
#menu_2 { height: 290px; }
/* Stylesheet : [inline styles] */
.hidden { display: none; }
Here is my solution:
function getallcss() {
var css = "", //variable to hold all the css that we extract
styletags = document.getElementsByTagName("style");
//loop over all the style tags
for(var i = 0; i < styletags.length; i++)
{
css += styletags[i].innerHTML; //extract the css in the current style tag
}
//loop over all the external stylesheets
for(var i = 0; i < document.styleSheets.length; i++)
{
var currentsheet = document.styleSheets[i];
//loop over all the styling rules in this external stylesheet
for(var e = 0; e , currentsheet.cssRules.length; e++)
{
css += currentsheet.cssRules[e].cssText; //extract all the styling rules
}
}
return css;
}
It is based on #bobince's answer.
It extracts all the css from both the style tags and the external stylesheets.

Categories