How to remove style attribute added with jquery - javascript

I am using a devExpress table with some custom requirements.
(UPDATE)
Took a break from this for a day and went back and did it properly using React Styling! Thanks for suggestions
In the screenshot I have certain cells disabled. However the user wants all cells to look disabled other that the row selected.
Using this
window
.$("td")
.not(document.getElementById(this.state.selection[0]))
.not(document.getElementsByClassName(this.state.selection[0]))
.not("td:first-child")
.not(window.$("td:contains('iPlay')"))
.not(window.$("td:contains('iLOE')"))
.not(window.$("td:contains('iInvest')"))
.not(window.$("td:contains('SPACER')"))
.not(window.$("td:contains('$MM')"))
.not(window.$("td:contains('$/BOE')"))
.attr("style", "color:#868a8f");
window
.$("td > div > div > div > input")
.not(document.getElementsByClassName(this.state.selection[0]))
.attr("style", "color:#868a8f");
I managed to achieve my desired result on page load
My problem is when I select a new row I cannot remove that color I applied before when it was not selected. I am trying to use "has" to find the selected row and change the color back to inherit or completely remove the style attribute.
window
.$("td")
.has(document.getElementById(this.state.selection[0]))
.has(document.getElementsByClassName(this.state.selection[0]))
.not("td:first-child")
.not(window.$("td:contains('iPlay')"))
.not(window.$("td:contains('iLOE')"))
.not(window.$("td:contains('iInvest')"))
.not(window.$("td:contains('SPACER')"))
.not(window.$("td:contains('$MM')"))
.not(window.$("td:contains('$/BOE')"))
.attr("style", "color:inherit");
window
.$("td > div > div > div > input")
.has(document.getElementsByClassName(this.state.selection[0]))
.attr("style", "color:inherit");
If it helps I do have the ids of the rows that are NOT selected.
I tried to do something with that but did not have any luck
const otherRows = ExpensesUtils.ROW_PROPS.filter(x => x !== this.state.selection[0]);
for (let i = 0; i < otherRows.length; i += 1) {
window
.$("td")
.has(document.getElementById(otherRows[i]))
.has(document.getElementsByClassName(otherRows[i]))
.attr("style", "color:inherit");
window
.$("td > div > div > div > input")
.has(document.getElementById(otherRows[i]))
.has(document.getElementsByClassName(otherRows[i]))
.attr("style", "color:inherit");
}
link to HTML
Table HTML
this.state.selection[0] is the selected rowId from the list below
I have applied the the rowIds to classes in the nested components. I could not figure out another way to access them.
const ROW_PROPS = [
"leaseAndWellExpense",
"leaseAndWellExpenseBoe",
"iloeLeaseAndWellExpense",
"iloeLeaseAndWellExpenseBoe",
"gnaLeaseAndWell",
"gnaLeaseAndWellBoe",
"transportation",
"transportationBoe",
"divisionGnA",
"divisionGnABoe",
"gatheringProcessing",
"gatheringProcessingBoe",
"hqGnA",
"hqGnABoe",
"interestExpense",
"interestExpenseBoe",
"netProdBoe",
"leaseImpairments",
"leaseImpairmentsBoe",
"ddaProducing",
"ddaProducingBoe",
"iInvestDdaProducing",
"iInvestDdaProducingBoe",
"ddaGatheringProcessing",
"ddaGatheringProcessingBoe",
"iInvestDdaGatheringProcessing",
"iInvestDdaGatheringProcessingBoe",
"marketingCosts",
"otherIncomeExpense",
"otherIncomeExpenseBoe",
"otherRevenue",
"incomeTaxProvision",
"incomeTaxProvisionBoe",
"severanceTaxes",
"severanceTaxesPercent",
"currentTaxes",
"currentTaxesRate",
"netWellHeadRevenue",
];

