Hide dynamic JS buttons based on a var value - javascript

I am having a similar problem to this: Hide dynamically added buttons based on an if statement. With a JS mod for A Dark Room I am working on to increase my JS skills. Neither of these snippets are mine, and both are working perfectly.
This is the code snippet to create the buttons:
build: function(buildBtn) {
var thing = $(buildBtn).attr('buildThing');
if($SM.get('game.temperature.value') <= Room.TempEnum.Cold.value) {
Notifications.notify(Room, _("builder just shivers"));
return false;
}
This snippet makes sure that buttons stay visible, but I would like to change it so that when a max value is met the button is hidden.
//show button if one has already been built
if($SM.get('game.buildings["'+thing+'"]') > 0){
Room.buttons[thing] = true;
return true;
}

Hiding and showing elements is typically done through a class. Have a css class like this
.hidden {
display : none'
}
Then in your javascript, add or remove hidden class according to your condition
if(condition) {
$(element).addClass('hidden');
} else {
$(element).removeClass('hidden');
}

It's hard to suggest because there isn't enough context. The snippet you show may not just be exclusively responsible for controlling the visibility of the button (despite the inline comment saying it is). As a result the following suggestion may not work and more information on what you're trying to do and more code would be needed.
If you have access to modify the snippet then you can include the max value there. If the max value is a variable (i.e myCustomMaxValue) and it's in scope then my best guess would be to add it here:
var myCustomMaxValue = 88;
var someOtherVariableInScope = 50
//show button if one has already been built
if($SM.get('game.buildings["'+thing+'"]') > 0){
//add your condition here and yield true/false
var myCustomCondition = someVariableInScope > myCustomMaxValue;
Room.buttons[thing] = myCustomCondition;
return myCustomCondition;
}
I would suggest the debug; keyword. Place it in the snippet and open your browsers' developer tools and its debugger will get hit. You can then inspect the variables in scope and verify the snippet is in fact responsible for dynamically showing and hiding the button.
//show button if one has already been built
if($SM.get('game.buildings["'+thing+'"]') > 0){
debug;
Room.buttons[thing] = myCustomCondition;
return myCustomCondition;
}

Related

Parse a JS array and add a style for matching values using .addClass()

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.

jQuery addClass adds the class but I don't see a visual change in the browser

I am using Angular 1.6 with jQuery 3.3.1 to practice Angular. My simple application screen looks like this.
In the event handler snippet below, I have a simple validation to check if the customer being added already exists in the system. If it does, I want to do 2 things:
Display an error message in red on top of the input fields. This happens nicely as you can see in the picture below.
Highlight the existing customer record in the list below the input fields by changing the background of the <li> to be red.
$scope.onBtnAddNewCustomerClicHandler = function() {
var customerId = $scope.customers.exists(
$scope.newCustomer.name,
$scope.newCustomer.city);
var listItem;
if (customerId > 0) {
// do the UI thing
var listItem = angular.element(
document.querySelector("#liCustomer_" + customerId));
if (listItem === undefined) {
throw new Error("Error: could not find the duplicate customer Id in the list of existing customers.");
}
$("#divErrorMessageSection").show();
listItem.addClass("backgroundRed");
return false;
}
else {
$("#divErrorMessageSection").hide();
if (listItem !== undefined) {
listItem.removeClass("backgroundRed");
}
}
$scope.customers.add();
return true;
};
My code works fine and does what it is supposed to, except I don't see any visual change indicating that the <li> background has turned red. However, I am able to change the class of the <li> to backgroundRed as indicated in the picture below.
The class gets added regardless of whether I use:
var listItem = angular.element(
document.querySelector("#liCustomer_" + customerId));
or
var listItem = $("#liCustomer_" + customerId);
To look for the listItem containing the existing customer record.
My CSS looks like this:
.backgroundRed {
background-color: red;
};
Try adding !important in your css like below:
.backgroundRed {
background-color: red !important;
};
I have experienced this a lot, according to my experience, css style tags are applied ONLY when the page loads. If you want to highlight the li tag, you have to change the style attribute.
The reason you don't see this on the error message is because the element is hidden until it shows, and is always red.
Try
listItem.style += "background-color: red";

Format text as user inputs in a contenteditable div

I'm attempting to make a page that allows users to input text and it will automatically format the input -- as in a screenplay format (similar to Amazon's StoryWriter).
So far I can check for text with ":contains('example text')" and add/remove classes to it. The problem is that all of the following p tags inherit that class.
My solution so far is to use .next() to remove the class I added, but that is limited since there might be need for a line break in the script (in dialogue for instance) and that will remove the dialogue class.
$('.content').on('input', function() {
$("p.input:contains('INT.')").addClass("high").next(".input").removeClass("high");
$("p.input:contains('EXT.')").addClass("high").next(".input").removeClass("high");
});
I can't get || to work in the :contains parameter either, but that's the least of my issues.
I have a JS fiddle
I've worked on this for a while now, and if I could change only the node that contains the text (INT. or EXT. in this example) and leaves the rest alone that would work and I could apply it to the rest of the script.
Any help would be appreciated, I'm new to the stackoverflow so thank you.
See the comments in the code below for an explanation of what's going on.
Fiddle Example
JQuery
var main = function(){
var content = $('.content');
content.on('input', function() {
$("p.input").each(function() {
//Get the html content for the current p input.
var text = $(this).html();
//indexOf will return a positive value if "INT." or "EXT." exists in the html
if (text.indexOf('INT.') !== -1 || text.indexOf('EXT.') !== -1) {
$(this).addClass('high');
}
//You could include additional "if else" blocks to check and apply different conditions
else { //The required text does not exist, so remove the class for the current input
$(this).removeClass('high');
}
});
});
};//main close
$(document).ready(main);

