I'm trying to create a Chrome extension that "unblurs" a series of images on a webpage. I'm very new to all this and I just wanted to know if I was on the right track.
From what I've seen, each image is contained in a tag that looks like this:
<div class="Bdrs(8px) Bgz(cv) Bgp(c) Ov(h) StretchedBox Ir(p) Cnt($blank)::a StretchedBox::a Bg($inherit)::a Scale(1.3)::a Scale(1.2)::a--s Blur(12px)::a">
In order for the picture to be unblurred, the Blur(12px) pseudo class must be changed to Blur(0px). I'm not getting any results from what I've tried, but I feel as though my logic is right. All I want the extension to do is automate the process of using "Inspect Element" to edit the page.
var profilePic = document.getElementsByClassName("Bdrs(8px) Bgz(cv) Bgp(c) Ov(h) StretchedBox Ir(p) Cnt($blank)::a StretchedBox::a Bg($inherit)::a Scale(1.3)::a Scale(1.2)::a--s Blur(12px)::a");
for(var i = 0; i < profilePic.length(); i++) {
profilePic[i].classList.remove("Bdrs(8px) Bgz(cv) Bgp(c) Ov(h) StretchedBox Ir(p) Cnt($blank)::a StretchedBox::a Bg($inherit)::a Scale(1.3)::a Scale(1.2)::a--s Blur(12px)::a");
profilePic[i].classList.add("Bdrs(8px) Bgz(cv) Bgp(c) Ov(h) StretchedBox Ir(p) Cnt($blank)::a StretchedBox::a Bg($inherit)::a Scale(1.0)::a Scale(1.0)::a--s Blur(0px)::a");
}
The images on the page should be unblurred, but nothing happens. I may not have my extension set up properly since I've just started looking into this stuff, but I was hoping that someone else with more experience could tell me if my code was okay.
Try this:
[...document.getElementsByClassName('Blur(12px)::a')]
.forEach(e => e.classList.replace('Blur(12px)::a', 'Blur(0px)::a'));
The problem with your current approach is that both classList.remove(..) and classList.add(..) expect a single parameter, a string representing a single class name or multiple string parameters representing single class names.
Related
I'm confused as I don't believe I've done anything out of the ordinary here, that I haven't done before.
I'm looking to implement a feature similar to Excel's "Highlight Duplicate Values" action.
I have a function that takes tab separated values and parses them into a list of claims. It's all hacky, but the "list" (or table) is a series of divs that contains various elements such as a button that holds the claim ID. Once the list is created and all claims are visible, I parse it to find what buttons hold duplicate values, and apply a class to said button to highlight it using .addClass().
The problem is that I cannot seem to get the button to highlight. Now I've used functions like this before without any issue, including making a row highlight when clicked (and dim the others), and so on, but I'm confused what seems to be wrong here.
The parsing code is as follows:
function parseForDuplicates() { // Look for duplicates to highlight
var importedListLength = $("div.column.colClaim").length; // Get length of claims in list
var claimsToReview = []; // create an array for below...
for (let a=0; a < softParsedList.length; a++) { // Add the claim IDs to the claimsToReview array
claimsToReview.push(softParsedList[a][0]);
}
for (let i=0; i < importedListLength; i++) { // Compare values...
var currentCheckedClaimBtn = $(`div.column.colClaim:nth-child(${i+1}) button`); // Get the button element for current line
if (i > 0) {
var previousCheckedClaimBtn = $(`div.column.colClaim:nth-child(${i}) button`); // Get the button element for previous line only if we're further along the list
} else {
var previousCheckedClaimBtn = "none"; // set to "none" if we're at the beginning.
}
if (i < importedListLength) {
var nextCheckedClaimBtn = $(`div.column.colClaim:nth-child(${i+2}) button`); // Get button element from next line
} else if (i == importedListLength) {
var nextCheckedClaimBtn = "none"; // set to "none" if we're at the end
}
var currentCheckedClaim = $(`div.column.colClaim:nth-child(${i+1}) button`).val(); // Get claim ID from current line
if (i > 0) {
var previousCheckedClaim = $(`div.column.colClaim:nth-child(${i}) button`).val(); // Get claim ID from previous line
} else {
var previousCheckedClaim = "none"; // set to "none" if we're at the beginning
}
if (i < importedListLength) {
var nextCheckedClaim = $(`div.column.colClaim:nth-child(${i+2}) button`).val(); // Get claim ID from next line
} else if (i == importedListLength) {
var nextCheckedClaim = "none"; // set to "none" if we're at the end
}
//console.log(`Previous Claim: ${previousCheckedClaim}`);
//console.log(`Current Claim: ${currentCheckedClaim}`);
//console.log(`Next Claim: ${nextCheckedClaim}`);
if (currentCheckedClaim == nextCheckedClaim) { // If the current claim matches next claim
currentCheckedClaimBtn.addClass('duplicateClaim'); // Highlight current button
nextCheckedClaimBtn.addClass('duplicateClaim'); // Highlight next button
nextCheckedClaimBtn.addClass('duplicateClaim'); // Highlight next button
console.log(`${currentCheckedClaim} is a duplicate!`);
}
if (currentCheckedClaim == previousCheckedClaim) { // If the current claim matches previous claim
currentCheckedClaimBtn.addClass('duplicateClaim'); // Highlight current button
previousCheckedClaimBtn.addClass('duplicateClaim'); // Highlight previous button
console.log(`${currentCheckedClaim} is a duplicate!`);
}
}
}
The CSS in question...
.duplicateClaim {
border-color: #BB9955 !important;
background-color: #773311 !important;
color: #FFFFFF !important;
}
I've tried with and without !important and that doesn't change anything
When I open up DevTools I can see that the styles get applied appropriately, however in the Styles sidebar, the style is nowhere to be found! I can add it manually to the stylesheet, and at that point, the buttons highlight as intended!
I've gone over the seemingly trivial things: I've definitely saved the CSS file. The HTML file points to the correct CSS file (it never changed to begin with), and there are no conflicting styles that I'm aware of. I use two stylesheets (one named style2.css and the other named external.css and there are no conflicts between them. I tried disabling external.css - no change. I also made sure I didn't somehow open the wrong css (from production or a backup) and just have been editing CSS that was never referenced by changing a DIFFERENT rule - the body - to have a background color that's #FFFFFF and it works. I've also tried inserting it directly into the HTML... that doesn't work. Moving .duplicateClaim to the TOP of the CSS file? Nope. Maybe I just fat fingered it all? Nope. Spelling is correct. I did a copy/paste just in case my eyes have betrayed my brain - nah, they're still cooperating with me... for now. And what about adding a class that's actually an ID?
Yeah, no, that period has not magically turned into a hash. Most definitely has remained a period, and hasn't given me an issue. Oh oh! But what about applying the style DIRECTLY too the element? Nah, I assure you I've tried and nothing wants to play nice.
And lastly, I've tried generating each line WITH the class already entered! That doesn't work either. For whatever reason, chrome just seems to eat that one rule for lunch, and it just doesn't exist. I feel like there is SOMETHING dumb that I'm just not looking at and I'm just dealing with being really, really tired, but I need some kind of sanity check here. Or, maybe I really am going crazy...
Of course, again, let me emphasize that when looking at the source in the developer tools, the class most definitely gets added to the elements that I specify in the code - the JS appears to work, regardless of whether or not it's messy and triggers you (however it's not the first time something appears to work but is still wrong. It just seems like the class ceases to exist the moment the page is loaded. And if I manually add it in the developer tools by clicking the New Style Rule button (the plus next to the :hov and .cls buttons)? It applies to the correct buttons without issue.
First of all a disclaimer, I'm not a dev. I'm halfway through The Odin Project and have covered some HTML and CSS, but, have not yet started on JS. In order to help with my learning I've created my own blog. My aim is for each blog post to have its own stylesheet (so with each new post I learn a little more about CSS).
Anyway, I plan to write a post about the benefits of using an eReader, specifically the Kindle. I've styled the page to look like a Kindle Oasis, and I'd like the reader to be able to step through the article contents via the Kindle's next/prev buttons, but, as I'm not a dev, this is where I'm stuck. Via Stack overflow I've managed to add some JS that will display page 1, 2 and 3 via dedicated buttons for each dive element, but, what I really need is to step through x number of pages via the prev/next buttons.
Here's what I have so far: https://codepen.io/dbssticky/pen/yLVoORO. Any help would be much appreciated. What I should do of course is finish The Odin Project and come up with a solution on my own, but, I'd really like to get this Kindle article published sooner rather than later. Hence my rather cheeky request for assistance.
Here's the JS I'm currently using:
function swapContent(id) {
const main = document.getElementById("main_place");
const div = document.getElementById(id);
const clone = div.cloneNode(true);
while (main.firstChild) main.firstChild.remove();
main.appendChild(clone);
}
You have the right idea and it just needs a few adjustments to get the previous/next functionality.
Currently your div IDs are following the format operation1, operation2, and so on. Since you want the previous/next functionality you'll need to change your 'swapping' function, which currently takes the full ID, to use the numeric portion only.
Add a new function which appends the number to 'operation' instead of using the whole thing:
function goToPage(pageNumber){
const main = document.getElementById("main_place");
const div = document.getElementById("operation" + pageNumber);
const clone = div.cloneNode(true);
while (main.firstChild) main.firstChild.remove();
main.appendChild(clone);
}
And then change your Page 1/2/3 buttons to use goToPage(1), goToPage(2) and so on.
Now for the previous/next functionality you'll need a way to track which page you're on, so that you can figure out which page to load.
Add a variable at the top (outside functions)
var currentPage = 0;
Then add a line in your goToPage function to track the page you're on.
currentPage = pageNumber;
Now that you're tracking you can add a previous and next function.
function goNextPage(){
goToPage(currentPage-1);
}
function goPreviousPage(){
goToPage(currentPage+1);
}
Then call it from the previous and next buttons.
<button onClick="goNextPage()" class="next-button"></button>
<button onClick="goPreviousPage()" class="previous-button"></button>
Here's a codepen: https://codepen.io/srirachapen/pen/WNZOXQZ
It's barebones and you may have to handle things like non existent div IDs.
HTML
<button class="next-button" onclick="nextContent()"></button>
<button class="previous-button" onclick="prevContent()"></button>
JS
var pageid = 0;
var maxpage = 3;
function nextContent() {
if(pageid == maxpage) return
pageid++
swapContent(`operation${pageid}`)
}
function prevContent() {
if(pageid == 1) return
pageid--
swapContent(`operation${pageid}`)
}
you can try this to switch between pages. But you may need to edit the "swapContent" method more sensibly.
Track the Current Page
Whatever solution you use to render pages & links (manual hardcoded links & content vs externally-stored & auto-generated), one thing is unavoidable: You need to track the current page!
var currentPage = 0
Then, any time there's a page change event, you update that variable.
With the current page being tracked, you can now perform operations relative to it (e.g. +1 or -1)
I'd suggest making a goToPage(page) function that does high-level paging logic, and keep your swapContent() function specifically for the literal act of swapping div content. In the future, you may find you'd want to use swapContent() for non-page content, like showing a "Welcome" or "Help" screen.
Example:
function goToPage(page) {
// Update `currentPage`
currentPage = page
// ... other logic, like a tracking event or anything else you want you occur when pages change
// Do the actual content swap, which could be your existing swapContent()
swapContent('operation'+page)
}
You'd invoke the function like so:
goToPage(3) // Jump to a specific page
goToPage(currentPage + 1) // Go to the next page
goToPage(currentPage - 1) // Go to the prev page
You can make separate helper functions like "goToNextPage()" if you desire, but for sure you start with a fundamental page-change function first.
Excuse my limited ability to be able to frame the question. I need to check 100 boxes to apply an accounting rule to 100 bank entries (in FreeAgent). In the console in Google Chrome I have typed the following, which succesfully checks the first box in the list. (Once it works I will put it in a loop so it checks all of them but I'm not at that point yet.)
var x = document.getElementsByClassName('FormElement-checkbox');
x[1].firstElementChild.checked = true;
When I try to continue with the procedure, the web page doesn't "realise" that the boxes have been checked. I can only get it to work if I physically click the checkboxes individually on the page - the fact they appear checked doesn't seem to matter to the page. So there is obviously something I am missing.
I can succesfully enter text into boxes and select items in drop downs. I have tried inspecting the checkbox element and seeing what happens when it is checked by clicking on it, but I can't see any difference in the HTML. I have explored a lot of the attributes in the javascript for that object when typing
x;
which is how I found the .firstElementChild.checked = true in the first place.
I don't know whether it is something specific to the page itself or whether in general I don't have enough experience to be able to tackle all data entry situations yet. I have tried searching for answers on this forum and elsewhere.
Have you tried something like this:
var x = document.getElementsByClassName('FormElement-checkbox')
x[0].checked = true;
or use the click() method on checkbox element.
Part of HTML document might be helpful.
This happens most likely because of some JS/CSS trickery - the elements are listening to click event rather than change in HTML property. Try raising .click event
var cbs = document.getElementsByClassName("FormElement-checkbox")
for (var i = 0; i < cbs.length; i++){
cbs[i].click()
}
Try this:
var x = document.getElementsByClassName('FormElement-checkbox');
var result = "document.getElementsByClassName('FormElement-checkbox')";
for (var i=0, len=x.length|0; i<len; i=i+1|0) {
result += "\n " + x[i].textContent;
}
You can also try using:
document.querySelector(".FormElement-checkbox")
to get the first element with the class_name (or)
document.querySelectorAll(".FormElement-checkbox")
to get a list of elements with the class_name
You can find everything about Document.getElementsByClassName() here at this link
I am using the Snowstorm.js javascript file with my webpage.
Current the source allows you to change the character which a 'snowflake' is displayed as. However, I would like to be able change the property of he snowflake to be the image of a snowflake which I have created.
You are able to edit the source and this is the line which sets the character to be displayed.
this.snowCharacter = '•'; // • = bullet, · is square on some systems etc.
Is there any way I can change this to display an image instead of a character and if so, how is this done? I have never worked with Javascript before so for any help or pointers I would be very greatful.
It looks like Snowstorm.js might have the functionality to do this already. Have you seen the information posted at http://www.bozo.us/Javascript/snowstorm/? This page suggests:
File Structure
The script looks for snow images under ./image/snow/ by
default as shown below. If desired, this can be changed in the
user-configurable section.
This seems to correspond to an update mentioned at the bottom of the page you linked, where it says:
1.2.20041121a
Script moved into one file (snowstorm.js) for simplicity
addEventHandler and PNG support functions updated
There's probably a ton of hacky ways to do this in JavaScript, but maybe this will lead you to a clean solution. Good luck!
Find these lines
this.o = document.createElement('div');
this.o.innerHTML = storm.snowCharacter;
this.o.style.color = storm.snowColor;
this.o.style.position = (fixedForEverything?'fixed':'absolute');
this.o.style.width = storm.flakeWidth+'px';
this.o.style.height = storm.flakeHeight+'px';
this.o.style.fontFamily = 'arial,verdana';
this.o.style.cursor = 'default';
this.o.style.overflow = 'hidden';
this.o.style.fontWeight = 'normal';
this.o.style.zIndex = storm.zIndex;
The "o" here is your div element. You can add it a class by adding this line:
this.o.className = "myClass";
To remove the character remove this line:
this.o.innerHTML = storm.snowCharacter;
Than you can style the snowflake with css, the way you know it. Just give it a background image. You can also remove the lines that set the color, width and height and style them with css.
Use unicode '❄' instead of '•' in the original line like this:
this.snowCharacter = '❄';
this will output the snowflake '❄' character as above instead of bullet point.
you might also have to increase these values to 16 or so:
this.flakeWidth = 8;
this.flakeHeight = 8;
I have a problem with JavaScript looping and DOM.
so I have a few div's, each has a background image defined by CSS, however when i rollover a text link, i wish for these background images to change, which ones will change depends on their class name and the link mouseover'ed
<div id="im1" class="web"></div>
<div id="im2" class="logo"></div>
<div id="im3" class="web"></div>
<div id="im4" class="logo"></div>
<div id="5" class="logo"></div>
web
so those are the divs with my link for the mouse over.
then to change these images i have some simple JavaScript, which works fine (if very long)....
function showweb() {
document.getElementById("im1").style.backgroundImage = "url('back/1col.png')";
document.getElementById("im2").style.backgroundImage = "url('back/2col.png')";
however, i wondered if there was a way i would condition by class name, and only change those with a certain class name, eg web, or logo. ive tried various ways and loops and things, but none seemed to work.
e.g
function showweb() {
for(i=0; i=5; i++){
url = "im" + i;
if(document.getElementById("url").className=="web"){
document.getElementById("url").style.backgroundImage = "url('back/"+ i +"col.png')";}
}
}
however this doesn't work, the divs just don't change..... am i doing something wrong? missing something? or doing it the completely wrong way?
all help appreciated, thanks in advance.
Edit: changed the "url" to url, my bad, that was very foolish, however still didnt work. i will try a few other ideas posted.
thanks everyone so far.
You don't need the quotes around url:
document.getElementById(url)
This may work (if the link to your images is right and presumed that by id="5" you mean id="im5". Play with it until it's right. Check your code thourougly, there were several errors (typos or worse 1) in your coding:
function showweb() {
for(var i=1; i < 6; i++){
var el = document.getElementById("im"+(i));
if(el && /web/.test( (el ||{}).className)){
el.style.backgroundImage = "url(back/"+ i +"col.png)";}
}
}
1 a few notes on that
id = "5" should supposedly be id ="im5"
i=0; i=5; i++ => i=5 should be i<5
i=0; i=5; i++ creates a global variable i. Use var i=0;...
given your id's, you should start with var i = 1
though not a real error, you don't need to surround the url value with apostrophes
to optimize call document.getElementById once and use it's result in the rest of the code
You're building the "url" variable, but then you pass the string constant "url" into the "getElementById()" function.
To get only elements of the desired class, you need node.getElementsByClassName('your_class'), where node can be document or some <div> selected by id, or any other node of the DOM tree.
Note: Remember that all methods that start with getElement will return single element, and those with getElements will return an array of elements, so this one returns an array which you need to iterate (even if there is only one element in it)
However, since you are working with DOM elements in JavaScript, you would save tons of time by using jQuery
You have a few of problem. First, you have quotes around the variable "url" so it's looking for an element with that id, which doesn't exist and thus fails when you attempt to access the className of a null lookup result. Second, your loop starts at 0, not one and you don't have a div with id "im0" so it would fail anyway when you attempt to get the className of that element, which also doesn't exist. Third, the check in your loop sets i to 5 instead of checking if it is less than or equal to 5. Your loop with thus continue forever, since 5 equates to true, which I'm sure is not what you want. Fourth, your code may break if you assign additional classes to the elements. Lastly, most of this sort of thing has already been done for you -- might I suggest you look into using a javascript framework, such as jQuery -- with the hover() method, as a better alternative than re-inventing the wheel if this isn't purely a learning exercise.