The easiest way of doing this is by creating a CSS rule's stylesheet.
In that stylesheet, you should define 2 classes.
Let's suppose 1 for your desired CSS rules and the other for the default/none rules.
I am just showing you the simplest version of doing this thing but with another aspect.
$('#b1').on('click', function() {
$('.c1').removeClass('c1');
$(this).addClass('c2');
});
.c1 {
color: red;
}
.c2 {
color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="b1">Change</button>
<p class="c1">This is a Test Line.</p>

The easiest way is
$('#idName').on('click', function()
{
$('.className').removeClass('removeClassName');
$(this).addClass('addClassName');
});
The code above means that when a button with the id of IdName is clicked, the element with className will be removing the class of removeClassName, and adding the class of addClassName.
For further clarification you can have a look at Removing CSS Using JQuery Documentation

There is another way by which you can achieve it.
Instead of playing with style attribute, since it takes the highest specificity so somewhere it might create an issue.
Instead of that you can use toggleClass. First add your default styling to table, whenever you click any row you can make use of toggle class
Toggle Class Example
Example.
$("td > div > div > div").click(function(){
$("input").toggleClass("main");
})

Related

D3.js - Append objects outside of the selection

How do you select a div and then create a new div right below it?
function addContainer(row)
{
row++
d3.select('body')
.append('div')
.attr('class', `#container${row}`)
.attr("onclick", `addContainer(${row})`)
.text("Container " + `${row}`)
}
<div id="container0" onclick="addContainer(0)" >Container 0</div>
<script src="https://d3js.org/d3.v5.min.js"></script>
Everything works fine except for the part that I want the added div to be exactly below the div I clicked on and not at the very bottom. So my idea was that instead of selecting the body I select the id of the div I clicked on and then append a new div. However this adds a div within the div and not below it.
So how do I append it outside of the selection or is there a better way to do it?
Here's one approach to do that: Use d3.insert.
And due to the this issues while binding events onclick on HTML elements, I've moved the event binding and handling to the JS section.
This is how I'm appending a <div> as the next sibling to the selected (clicked) element:
this.parentNode.insertBefore(this.cloneNode(deep), this.nextSibling)
Code:
d3.select('#container0').on('click', addContainer);
function addContainer(row)
{
if(!row) row = 0;
row++
d3.select(this).select(function () {
return this.parentNode.insertBefore(document.createElement('div'), this.nextSibling);
})
.attr('class', `#container${row}`)
.on('click', function () { addContainer.call(this, row); })
.text("Container " + `${row}`)
}
<div id="container0">Container 0</div>
<script src="https://d3js.org/d3.v5.min.js"></script>
Notice the addContainer.call(this, row) to bind the this used while selection.
Hope this helps. And about the container number, it adds +1 to the bound element's number. If you want the container number to keep on increasing, just declare the row outside and take it out while calling the function (as this'll help the divs to have unique IDs). And do check the DOM if it's inserting the elements correctly.

Toggling the class of an object with jquery

