This answer shows how to hide visible elements. I want to create action for switching visibilities some elements. According to documentation I need to use element.removeAttr to remove some attributes. I can see removed ./display', 'none' attribute, but on UI elements are still hidden - they should be visible.
Do you know what I'm missing? Should I rerender UI somehow?
Below is my event.
paper.on('cell:pointerdown', function switchTaskVisibility(...args) {
const selectedItem = args[0];
const successors = graph.getSuccessors(selectedItem.model);
const tasks = successors.filter(function isElementOfTypeTask(element) {
const type = element.prop('type');
if (type === 'task') return element;
});
console.log(tasks);
const hasVisibleTasks = selectedItem.model.prop('hasVisibleTasks');
if (hasVisibleTasks) {
tasks.forEach((element) => {
element.attr('./display', 'none');
});
}
else {
tasks.forEach((element) => {
element.removeAttr('./display');
});
}
// HERE I CAN SEE THAT DISPLAY ATTRIBUTE SWITCHES CORRECTLY
// BUT AFTER FIRST HIDING OF ELEMENTS I CANNOT MAKE THEM VISIBLE IN UI
console.log(graph.getSuccessors(selectedItem.model));
selectedItem.model.prop('hasVisibleTasks', !hasVisibleTasks);
});
Thanks,
Rafal
I found some workaround. From some reason removeAttr doesn't rerender elements properly, so I tested visibility property like this:
const hasVisibleTasks = selectedElement.prop('hasVisibleTasks');
if (hasVisibleTasks) {
cells.forEach((element) => {
element.attr('./visibility', 'hidden');
});
}
else {
cells.forEach((element) => {
element.attr('./visibility', 'visible');
});
And works fine. But I still don't understand why element.removeAttr('./display') didn't rerender UI earlier.
Best regards,
Rafal
Irrespective of the solution, Why you are using const data type for hasVisibleTasks as it seems the value of this variable is changing in run-time.
Related
I'm trying to write a function, to make a visual object come on and off, on and off, as the user clicks on it. Then add a click event listener in the class, called button btn-sauce.
So far my code doesn't work :
function renderWhiteSauce() {
if (element.classList) {
element.classList.toggle("btn-sauce.active");
} else {
var classes = element.className.split(" ");
var i = classes.indexOf("btn-sauce.active");
if (i >= 0)
classes.splice(i, 1);
else
classes.push("btn-sauce.active");
element.className = classes.join(" ");
}
document.querySelector('.btn-sauce.active').addEventListener('click', () => {
state.sauce = !state.sauce;
renderEverything();
});
You can just add and remove classes with methods classList.add('classname') and classList.remove('classname'). Define class which makes btn active and just add or remove it.
const elem = document.querySelector('.btn-sauce')
elem.addEventListener('click', () => {
if(elem.className.indexOf('className') < 0) {
elem.classList.add('className')
} else {
elem.classList.remove('className')
}
});
btn-sauce and active are two separate classes, but you are writing your code like they are one. Remove btn-sauce. (including the dot) from everything above the querySelector line and you will be able to toggle the active class on and off.
If the element is not "active" to begin with, you should also change document.querySelector('.btn-sauce.active') to document.querySelector('.btn-sauce').
One last note, you are calling renderEverything() in your click handler, which I assume is another function that calls renderWhiteSauce(), but I thought I'd mention it in case this was just a typo and they were meant to be the same function.
This is probably an easy solution but right now I can't figure out how to make it work
$(".a").click(function () {
if ($("#btnCollapse").css('display')!='none')
$("#btnCollapse").click();
});
Then I tried using vanilla js, I know I am missing something....
var anchor = document.querySelectorAll(".a");
var button = document.querySelectorAll("#btnCollapse");
function collapseNav() {
anchor.addEventListener('click', function() {
button.style.display="none"
});
button.click();
}
querySelectorAll returns a nodelist so you need to loop through its result.
For the #bntCollapse use querySelector, it returns as single element. For elements with an id, and if you need to find many, you can use getElementById, which is faster than querySelector
To get the style, use window.getComputedStyle as it will return a style being set using external CSS as well, which element.style.display won't.
var anchors = document.querySelectorAll(".a");
for (var i = 0; i < anchors.length; i++) {
anchors[i].addEventListener('click', function(e){
var btn = document.querySelector("#btnCollapse");
if (window.getComputedStyle(btn,null).getPropertyValue("display") != 'none') {
btn.click();
}
})
}
Note, you can use foreach to loop the elements, though based on how, in IE, Edge and Safari it might not work, so test it thoroughly, therefore I used a for..loop for maximum browser support.
Direct conversion of your "jQuery" code:
if (button.style.display != 'none')
button.click();
It can be done using closure-in-loop,
var anchor = document.querySelectorAll(".a");
var button = document.querySelectorAll("#btnCollapse");
Array.from(anchor).forEach(a => {
a.addEventListener('click', function() {
if(button.style.display!="none"){
button.click();
}
});
});
querySelectorAll() returns a collection of elements, not a single one, hence you need to loop over it. The button has an id so you can select it using querySelector() to get a single instance back.
You also have no collapseNav() function in the jQuery version so your event handler will be added on load.
Finally the logic is not the same. In the jQuery you only click the button if it's display is not none. Try this:
var anchor = document.querySelectorAll(".a");
var button = document.querySelector("#btnCollapse");
anchor.forEach(function(el) {
el.addEventListener('click', function() {
if (button.style.display != 'none')
button.click();
});
});
I have a selected object that was clicked. When this happens, i would like to retrieve the object and then find the children with a specific class value so i can disable them.
I am able to get the object but when i access the children i always get "undefined" even though i can see the children.
I browsed the object and i can see the class attributes values i am looking for.
Can somebody please tell me if i am referencing this correctly?
Below is my code,
The specific line with the issue is,
var kids = clicked_obj.children('.ui-selected');
// manually trigger the "select" of clicked elements
$(".page").click(function (e) {
console.log(e);
//var selected_divs = $(".page").find("div[class*='ui-selected']");
var selected_divs = $(".page").find(".existingFieldItem.ui-selected");
selected_divs.each(function () {
if (e.ctrlKey == true) {
var clicked_obj = e.target.parentElement;
var kids = clicked_obj.children('.ui-selected');
console.log("Ctrl clicked");
console.log($(this).attr("id"));
kids.each(function () {
$(this).removeClass("ui-selected");
});
// if command key is pressed don't deselect existing elements
$(this).removeClass("ui-selected");
$(this).addClass("ui-selecting");
}
else {
if ($(this).hasClass("ui-selected")) {
// remove selected class from element if already selected
$(this).removeClass("ui-selected");
}
else {
// add selecting class if not
$(this).addClass("ui-selecting");
}
}
});
$(".page").data("ui-selectable")._mouseStop(null);
});
});
You're missing a jQuery selection:
var clicked_obj = $(e.target.parentElement);
e.target.parentElement is a DOM element object, not a jQuery selection.
I have a webform with a control panel (#pnlStepOne). The panel includes two textfields "txtFname" and "txtLname". I have a validator setup for each textfield. I have tested the form and all works as desired.
My questions is how do I add a jQuery effect to the panel onclick event only if one (or both) of the textfields ("txtFname" and "txtLname") don't validate. (this effect would "shake" the panel).
And I would like to add another jQuery effect to "flip" the control panel and switch the current one (#pnlStepOne) for another one (#pnlStepTwo) if both fields are validated by the asp:RequiredFieldValidators.
Just a sample code that I will tweak once I have the right If condition.
$(document).ready(function () {
$("#btnStepOne").click(function (event) {
if (**this is the condition that I am missing**)
{
$('#pnlStepOne').css({
background: 'red',
});
}
});
});
You can modify your code to be like this:
$(document).ready(function () {
$("#btnStepOne").click(function (event) {
var fvFname = document.getElementById('client-id-of-your-fvFname-validator');
var fvLname = document.getElementById('client-id-of-your-fvLname-validator');
ValidatorValidate(fvFname);
ValidatorValidate(fvLname);
if (!fvFname.isvalid || !fvLname.isvalid) {
$('#pnlStepOne').css({
background: 'red',
});
}
});
});
Have a rad of my answer to a similar question here:
Enable/Disable asp:validators using jquery
Which has the MSDN link here: http://msdn.microsoft.com/en-us/library/aa479045.aspx
In one of my projects I use a prettifyValidation function, so you could have something like:
$(document).ready(function () {
$("#btnStepOne").click(function (event) {
prettifyValidation();
});
});
function prettifyValidation() {
var allValid = true;
if (typeof Page_Validators != 'undefined') {
// Loop through from high to low to capture the base level of error
for (i = Page_Validators.length; i >= 0; i--) {
if (Page_Validators[i] != null) {
if (!Page_Validators[i].isvalid) { // The Control is NOT Valid
$("#" + Page_Validators[i].controltovalidate).removeClass("makeMeGreen").addClass("makeMeRed");
allValid = false;
} else { // Control is valid
$("#" + Page_Validators[i].controltovalidate).removeClass("makeMeRed").addClass("makeMeGreen");
};
};
};
};
}
This will loop through all controls on the page that have an ASP.NET validator attached, and then add or remove a class depending if they are valid or not.
Obviously from here you can limit the function to a specific control by matching the controlToValidate property, and you can restyle, add controls, change classes but this should hopefully provide you a decent base to work from.
Using jQuery how can I not allow new lines to be inserted (by pressing enter or copying in text) - In semi-pseudo code...
$('textarea').keydown(function(){
$(this).remove_new_lines();
});
Thanks!
EDIT:
Would it be as crude as the following or is there a better way?
function removeNL(s){
return s.replace(/[\n\r\t]/g,);
}
$('textarea').keydown(function(){
$(this).val(removeNL($(this).val));
});
There are two methods to do this: check each character as it is input and return false if you don't want it to show up, or on each change/keyup you can check the entire contents. While the former is more performant, it won't work in situations where the user pastes content in that includes unwanted characters. For that reason, I recommend the latter approach, something like this (which will disallow all vertical whitespace):
With jQuery:
$('textarea').on('keyup', function(){
$(this).val($(this).val().replace(/[\r\n\v]+/g, ''));
});
Or using plain JavaScript (ES2015/ES6):
constrainInput = (event) => {
event.target.value = event.target.value.replace(/[\r\n\v]+/g, '')
}
document.querySelectorAll('textarea').forEach(el => {
el.addEventListener('keyup', constrainInput)
})
Another approach is to wait until the focus leaves the textarea, then apply the transformation. This avoids janky behavior on operating systems using synthetic, conditionally active keyboard controls. The user will see newlines until they leave the field, though, so be aware. To do this, just change the above event listener to listen for blur rather than keyup.
If you're using React, you have it made because it avoids issues with mobile browsers while letting you manage the value as it changes using controlled components:
class TextArea extends React.PureComponent {
state = {
value: ""
};
handleChange = event => {
const value = event.target.value.replace(/[\r\n\v]+/g, "");
this.setState({ value });
};
render() {
return <textarea onChange={this.handleChange} value={this.state.value} />;
}
}
you can check keyCode, if it is equal to 13 simply return false
$('#TEXTAREA').keypress(function(e){
if (e.keyCode == 13) return false
})
$('textarea').keydown(function(e){
var s = $('textarea').val();
while (s.indexOf("\n") > -1)
s = s.replace("\n","");
$('textarea').val(s);
});