Set a parents parent css using javascript/ knockout - javascript

I've got some checkboxes within a table and I want to the css of their parent to be dependent upon whether it's checkbox is checked or not. I can't seem to get this to work and was hoping you could point me in the right direction.
At the moment, I've got a setCss() function on the checkbox 'onclick' method but am getting the resource undefined error.
I've added jsFiddle
function setCss() {
if (this.checked)
$(this).closest('td').className = "selected";
else
$(this).closest('td').className = "deselected";
}

You can do this quite simply using the knockout css binding:
<td data-bind="css: {'selected': selected,'deselected': !selected() }">
<!-- existing content -->
</td>
I've updated your fiddle to work in this way.
This binding means "set the 'selected' class if selected() evaluates to a truthy value, and set the 'deselected' class if it evaluates to falsey".
You could also neaten up your CSS by using a :not(selected) instead of an explicit deselected class

Related

how to set visible = false by knockout

I have posted more detailed question this is much clear and straightforward
here
hello, I am trying to set the value of list element to false by using knockout
this is my HTML
<li>
<a onclick="log(this)" data-bind="visible: true, text: $data"></a>
</li>
is there a way to say something like this :
myViewModel.items()[i].setVisible(false);
Don't set the visible binding to true set it to the variable you define in your viewModel. Also you can access individual elements of an observable array through the foreach binding. Lastly, if you want to use $data you can access the property of the individual array object directly using the "." operator. The documentation I referenced at the end of my post has more information. See below:
<div data-bind="foreach: shouldShowMessageArray">
<div data-bind="visible: $data.shouldShowMessage">
Message goes here.
</div>
</div>
<script type="text/javascript">
var myViewModel;
$(document).ready(function(){
myViewModel = new viewModel();
function viewModel() {
this.shouldShowMessage = ko.observable(false) // Message initially visible
this.shouldShowMessageArray = ko.observableArray([
{shouldShowMessage: ko.observable(true)},
{shouldShowMessage: ko.observable(false)}
]);
}
ko.applyBindings(myViewModel);
});
</script>
Knockout foreach / $data documentation
If you are looking to load the page with a starting value of visible:false, you may run into some issues with the "visible" binding.
I have had trouble with the "visible" binding when I want an element to be hidden on page load, and then made visible after some action taken by the user. You will see a flash of the hidden element while your knockout.js logic loads if you are using the visible binding. If you try to use inline CSS to set display:none on the element, then it will never become visible even when the KO logic results in a visible:true value. This is because KO applies the CSS rules after it has handled changing the element.style.display value.
One solution to this issue that I have found is to set up a CSS class that well set display to none, and then use a data binding to conditionally apply that CSS rule based on an observable.
CSS:
.hideMe { display: none; }
HTML:
<div class="hideContent" data-bind="css: { hideContent: !yourObservable() }">
<p>Content</p>
</div>

toggle div to show hide

I have a simple block of code to hide/show two divs. It works great, the only issue I have is that I need to return the display value to the #MSOZoneCell_WebPartWPQ2 back to table. I have set it to none in the css initially. The last line doesn't seem to take effect.
here is the code:
$(function() {
$('#swap').click(function() {
$('#MSOZoneCell_WebPartWPQ2').toggle();
$('#example_wrapper').toggle();
$('#MSOZoneCell_WebPartWPQ').css('display') == 'table';
});
});
You're using == operator
Try this:
$(document).ready(function(){
$('#swap').click(function() {
$('#MSOZoneCell_WebPartWPQ2').toggle();
$('#example_wrapper').toggle();
$('#MSOZoneCell_WebPartWPQ').attr('style','display:table;');
});
});
you should use .css( propertyName, value )
Set one or more CSS properties for the set of matched elements.
so your last line should be
$('#MSOZoneCell_WebPartWPQ').css('display', 'table');
when you call .css( propertyName )
$('#MSOZoneCell_WebPartWPQ').css('display);
you are Getting the value of said property not setting it
Get the computed style properties for the first element in the set of
matched elements.
Update 1:
please note that Jquery's .show(), .hide() and .toggle() will only work with elements with block display property.
so one way to avoid changing the display property back and forth is to wrap the wanted elements in a div (container) and .toggle() it.
I have created a JSFiddle, I warped each div in a container div with a calss called "toggle" and set initial display value of one of them to "none" using style attribute.
<div class="toggle" style="display:none">
now I toggle between them using this
$('.toggle').toggle();
Update 2:
you can also use .toggleClass() here's another JSFiddle
Add this to your CSS
#example_wrapper.hiddenDiv, #MSOZoneCell_WebPartWPQ2.hiddenDiv {
display: none;
}
add a class to the div you want initially hidden
<div id="MSOZoneCell_WebPartWPQ2" class="hiddenDiv">
toggle the class using this
$(function() {
$('#swap').click(function() {
$('#MSOZoneCell_WebPartWPQ2').toggleClass("hiddenDiv");
$('#example_wrapper').toggleClass("hiddenDiv");
});
});
in this example I'm using a class called "hiddenDiv", if you change it make sure the class name is the same in CSS, HTML and JS.
you are sure you need "==" to set the value? or one "="
Firstly == is an equality check. You should use = to set a value.
Secondly, the css() method setter accepts two parameters. The rule to set and the value itself. Try this:
$('#MSOZoneCell_WebPartWPQ').css('display', 'table');

Edit HTML Table Data cell using Jquery