I have elements that are added by the user (when they click a button), it adds a p and a pre element. The pre element is invisible and has no class while the p element has a class of "query-p".
What I'm trying to do is to make it so whenever the user clicks on a p element with "data-id='p1'", it add the class "show" to the pre element with "data-id='pre1'" or for example when you click on a p element with "data-id='p2'", it add the class "show" to the pre element with "data-id='pre2'" and so on.
This is my jquery code :
$(function () {
$("p[data-id]").on("click", function() {
var idFound = $(this).data("id");
if ($("p[data-id]").attr("class") == "query-p" && $("pre[data-id]").attr("class") != "show") {
$("pre[data-id]").attr("class", "show");
}
else if ($("pre[data-id]").attr("class") == "show") {
$("pre[data-id]").removeAttr("class");
}
});
});
This is my HTML (the elements that I'm working with are not in this code, I put it here because it might help): https://pastebin.com/eKVbUZHQ
This is my other javascript file (it mostly contains the code that adds the elements that I'm working with) : https://pastebin.com/yEZuuhA8
The problem that I'm having is that my code shows all pre elements instead of only the one it's supposed to.
EXAMPLE :
I added new elements with :
p element 1 : id="display-pre1" class="query-p" data-id="p1"
pre element 1 : id="display-pre-a1" data-id="pre1"
p element 2 : id="display-pre2" class="query-p" data-id="p2"
pre element 2 : id="display-pre-a2" data-id="pre2"
The pre elements are hidden with "display: 'none'".
All elements with class "show" have "display: 'block'".
The pre elements have no class.
Now, whenever I click on the first p element, it adds the class "show" to both the pre element 1 and the pre element 2, so they both get "display: 'block'", when I click it again it hides both of the pre elements again.
Hope this helps a bit.
Some of the issues within the click handler:
With $("p[data-id]") you select all p elements with a data-id attribute, while you need to only select the clicked one.
With $("pre[data-id]") you select all pre elements with a data-id attribute, while you need to only select one with a particular value for that attribute.
You compare the class attribute with "query-p", but then why not put this condition in a way that the click handler is only defined for those? Then you don't have to check this anymore once the user has clicked.
The code with attr("class") and removeAttr("class") assumes that an element will have at the most one CSS class. This is restricting the possibilities. Elements should be allowed to have multiple CSS classes defined for it.
Here is a small snippet to demo how it could work:
$(function () {
$("p.query-p[data-id]").on("click", function() {
var data = $(this).data("id").replace(/^p/, "pre"),
$pre = $("pre[data-id=" + data + "]");
$pre.toggleClass("show");
});
});
pre { display: none }
pre.show { display: block }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p class="query-p" data-id="p1">para 1</p>
<p class="query-p" data-id="p2">para 2</p>
<pre data-id="pre1">pre 1</pre>
<pre data-id="pre2">pre 2</pre>

Too much duplication of code

The problem I am encountering, is that I have to many duplicates. I am basically trying to show 1/11 tables by which bottom is clicked (list_row[1-11]), so when I show for instance table 2, it must hide all the other tables.
I believe this can be shortened by a loop or something else, because if I have 100 tables then I must copy and paste, not smart. Keep in mind that the code below is just showing table 1 to table 3. How can I prevent these duplicates?
// hide the tables by default when page loads
$('#table1').hide();
$('#table2').hide();
$('#table3').hide();
$('#table4').hide();
$('#table5').hide();
$('#table6').hide();
$('#table7').hide();
$('#table8').hide();
$('#table9').hide();
$('#table10').hide();
$('#table11').hide();
// Show Exhaust Temperature diagram
$('#list_row1').on('click',function(){
$('#table1').show();
$('#table2').hide();
$('#table3').hide();
$('#table4').hide();
$('#table5').hide();
$('#table6').hide();
$('#table7').hide();
$('#table8').hide();
$('#table9').hide();
$('#table10').hide();
$('#table11').hide();
});
// Show Cylinder Pressure diagram
$('#list_row2').on('click',function(){
$('#table1').hide();
$('#table2').show();
$('#table3').hide();
$('#table4').hide();
$('#table5').hide();
$('#table6').hide();
$('#table7').hide();
$('#table8').hide();
$('#table9').hide();
$('#table10').hide();
$('#table11').hide();
});
$('#list_row3').on('click',function(){
$('#table1').hide();
$('#table2').hide();
$('#table3').show();
$('#table4').hide();
$('#table5').hide();
$('#table6').hide();
$('#table7').hide();
$('#table8').hide();
$('#table9').hide();
$('#table10').hide();
$('#table11').hide();
});
// Code continues to table11.
Set all your tables to display: none then introduce an .active class set to display: block (or display: table, in this case). Then simply toggle the class on and off:
.active {
display: table;
}
$('#list_row1').on('click', function() {
$('.active').removeClass('active');
$('#table1').addClass('active');
});
To avoid repetition, however, you'd be better off extending this this to add data-* attributes to your #list_row/n/ elements, and handle click events on these:
<elem id="list_row1" data-row="1"></elem>
$('[data-row]').on('click', function() {
var row = $(this).attr('data-row');
$('.active').removeClass('active');
$('#table' + row).addClass('active');
});
Do also note that you can chain selectors with commas. Rather than using $(elem1).hide(); $(elem2).hide() you can instead $(elem1, elem2).hide().
Try
$('[id^=list_row]').on('click',function(){
$('table').hide();
$('#table'+$(this).attr('id').slice(8)).show();
});
You can also use the starts-with jQuery selector:
$('id^="table"').hide();
$('id^="list_row"').on('click',function(){
var num = this.id.split('w')[1]; //alert(num)
$('id^="table"').hide();
$('#table'+num).show();
});
Reference:
All jQuery Selectors
Add a class to all your table and listrow elements, and a custom attribute on those lasts to identify where are you clicking.
<table id="table2" class="tableClass">
<whatever id="list_row2" class="listRowClass" data-yourProjectname-numRow="2">
This way you can just show the table that's been clicked and hide all the rest:
$(".listRowClass").on("click", function() {
$(".tableClass").hide() // Hides all tables
$("#table" + $(this).attr("data-yourProjectname-numRow")).show() //Shows clicked table
});

Use JQuery to target div container for hide/show div without using ID's

I have a script below and wanted to target the show/hide div as the check boxes are clicked without using ID's and restricting the hide/show feature within each container. Any suggestions?
Here is the fiddle. http://jsfiddle.net/45NRN/2/
And here is the jquery code.
$('.c-input').live('change', 'checkbox', function() {
var target = $(this).prev('.showHideDiv');
if ($(this).find('input:checked').length == 0) {
target.hide();
} else {
target.show();
}
});
This should do the trick
$('.c-input').live('change', ':checkbox', function() {
var target = $(this).closest('.c-input').prev().find('.showHideDiv');
if ($(this).find('input:checked').length == 0) {
target.hide();
} else {
target.show();
}
});
DEMO
Some comments:
Replaced 'checkbox' by ':checkbox'. Your selector finds tags with name checkbox (<checbox\>,that's not what you're looking for
this in your context is the checkbox and not the .c-input element. I changed the related selector to reflect this.
Or you could do this Working demo :- ) http://jsfiddle.net/P8UFL/
Issue was you are using .prev for the element which is inside another div --> wrap
Hence, to traverse through it correctly you probably need to do the prev on wrap and then find showHideDiv
Also HTML is bit invalid > chuck in /> with your checkboxes tag.
.live is depricated from 1.7 > Jquery version; alternative is .on just a note.
Hope this helps :)
Code
var target = $(this).prev('.wrap').find(".showHideDiv");

Javascript Collapsible Menu (hide the other elements)

I have the following working Javascript function:
function collapsible(zap) {
if (document.getElementById) {
var abra = document.getElementById(zap).style;
if (abra.display == "block") {
abra.display = "none";
} else {
abra.display = "block";
}
return false;
} else {
return true;
}
}
When I use the following in html code it displays or hides the "element" div:
<li>Element</li>
Thats working fine. But the problem is, that I want to use the function for multiple links, and then the other elements, that were clicked before, stay, open.
How can I reprogram the code, so that only one div stays open and the other gets closed if i click on another link?
Thanks beforehand!
If you could use jQuery and more importantly jQueryUI accordion I think it would accomplish exactly what you're looking for.
However, without using those two, here is how I would structure it. Like mentioned above, I would use classes to modify the styles of the divs you want shown or hidden. Then the js code can just toggle those classes on each of your elements. The slightly more difficult part (without jquery) is modifying class values since in your final application you may have lots of classes on each div. This is just a very crude example to get you going.
Working JSFiddle Example
Sample DOM
<div >
<li>Element1</li>
<div id='elem1' class='myelem visible'>
Element 1 contents
</div>
</div>
<div >
<li>Element2</li>
<div id='elem2' class='myelem'>
Element 2 contents
</div>
</div>
<div >
<li>Element3</li>
<div id='elem3' class='myelem'>
Element 3 contents
</div>
</div>
Sample JS
window['collapsible'] = function(zap) {
if (document.getElementById)
{
var visDivs = document.getElementsByClassName('visible');
for(var i = 0; i < visDivs.length; i++)
{
visDivs[i].className = visDivs[i].className.replace('visible','');
}
document.getElementById(zap).className += " visible";
return false;
}
else
return true;
}
Sample CSS:
.myelem {
display: none;
}
.visible {
display: block;
}
The way to go is to create a class(or maybe two), like collapsible and active or open that has this style(display: block or none) and then you working adding or removing the class.
The logic would be:
Links that has the class collapsible when clicked would add the active or open class which would give the behavior that remains opens(or active) by css.
If you want to hide others elements you would look for the elements with the class collapsible and then remove the active(or open) class if has any.
Here is my solution: http://jsfiddle.net/g5oc0uoq/
$('.content').hide();
$('.listelement').on('click', function(){
if(!($(this).children('.content').is(':visible'))){
$('.content').slideUp();
$(this).children('.content').slideDown();
} else {
$('.content').slideUp();
}
});
show() and hide() can be used instead of slideUp() and slideDown() if you have performance issues.

Categories