Add hanging indent to CKEditor on web page [duplicate]

I'm using CKEditor and I want to indent just the first line of the paragraph. What I've done before is click "Source" and edit the <p> style to include text-indent:12.7mm;, but when I click "Source" again to go back to the normal editor, my changes are gone and I have no idea why.
My preference would be to create a custom toolbar button, but I'm not sure how to do so or where to edit so that clicking a custom button would edit the <p> with the style attribute I want it to have.
Depending on which version of CKE you use, your changes most likely disappear because ether the style attribute or the text-indent style is not allowed in the content. This is due to the Allowed Content Filter feature of CKEditor, read more here: http://docs.ckeditor.com/#!/guide/dev_advanced_content_filter
Like Ervald said in the comments, you can also use CSS to do this without adding the code manually - however, your targeting options are limited. Either you have to target all paragraphs or add an id or class property to your paragraph(s) and target that. Or if you use a selector like :first-child you are restricted to always having the first element indented only (which might be what you want, I don't know :D).
To use CSS like that, you have to add the relevant code to contents.css, which is the CSS file used in the Editor contents and also you have to include it wherever you output the Editor contents.
In my opinion the best solution would indeed be making a plugin that places an icon on the toolbar and that button, when clicked, would add or remove a class like "indentMePlease" to the currently active paragraph. Developing said plugin is quite simple and well documented, see the excellent example at http://docs.ckeditor.com/#!/guide/plugin_sdk_sample_1 - if you need more info or have questions about that, ask in the comments :)
If you do do that, you again need to add the "indentMePlease" style implementation in contents.css and the output page.
I've got a way to indent the first line without using style, because I'm using iReport to generate automatic reports. Jasper does not understand styles. So I assign by jQuery an onkeydown method to the main iframe of CKEditor 4.6 and I check the TAB and Shift key to do and undo the first line indentation.
// TAB
$(document).ready(function(){
startTab();
});
function startTab() {
setTimeout(function(){
var $iframe_document;
var $iframe;
$iframe_document = $('.cke_wysiwyg_frame').contents();
$iframe = $iframe_document.find('body');
$iframe.keydown(function(e){
event_onkeydown(e);
});
},300);
}
function event_onkeydown(event){
if(event.keyCode===9) { // key tab
event.preventDefault();
setTimeout(function(){
var editor = CKEDITOR.instances['editor1'], //get your CKEDITOR instance here
range = editor.getSelection().getRanges()[0],
startNode = range.startContainer,
element = startNode.$,
parent;
if(element.parentNode.tagName != 'BODY') // If you take an inner element of the paragraph, get the parentNode (P)
parent = element.parentNode;
else // If it takes BODY as parentNode, it updates the inner element
parent = element;
if(event.shiftKey) { // reverse tab
var res = parent.innerHTML.toString().split(' ');
var aux = [];
var count_space = 0;
for(var i=0;i<res.length;i++) {
// console.log(res[i]);
if(res[i] == "")
count_space++;
if(count_space > 8 || res[i] != "") {
if(!count_space > 8)
count_space = 9;
aux.push(res[i]);
}
}
parent.innerHTML = aux.join(' ');
}
else { // tab
var spaces = " ";
parent.innerHTML = spaces + parent.innerHTML;
}
},200);
}
}

JavaScript file Not Minifying Correctly

I'm trying to minify a JavaScript file for my website but this part of the code in the snippet is causing errors when it minifies.
//do not hide if click on the label object associated to the select
Do I need this part of the code or is it an important command for the code. If I do need it, do I need to add anything to it in order to minify correctly?
/* Hide all open selects */
var jqTransformHideSelect = function(oTarget){
var ulVisible = $('.jqTransformSelectWrapper ul:visible');
ulVisible.each(function(){
var oSelect = $(this).parents(".jqTransformSelectWrapper:first").find("select").get(0);
//do not hide if click on the label object associated to the select
if( !(oTarget && oSelect.oLabel && oSelect.oLabel.get(0) == oTarget.get(0)) ){$(this).hide();}
});
};
It's a comment. You can remove it. Check out this article on JavaScript comments.
Also, you can lint it to see if there are any issues. I linted it for you:
Make sure you've included jQuery and all that good stuff.

Categories

Resources