I am looking online how to upload a folder of images and display them using JavaScript, and I am seeing this code repeatedly:
var inps = document.querySelectorAll('input');
[].forEach.call(inps, function(inp) {
inp.onchange = function(e) {
console.log(this.files);
};
});
Firstly, it doesn't work on my Google Chrome (it is not logging anything), and more importantly, what is this method of doing
[].forEach.call
What does this mean? (to use [] before forEach)?
BLOB - Binary Large Object
If you want preview loaded images, you should create blob.
URL will correct after save image in file base or database.
my GIT hub with example for only one picture
[].forEach.call it's just rule and you got answer upper.
developer.mozilla.org -> [].forEach.call
let inps = document.querySelectorAll('input');
[].forEach.call(inps, function(inp) {
inp.onchange = function(e) {
console.log(URL.createObjectURL(this.files[0])) //create BLOB for preview if need
for (file of this.files) {
setFiles(file); //parsing all uploaded files
createLIST(file, this.files.length);
}
};
});
//save all file to database by your URL -> URL_FOR_PROCESSING_POST
function setFiles(file) {
console.log(file);
let request = new XMLHttpRequest();
let formData = new FormData();
formData.append(file.name, file);
request.open('POST', 'URL_FOR_GET_POST');
request.send(formData);
}
arResult = [];
function createLIST(file, count) {
let html = '<ul>';
for (let item in file) {
html += `<li><div>${item}</div> <div>${file[item]}</div></li>`;
}
html += '</ul>';
arResult.push(html);
if (arResult.length === count) {
document.querySelector('#output-data').innerHTML = arResult.join('');
}
}
.output-data {
counter-reset: section;
}
.output-data ul {
border-bottom: 1px solid grey;
padding-bottom: 1rem;
}
.output-data ul:before {
counter-increment: section;
content: "File " counter(section) ": ";
font-weight: bold;
font-size: 20px;
color: green;
margin-bottom: 1rem;
display: block;
}
.output-data li {
display: flex;
padding-bottom: 0.25rem;
}
.output-data li div:first-child {
font-weight: bold;
flex: 0 1 200px;
}
.output-data li div:last-child {
text-align: left;
}
<input type="file" name="file" webkitdirectory directory>
<div id="output-data" class="output-data"></div>
Related
So I am still fairly early in my BED-Studies, and would apreciate any sugestions to be more code hevy than smart and eficient, this way i can learn.
Case:
I am creating a website that displays how the studies evolves my skills. And like any other page, it needs a nav-bar but it can get a little time consuming to retype every relevant link.
I have tried to google the question, but as far as i can find ther is a resounding "nope!", but then again, somthimes i com across people using a "file" function but i cant seem to find this function in jquery or js.
And thus back to my question: is ther a way to make JavaScript "see" the files in a location without hard-coding them in?
my folder structure is likethis:
/school:
./index.html
./css
./js
./programingFoundation:
./pfdindex.html
./module1
./module2
./...
./frontEndTech:
./fetIndex.html
./module1
./module2
,/..
Edit:
my attempt at navigation (mainNav.js):
function innsertMainNav() {
const mainNavTitles = [
{ button: 'Home', url: '/index.html', active: true },
{ button: 'JS Basic', url: '/programmingFoundations/pfindex.html', active: true },
{ button: 'Frontend', url: '/forntEndTechnologies/fetindex.html', active: true },
{ button: 'OOP', url: './programmingWithObjects/pwoindex.html', active: true },
{ button: 'Project Methodology', url: '/projectMethodology/pmindex.html', active: false },
{ button: 'Semester Project', url: '/semesterProject/smindex.html', active: false },
{ button: 'JS Servers', url: '/javaScriptServers/jssindex.html', active: false },
{ button: 'dataBases', url: '/databases/dbindex.html', active: false },
{ button: 'Rest Api', url: '/restApi/raindex.html', active: false },
{ button: 'Servers', url: '/serverDeployment/sdindex.html', active: false },
{ button: 'Exam', url: '/examProject/epindex.html', active: false }
];
//insert header
$('head').after('<header class="container-md bg-light"></header>');
// add title and logo line
$('header').append(`<div class="row"><h1>${document.title}</h1></div>`);
// add Navigation
$('header').append('<nav id="mainNav" class="row">\
<div id="outerDiv" class="container-fluid">\
<button\
class="navbar-toggler" type="button" data-bs-toggle="collapse"\
data-bs-target="#collapsing" aria-controls="collapsing"\
aria-expanded="false" aria-label="Togglenavigation">\
<span class="navbar-toggler-icon"></span>\
</button>\
<div id="collapsing" class="collapse navbar-collapse">\
<ul id="mainNavList" class="navbar-nav me-auto mb-2 mb-lg-0"></ul>\
</div></div></nav>');
// Populate main NAV
for (let i = 0; i < 10; i++) {
if (mainNavTitles[i].active) {
$('ul#mainNavList').append(`<li>\
<a class="col" href="..${mainNavTitles[i].url}">\
${mainNavTitles[i].button}\
</a></li>`);
}
else {
break;
}
}
$('#mainNav').addClass('navbar navbar-expand-lg navbar-light');
$('nav a').addClass('nav-link');
}
If you're only using HTML and vanilla JS, you could do it like this.
First, create a javascript file, and include it in every main html file you use on your website (for example, index.html. contact.html, portfolio.html, etc).
Let's call this file helpers.js.
Its contents would be something like this.
// Let's see if the HTML which is using helpers.js has its own navigation
var navigation = document.querySelectorAll("nav");
if(!navigation.length) {
var navigation = document.createElement("nav");
} else {
navigation = navigation[0];
}
// We'll make a centralized list of main links - the ones we want to see in the navigation
var linkList = {
"home":"index.html",
"portfolio":"portfolio.html",
"about me":"about.html",
"contact me":"contact.html"
};
// The function is here to help us populate the navigation with our links
function fillNavigation(elem, source) {
elem.innerHTML = "";
for(let description in source) {
let content = '' + description + '';
elem.innerHTML += content;
}
}
// We call the function, and let it work for us
fillNavigation(navigation,linkList);
One advantage of this is that you have one place where you change your main links list - you wouldn't have to visit each and every page of your site in order to make changes to your navigation. The helpers.js will do this for you.
A running example (JS fiddle here, in case you want to play around with this)
var navigation = document.querySelectorAll("nav");
if(!navigation.length) {
var navigation = document.createElement("nav");
} else {
navigation = navigation[0];
}
var linkList = {
"home":"index.html",
"portfolio":"portfolio.html",
"about me":"about.html",
"contact me":"contact.html"
};
function fillNavigation(elem, source) {
elem.innerHTML = "";
for(let description in source) {
let content = '' + description + '';
elem.innerHTML += content;
}
}
// The timeout is here for illustrative purposes only
setTimeout(function() {
fillNavigation(navigation,linkList);
},2000);
nav {
padding: 5px;
width: calc(100% - 10px);
text-align: center;
background-color: #333;
color: #fff;
}
nav a {
text-decoration: none;
padding: 3px;
}
nav a:hover {
color: red;
transition: 0.5s;
}
<nav>ok</nav>
<p>
lorem ipsum
sit dolor amet
etc lupus in fabula
homo homini lupus est
similis simili gaudet
bellum omnia contra omni
</p>
<hr>
<p>
some other stuff
</p>
EDIT For cases where you have multi-level menus, you could use something like this. As in the first example, a fiddle is available here
var navigation = document.querySelectorAll("nav");
if(!navigation.length) {
var navigation = document.createElement("nav");
} else {
navigation = navigation[0];
}
var linkList = {
"home":"index.html",
"portfolio":"portfolio.html",
"about me":"about.html",
"contact me":"contact.html",
"modules":{
"module1": {
"lorem":"lorem.html",
"ipsum":"ipsum.html"
},
"module2": {
"foo":"foo.html",
"bar":"bar.html"
}
}
};
function isObject(obj) {
return typeof obj === 'object';
}
function renderLinks(source,flagClose) {
let txt = "";
for(let description in source) {
if(isObject(source[description])) {
txt += '<li class="parent">' + description + '<ul class="sublevel none">';
txt += renderLinks(source[description],description);
} else {
let addition = flagClose ? (flagClose.trim() + '/') : ''
txt += '<li>' + description + '</li>';
}
}
if(flagClose) {
txt += '</ul></li>';
}
return txt;
}
function fillNavigation(elem, source) {
elem.innerHTML = "";
elem.innerHTML += renderLinks(source);
// show on hover
$("li.parent").mouseenter(function() {
$(this).find("> ul.sublevel").removeClass("none");
});
$("li.parent").mouseleave(function() {
$(this).find("> ul.sublevel").addClass("none");
});
}
fillNavigation(navigation,linkList);
.none {
display: none !important;
}
nav {
padding: 5px;
width: calc(100% - 10px);
text-align: left;
background-color: #333;
color: #fff;
}
nav a {
text-decoration: none;
padding: 3px;
}
nav a:hover {
color: red;
transition: 0.5s;
}
li {
list-style: none;
}
li.parent {
position: relative;
padding-right: 10px;
padding-left: 5px;
}
li.parent * {
display: block;
}
ul.sublevel {
position: absolute;
top: -1px; /* because of the border */
left: 100%;
background-color: #333;
margin-top: 0px;
margin-bottom: 0px;
padding-left: 10px;
min-width: 100px;
border: 1px solid #aaa;
text-align: left;
}
li.parent, ul.sublevel {
cursor: pointer;
}
nav li {
display: inline-block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav>ok</nav>
<p>lorem ipsum sit dolor amet etc lupus in fabula homo homini lupus est similis simili gaudet bellum omnia contra omni </p>
<hr>
<p>some other stuff</p>
You will notice a few differences from the first case (one-level menu):
the original linkList has been modified, in order to show the case when there's a multi-level menu (modules/module1/link1.html, modules/module1/link2.html, etc)
the function fillNavigation has been changed, as well - it now contains a call to a new function, renderLinks, which creates all the innerHTML
renderLinks is a recursive function, which makes it handy for cases where you decide to change the depth of your navigation. Please note that it has been tested on one and two-level menus. It should work for more levels than that, but you would have to adjust the CSS accordingly (or change the function a bit, so that you may have specific CSS classes, connected with a specific level)
the function renderLinks relies on a helper function, isObject. The purpose of this function is to test whether the item we're currently processing is actually a sub-menu. Since we control the original linkList and its structure, we can do it as shown in the code. For more complex cases (for example, where we have no, or little control on how the link list is formed, this solution would most likely be lacking)
hover effect and showing of sub-level menus is handled via jQuery. There is no special reason for this, other than that I found it simpler to achieve (less to type)
since we can have more than one menu element with children, mouseenter and mouseleave target only the first sub-level within the one we're hovering on. This also lets us travel (visually) along the hovered route, without closing the original top-level menu item which contains the one's we're currently traversing
The question here seems to be, how do I read a local filesystem from a web browser. Browsers have a FileAPI but it does not offer the ability to pass a list of the files and folders on the local filesystem without user input.
I'm building a website and am trying to display a message at the top of the page (inside the header) so it only appears once on every visit/session. An example of this the 'Book an appointment' green bar at the top of this website:
https://www.tiffany.co.uk
My website is here: https://vitrify.tempurl.host/
I've got as far as having a message appear (orange panel at top of page) but currently it appears every time a page is loaded. I just want it to appear once, just like a cookie consent.
I've spent hours looking for a solution but, as I'm not a programmer, I'm struggling. Any help would be much appreciated.
Here's the HTML:
function myFunction() {
var x = document.getElementById("topDIV");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
.topDIV {
color: #000000;
font-weight: 300;
font-size: 15px;
}
.topDIV a:link, .topDIV a:visited {
color: #000000!important;
font-weight: 500;
letter-spacing: -0.3px;
line-height: 1.2 ;
}
span.topDIV {
}
.topDIV a:hover {
border-bottom: 1px solid rgba(0,0,0,0.50) !important;
display: inline-block;
}
.button-x {
position: relative;
float: right;
top: -5px;
background:none;
border:none;
color:rgb(0,0,0) ;
cursor: pointer;
vertical-align: 0px;
}
.button-x:before {
font-family: 'Times';
content: "X";
font-size:30px;
vertical-align:0px;
opacity:0.5;
}
.button-x:hover {
opacity:1!important;
}
<span class = "topDIV">Welcome to <em>Vitrify</em>. Following in the finest traditions of vitreous enamelled jewellery. Find out more.</span><button class = "button-x" onclick="myFunction()"></button>
As mentioned above you need to use localStorage to solve your problem.
Need to know when page is loaded
Get value from the localStorage
Add event to the button (i removed the onclick event from the html for a cleaner solution)
After click set value for localStorage and hide item
If localStorage have value, hide the element
working example
Javascript
document.addEventListener('DOMContentLoaded', function () {
const topDiv = document.querySelector('.topDIV');
const buttonX = document.querySelector('.button-x');
// Get value from localStorage when open the page
const lS = localStorage.getItem('first-visit');
// Add button 'click' event
buttonX.addEventListener('click', () => {
// Set value to the localStorage
localStorage.setItem('first-visit', false);
// hide DOM element
topDiv.style.display = 'none';
});
// This does not check on the first visit to the page
// If localStorage have value, hide DOM element
if (lS) topDiv.style.display = 'none';
});
Html
<span class="topDIV"
>Welcome to <em>Vitrify</em>.Following in the finest traditions of
vitreous enamelled jewellery.
Find out more.
</span>
<button class="button-x"></button>
You can add a flag "showTopMessage:true" in your local storage or session storage based on one time msg to user or every time he visits. respectively.
On Cross/close icon click set the flag "showTopMessage:false".
const showTopBar = "SHOW_TOP_BAR";
const[showTopBar,setShowTopBar] = useState(true);
useEffect(()=>{
const saveState = localstorage.getItems(showTopBar);
if(saveState) setShowTopBar(saveState);
else localstorage.setItem(showTopBar, true);
},[]);
const handleTopBarClose = () => {
setShowTopBar(false);
localstorage.setItem(showTopBar, false);
}
return(
<div>
{
showTopBar && <TopBarComponent onClose={handleTopBarClose}/>
}
</div>
)
I'm working on a project in which a user can select colors from a color input and create their own theme dynamically using CSS variables. I'd like the user to be able to download the entire CSS file with the values they selected.
My issue: The CSS file downloaded doesn't display the actual color values, but shows the variable name.
NOT WANTED
pre[class*="language-"] {
background: var(--block-background);
}
instead of
WANTED OUTPUT
pre[class*="language-"] {
background: #0D2831;
}
I know I can get CSS property values by doing the following.
const styles = getComputedStyle(document.documentElement)
const value = String(styles.getPropertyValue('--block-background')).trim()
I figured that I would create a function that loops through all my CSS variables and grabs the corresponding property values and then adds them to a new stylesheet for the user to download, but I got lost along the way. I currently have two CSS files, a main.css and a prism.css. The main.css file holds the page styling and all CSS variables within the root. The prism.css file contains the theme in which I want the user to be able to download.
I'm trying to find a way to create a new stylesheet that contains everything within the prism.css file but has the actual color hex code instead of the CSS variable name as a value to the given CSS property.
Index.js
import { colors } from './colorHelper'
const inputs = [].slice.call(document.querySelectorAll('input[type="color"]'));
const handleThemeUpdate = (colors) => {
const root = document.querySelector(':root');
const keys = Object.keys(colors);
keys.forEach(key => {
root.style.setProperty(key, colors[key]);
});
}
inputs.forEach((input) => {
input.addEventListener('change', (e) => {
e.preventDefault()
const cssPropName = `--${e.target.id}`;
document.styleSheets[2].cssRules[3].style.setProperty(cssPropName, e.target.value)
handleThemeUpdate({
[cssPropName]: e.target.value
});
console.log(`${cssPropName} is now ${e.target.value}`)
});
});
const cssRules = document.styleSheets[2].cssRules;
for (var i = 0; i < cssRules.length; i++) {
// Finds css variable names
const regexp = /(?:var\(--)[a-zA-z\-]*(?:\))/
let cssVariables = cssRules[i].cssText.matchAll(regexp)
cssVariables = Array.from(cssVariables).join()
console.log(cssVariables)
}
colorHelper.js
const colorSelect = {
'Line Highlights': {
'highlight-background': '#F7EBC6',
'highlight-accent': '#F7D87C'
},
'Inline Code': {
'inline-code-color': '#DB4C69',
'inline-code-background': '#F9F2F4'
},
'Code Blocks': {
'block-background': '#0D2831',
'base-color': '#5C6E74',
'selected-color': '#b3d4fc'
},
'Tokens': {
'comment-color': '#93A1A1',
'punctuation-color': '#999999',
'property-color': '#990055',
'selector-color': '#669900',
'operator-color': '#a67f59',
'operator-background': '#FFFFFF',
'variable-color': '#ee9900',
'function-color': '#DD4A68',
'keyword-color': '#0077aa'
}
}
const colorNames = []
const colors = {}
Object.keys(colorSelect).map(key => {
const group = colorSelect[key]
Object.keys(group).map(color => {
colorNames.push(color)
colors[color] = group[color]
})
})
export { colorSelect, colorNames, colors }
prism.css
pre[class*="language-"],
code[class*="language-"] {
color: var(--base-color);
font-size: 13px;
text-shadow: none;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
direction: ltr;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::selection,
code[class*="language-"]::selection,
pre[class*="language-"]::mozselection,
code[class*="language-"]::mozselection {
text-shadow: none;
background: var(--selected-color);
}
#media print {
pre[class*="language-"],
code[class*="language-"] {
text-shadow: none;
}
}
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
background: var(--block-background);
}
:not(pre) > code[class*="language-"] {
padding: .1em .3em;
border-radius: .3em;
color: var(--inline-code-color);
background: var(--inline-code-background);
}
/* Tokens */
.namespace {
opacity: .7;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: var(--comment-color);
}
.token.punctuation {
color: var(--punctuation-color);
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: var(--property-color);
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: var(--selector-color);
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: var(--operator-color);
background: var(--operator-background);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: var(--keyword-color);
}
.token.function {
color: var(--function-color);
}
.token.regex,
.token.important,
.token.variable {
color: var(--variable-color);
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}
/* Line highlighting */
pre[data-line] {
position: relative;
}
pre[class*="language-"] > code[class*="language-"] {
position: relative;
z-index: 1;
}
.line-highlight {
position: absolute;
left: 0;
right: 0;
padding: inherit 0;
margin-top: 1em;
background: var(--highlight-background);
box-shadow: inset 5px 0 0 var(--highlight-accent);
z-index: 0;
pointer-events: none;
line-height: inherit;
white-space: pre;
}
I have three stylesheets.
style.css holds the CSS variables in the root
normalize.css
prism.css contains the styles for syntax highlighting. This is the stylesheet I would like the user to download, but I would like to provide them with the actual hex values for each variable and not the variable name for the CSS property.
Stylesheet order in my HTML
<link rel="stylesheet" type="text/css" href="./style.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.css"
integrity="sha256-WAgYcAck1C1/zEl5sBl5cfyhxtLgKGdpI3oKyJffVRI=" crossorigin="anonymous" />
<link href="./themes/prism.css" rel="stylesheet" />
EDIT
I attempted to loop through the stylesheet and grab the CSS variable names, but some of them returned as an empty string.
This is what I did
const cssRules = document.styleSheets[2].cssRules;
for (var i = 0; i < cssRules.length; i++) {
const regexp = /(?:var\(--)[a-zA-z\-]*(?:\))/
let cssVariables = cssRules[i].cssText.matchAll(regexp)
cssVariables = Array.from(cssVariables)
console.log(cssVariables)
}
This was the result in the console
var(--base-color)
var(--selected-color)
<empty string>
var(--block-background)
var(--inline-code-color)
<empty string>
var(--comment-color)
var(--punctuation-color)
var(--property-color)
var(--selector-color)
var(--operator-color)
var(--keyword-color)
var(--function-color)
var(--variable-color)
<empty string>
var(--highlight-background)
I then attempted to chain .replace() after the trim() but that didn't seem to work either.
You can download the file as text then find and replace the variables.
For example:
var s = `pre[class*="language-"] {
background: var(--block-background);
}`
const variables = {"block-background":"#0D2831"};
Object.keys(variables).forEach(key => {
s = s.replace("var(--"+key+")", variables[key]);
});
console.log(s);
You are getting empty strings from css rules that do not have var(--something) in them. Like
#media print {
pre[class*="language-"],
code[class*="language-"] {
text-shadow: none;
}
}
which gives you the first empty string.
You are missing var(--operator-background) because matchAll() actually doesn't do what you expect. It does
returns an iterator of all results matching a string against a regular expression
but the regular expression you have yields only one result. So you need to add g flag to it
/(?:var\(--)[a-zA-z\-]*(?:\))/g
mozselection... Hmm... Not sure, but shouldn't it be -moz-selection?
The full loop for replacements can look like this:
const updated_rules = [];
for (var i = 0; i < cssRules.length; i++) {
const regexp = /(?:var\(--)[a-zA-z\-]*(?:\))/g;
let updated_rule = cssRules[i].cssText;
let cssVariables = updated_rule.matchAll(regexp);
cssVariables = Array.from(cssVariables).flat();
for (const v of cssVariables) {
updated_rule = updated_rule.replace(v, colors[v.slice(6, -1)]);
}
updated_rules.push(updated_rule);
}
console.log(updated_rules);
It's an ugly code, and should be refactored, but...
Why would you access css through document.styleSheets anyway? It's harder than just replacing strings in a css-file and for one thing, I'm not sure if you whould be able to access ::-moz-selection rule on Chrome, and in turn ::-webkit-selection on Firefox
I am trying to display a set of CSS properties in a textarea using JavaScript:
var exampleone = document.getElementById('th001');
var borderbox = window.getComputedStyle(exampleone).getPropertyValue('cursor');
document.getElementById("csstextareadisp").value = borderbox;
However it only displays one element, which I have to specify.
I want the JavaScript to read all properties which exist in the CSS document and display them as seen in the CSS document, e.g.
.exone{
border-style: solid;
border-width: 2px;
border-color: rgba(57,165,255,1.00);
width: 150px;
height: 30px;
position: relative;
text-align: center;
background-color: transparent;
color: black;
}
.exone:hover{
cursor: pointer;
background-color: rgba(57,165,255,1.00);
color: white;
}
My question is, is there a way I can use JavaScript to get it to display like that (seen above) in a textarea other than setting it to display using:
document.getElementById("csstextareadisp").value = ".exone{ \n border-style: solid; \n border-width: 2px; \n border-color: rgba(57,165,255,1.00); \n width: 150px; \n height: 30px; \n position: relative; \n text-align: center; \n background-color: transparent;color: black; \n } \n\n .exone:hover{ \n cursor: pointer; \n background-color: rgba(57,165,255,1.00); \n color: white; \n }";
Updated answer
There is a helpful topic here:
How to get the applied style from an element, excluding the default user agent styles
I tried to enhance the solution provided in this topic to better fit your needs by…
Adding a parameter to be able to choose whether or not to include inline style,
Adding a function to correctly indent the styles,
Trying to simplify some code.
var proto = Element.prototype;
var slice = Function.call.bind(Array.prototype.slice);
var matches = Function.call.bind(proto.matchesSelector ||
proto.mozMatchesSelector || proto.webkitMatchesSelector ||
proto.msMatchesSelector || proto.oMatchesSelector);
// Returns true if a DOM Element matches a cssRule
var elementMatchCSSRule = function(element, cssRule) {
// console.log(cssRule) //.selectorText.split(":")[0]); // Testing to add hover
return matches(element, cssRule.selectorText);
};
// Returns true if a property is defined in a cssRule
var propertyInCSSRule = function(prop, cssRule) {
return prop in cssRule.style && cssRule.style[prop] !== '';
};
// Here we get the cssRules across all the stylesheets in one array
var cssRules = slice(document.styleSheets).reduce(function(rules, styleSheet) {
return rules.concat(slice(styleSheet.cssRules));
}, []);
// Get only the css rules that matches that element
var getAppliedCSS = function(elm) {
var elementRules = cssRules.filter(elementMatchCSSRule.bind(null, elm));
var rules = [];
if (elementRules.length) {
for (i = 0; i < elementRules.length; i++) {
rules.push({
order: i,
text: elementRules[i].cssText
})
}
}
return rules;
}
// TAKIT: Added this function to indent correctly
function indentAsCSS(str) {
return str.replace(/([{;}])/g, "$1\n ").replace(/(\n[ ]+})/g, "\n}");
}
function getStyle(elm, lookInHTML = false) { // TAKIT: Added the new parameter here
var rules = getAppliedCSS(elm);
var str = '';
for (i = 0; i < rules.length; i++) {
var r = rules[i];
str += '/* CSS styling #' + r.order + ' */\n' + r.text;
}
// TAKIT: Moved and simplified the below from the other function to here
if (lookInHTML && elm.getAttribute('style')) // TAKIT: Using the new parameter
str += '\n/* Inline styling */\n' + elm.getAttribute('style');
return indentAsCSS(str);
}
// Output in textarea
var exone = document.getElementById("exone");
var result = document.getElementById("result");
result.value = getStyle(exone, true); // TAKIT: Using the new parameter for inline style
#exone {
border-style: solid;
border-width: 2px;
border-color: rgba(57, 165, 255, 1.00);
width: 150px;
height: 30px;
position: relative;
text-align: center;
background-color: transparent;
color: black;
}
#exone:hover {
cursor: pointer;
background-color: rgba(57, 165, 255, 1.00);
color: white;
}
#result {
width: 90%;
height: 240px;
}
<div id="exone" style="opacity: 0.95;"></div>
<textarea id="result"></textarea>
(I'm trying to add the :hover style to the output too, but I can't make it to work)
⋅
⋅
⋅
Old answer
(When I hadn't found anything helpful yet)
As the .getComputedStyle doesn't make any difference between the one that are present in the CSS and the other ones, it seems complicated to differenciate them.
So, here is an attempt of that:
I've made a loop to compare the element exone with another reference element that has not been stylized using CSS,
It seems that the element we take in reference must be on the page to effectively compare them, so I've put it in the HTML.
In the loop, if the values are the same, that must mean that both of them are not stylized, so, we skip to the next item.
I ended-up with that snippet:
// Get style of our example element
var exampleone = document.getElementById('exone');
var styles_one = window.getComputedStyle(exampleone);
// Get style of a reference element without CSS
var reference = document.getElementById('exref');
var styles_ref = window.getComputedStyle(reference);
// Loop and compare our example element with the reference element
var results = {};
for (var key in styles_ref) {
if(key.includes('webkit')) continue; // Next if webkit prefix
if(styles_one[key] == styles_ref[key]) continue; // Next if same value as the ref
results[key] = styles_one[key]; // Copy value in results[key]
}
delete results.cssText; // Useless in our case
// Output in console
console.log(results);
#exone {
border-style: solid;
border-width: 2px;
border-color: rgba(57, 165, 255, 1.00);
width: 150px;
height: 30px;
position: relative;
text-align: center;
background-color: transparent;
color: black;
}
#exone:hover {
cursor: pointer;
background-color: rgba(57, 165, 255, 1.00);
color: white;
}
<div id="exone"></div>
<div id="exref"></div>
The console should display only the CSS that differs from the not stylized reference element… So, this must come from the CSS!
Now, we only need to format a little this output and put it in a textarea.
Feel free to comment.
Hope it helps.
I am pulling some information from an external database using javascript. However, I am not sure how to generate a like unlike toggle button for users to click below each information.
I place a toggle link within the appendeddata variable just to test if it would work. The link did show up below each data but the toggle effect did not work. I place the code within the same script and in its own script however no luck.
I want to also id the user that clicks the link. how can I do this?
Thank you.
here is my javascript code.
var appendedhtml = "";
var address = "";
function getDomes() {
$.ajax({
type: "GET",
url: "https://api.google.com/d/domes/explore?
ll="+lat+","+lng+"&client_id= client_id&query="+$("#query").val()+"",
success: function(data) {
$("#domes").show();
var dataobj = data.response.groups[0].items;
$("#domes").html("");
$.each( dataobj, function() {
if (this.dome.categories[0]) {
str = this.dome.categories[0].icon.prefix;
newstr = str.substring(0, str.length - 1);
icon = newstr+this.dome.categories
[0].icon.suffix;
} else {
icon = "";
}
if (this.dome.location.address) {
address = '<p
class="subinfo">'+this.dome.location.address+'<br>';
} else {
address = "";
}
appendedtml = '<div
class="venue"><h2><span>'+address'</span></h2> <hr>';
$("#domes").append(appendedhtml);
});
}
});
}
I place the code that would give the toggle effect within the main script and by itself
with no luck.
<script>
$(document).ready(function(){
$('a.toggler').click(function(){
$(this).toggleClass('off');
});
});
this is the css for the toggle button. I know the button works indecently just cannot get it
to work with the data output from the main script.
a.toggler {
background: green;
cursor: pointer;
border: 2px solid black;
border-right-width: 15px;
padding: 0 5px;
border-radius: 5px;
text-decoration: none;
transition: all .5s ease;
}
a.toggler.off {
background: red;
border-right-width: 2px;
border-left-width: 15px;
}
try jQuery's on method instead of click method.
$( "a.toggler" ).on( "click", function() {
$(this).toggleClass('off');
});
on method listens to events from elements that were created dynamically.