I have an HTML table, and each cell of the table will have two data attributes. What I'm trying to do is set a button to switch the value being shown in the table between those two attributes.
<table class="table1">
<tbody>
<tr>
<td data-original="A" data-new="B"> A </td>
</tr>
</tbody>
</table>
I'm able to set new text and get attributes outside the table, but whenever I try to within the table I keep receiving an error:
'Uncaught -> TypeError: undefined is not a function'.
I've been receiving this error for a number of commands $('td').text(), .val(), .attr('td'), .getAttribute().
Am I missing a plugin or something for getting and setting values from tables?
ANSWER: I figured out the reason, I was an idiot and didn't mention that there would be numerous TD elements with repeating tags. I eventually used Underscore.js's each method to iterate through them and parts of the below answer to swap the values.
Just made a Fiddle:
$("button").on("click", function () {
$("td").text($.trim($("td").text()) == $("td").data("original")
? $("td").data("new") : $("td").data("original"));
});
to switch between the data-original and data-new values by checking the current text in the td and using a ternary operator.
By using trim() for the initial text issues in case of whitespace are taken care of (as I just noticed that you have whitespace in your example td).
Just in case the button isn't already in the DOM when the page is initially loaded, you have to adjust the on() to delegate the click event from a static parent element to the button, e.g. like this: $(document).on("click", "button", function () { ...
Instead of $(document) every other static parent element can be used.
And as you mentioned that the table will have multiple tds with data-attributes, I've just adjusted the Fiddle to take care of that:
$("button").on("click", function () {
$("td").each(function () {
$(this).text($.trim($(this).text()) == $(this).data("original") ?
$(this).data("new") : $(this).data("original"));
});
});
I don't know how .text() didn't work for you.
To set text inside td elements, you use .text(). To get the data inside data-current or data-new, jQuery has a handy function .data(tag), for example $(sel).data('current').
Here's a fiddle displaying usage of this on your problem.

Knockout binding not working incase of inline editing

I was trying to create an inline editing with knockout.
I created both 'span' and 'input' for same field.
On click of span I hide the span and 'show' the 'input'.
But the change in the input is not reflection on the span.
My Html field
<td>
<span data-bind="text: name" style="display: inline;">Furious Lizard</span>
<input data-bind="value: name" style="display: none;" type="text">
</td>
My code for inline
$('td').on('click', function () {
var spanElement = $(this).find('span');
$(this).find('span').hide();
$(this).find('input').show().select().on('blur', function () {
$(this).hide();
spanElement.show();
});
});
Why isn't the binding working?
JSFiddle
I believe the reason is that eventhough you are binding to an observableArray, the properties on your objects are not themselves observable, so when the property is altered other bound elements aren't notified of the change.
I have edited your sample:
http://jsfiddle.net/879Pk/3/
There you can see that the first element in your data, instead of just being standard properties, they are observable as well:
{
name: ko.observable("Well-Travelled Kitten"),
model: ko.observable(352),
price: 75.95
}
NOTE: I didn't modify the price since you use it below for calculations. For that to work you'd have to modify all prices to be observable, and then while computing actually call the observable (using parenthesis) in order to get the actual value.
In order to avoid having to manually create the observables for each property, Knockout has a plugin called "Mapping" (http://knockoutjs.com/documentation/plugins-mapping.html) which does exactly that, using the following syntax:
var viewModel = ko.mapping.fromJS(data);
Now, regarding your second JSFiddle, I have just made a few corrections:
http://jsfiddle.net/879Pk/5/
When you were adding the element the properties on the new one weren't observable, and you were also missing the parenthesis when evaluating the price property.
you want that the data writen in the input to be visible in the span element as text?
$(this).find('span').html($(this).find('input').val());

How to make an ng-click event conditional?

I have this code inside ng-repeat:
Do something
How to make a condition that the button is disabled when it has class="disabled"?
Or is there a way to do it in Javascript so that will look like:
$('.do-something-button').click(function(){
if (!$(this).hasClass('disabled')) {
do something
}
});
It is not good to manipulate with DOM (including checking of attributes) in any place except directives. You can add into scope some value indicating if link should be disabled.
But other problem is that ngDisabled does not work on anything except form controls, so you can't use it with <a>, but you can use it with <button> and style it as link.
Another way is to use lazy evaluation of expressions like isDisabled || action() so action wouold not be called if isDisabled is true.
Here goes both solutions: http://plnkr.co/edit/5d5R5KfD4PCE8vS3OSSx?p=preview
We can add ng-click event conditionally without using disabled class.
HTML:
<div ng-repeat="object in objects">
<span ng-click="!object.status && disableIt(object)">{{object.value}}</span>
</div>
I use the && expression which works perfectly for me.
For example,
<button ng-model="vm.slideOneValid" ng-disabled="!vm.slideOneValid" ng-click="vm.slideOneValid && vm.nextSlide()" class="btn btn-light-green btn-medium pull-right">Next</button>
If vm.slideOneValid is false, the second part of the expression is not fired. I know this is putting logic into the DOM, but it's a quick a dirty way to get ng-disabled and ng-click to place nice.
Just remember to add ng-model to the element to make ng-disabled work.
Basically ng-click first checks the isDisabled and based on its value it will decide whether the function should be called or not.
<span ng-click="(isDisabled) || clicked()">Do something</span>
OR read it as
<span ng-click="(if this value is true function clicked won't be called. and if it's false the clicked will be called) || clicked()">Do something</span>
You could try to use ng-class.
Here is my simple example:
http://plnkr.co/edit/wS3QkQ5dvHNdc6Lb8ZSF?p=preview
<div ng-repeat="object in objects">
<span ng-class="{'disabled': object.status}" ng-click="disableIt(object)">
{{object.value}}
</span>
</div>
The status is a custom attribute of object, you could name it whatever you want.
The disabled in ng-class is a CSS class name, the object.status should be true or false
You could change every object's status in function disableIt.
In your Controller, you could do this:
$scope.disableIt = function(obj) {
obj.status = !obj.status
}
I had this issue also and I simply found out that if you simply remove the "#" the issue goes off. Like this :
Do something

Categories