I'm binding my ViewModel's isChecked property to a data-whatever attribute. The value of this attribute is changed by jQuery:
$element.data('whatever', "true")
KnockoutJs doesn't notice this change and my ViewModel's property doesn't change. How can I make KnockoutJs notice it?
I tried something like that, but it didn't work:
JavaScript "view layer" script:
$element.data('whatever', "true")
$element.trigger("myCustomEvent")
The view:
<div data-bind="attr: { 'data-whatever': isChecked, event : {myCustomEvent: checkedFunction} }">
checkedFunction is just an empty method in the ViewModel to fit the event binding syntax. It still looks like KnockoutJs is not listening to myCustomEvent.
EDIT
As Fisherman suggested I used $element.attr instead of $element.data, but it still doesn't work:
<html>
<div id="test" data-bind="attr: { 'data-whatever': isChecked }">my div</div>
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="http://knockoutjs.com/downloads/knockout-3.2.0.js"></script>
<script>
var vm = {
isChecked : ko.observable("one"),
};
$(function () {
ko.applyBindings(vm);
console.log($('#test').attr('data-whatever')); // "one"
$('#test').attr('data-whatever', 'two');
console.log($('#test').attr('data-whatever')); // "two"
console.log(vm.isChecked()); // // "one" again, thouh it should be "two"
});
</script>
</html>
even if I add the event:
<html>
<div id="test" data-bind="attr: { 'data-whatever': isChecked, event :{ myCustomEvent : aFunction }}">my div</div>
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="http://knockoutjs.com/downloads/knockout-3.2.0.js"></script>
<script>
var vm = {
isChecked : ko.observable("one"),
aFunction : function(){ }
};
vm.isChecked.subscribe(function(){
console.log("hit the event"); // never happens
});
$(function () {
ko.applyBindings(vm);
console.log($('#test').attr('data-whatever')); // "one"
$('#test').attr('data-whatever', 'two');
$('#test').trigger('myCustomEvent');
console.log($('#test').attr('data-whatever')); // "two"
console.log(vm.isChecked()); // "one" again, though should be "two"
});
</script>
</html>
You can't set the data attribute with jQuery's data() functions. Have a look at the documentation: http://api.jquery.com/data/
The data- attributes are pulled in the first time the data property is
accessed and then are no longer accessed or mutated (all data values
are then stored internally in jQuery)
http://jsfiddle.net/prpL0x3j/
console.log($('#test').data('whatever'));
// one
$('#test').data('whatever', 'two');
console.log($('#test').data('whatever'));
// two
Check out the attribute of the DOM element in the developer bar - it does not change, even though jQuery's data value changed.
Consider using the attr() function: http://api.jquery.com/attr/
$element.attr('data-whatever', "true")
Related
If I have the following piece of code:
<button id="btnOne" data-football="Mitre">Press Me</button>
How would I get the name of the data tag, so in this case it would be 'data-football'. I know how I would get the value but would like to know how I can get the name of the data-tag - in this case data-football when the button is pressed.
i.e,
$(document).on("click", "button", function(){
// Get the name of the attribute (data-football - not the value);
});
Thanks.
You can use attributes property for getting the all attributes of a HTML tag
<div id="_id" data-football='test'></div>
<script>
const attrs = document.getElementById('_id').attributes
const keyName = attrs[1].nodeName // will be data-football
</script>
Try one of the following.
$(document).on("click", "button", function(){
$(this).data('data-football')
});
Or
$(document).on("click", "#btnOne", function(){
$(this).data('data-football')
});
Read More about jQuery data
am learning jquery but am having a hard time figuring out how to set two attributes and give it a call back function at the same time.... i have te code to how to set multiple attributes and i have the code to how to give it a callback function but how do i pu them together in one...
here's the code for setting multiple atrributes:
<script>
$(document).ready(function(){
$("button").click(function(){
$("#w3s").attr({
"href" : "http://www.w3schools.com/jquery",
"title" : "W3Schools jQuery Tutorial"
});
});
});
</script>
</head>
<body>
<p>W3Schools.com</p>
<button>Change href and title</button>
<p>Mouse over the link to see that the href attribute has changed and a title attribute is set.</p>
And here's the code with a callback function
<script>
$(document).ready(function(){
$("button").click(function(){
$("#w3s").attr("href", function(i,origValue){
return origValue + "/jquery";
});
});
});
</script>
</head>
<body>
<p>W3Schools.com</p>
<button>Change href Value</button>
<p>Mouse over the link (or click on it) to see that the value of the href attribute has changed.</p>
so how do i put them together? thanks in advanced to anyone who takes the time.
You can use chaining (more about jQuery chaining here: http://www.jquery-tutorial.net/introduction/method-chaining/), like this:
<script>
$(document).ready(function(){
$("button").click(function(){
$("#w3s").attr("href", function(i,origValue){
return origValue + "/jquery";
}).attr('title','Tutorial');
});
});
</script>
<body>
<p>W3Schools.com</p>
<button>Change href Value</button>
<p>Mouse over the link (or click on it) to see that the value of the href attribute has changed.</p>
http://jsfiddle.net/FHD84/
Sure, you can do in this way (store the function in a variable and then assign it to attribute)
working example --> http://jsfiddle.net/HKEeB/2/
$(document).ready(function(){
$("button").click(function(){
var func= function(i,origValue){
return origValue + "/jquery";
};
$("#w3s").attr({
"href" : func,
"title" : "W3Schools jQuery Tutorial"
});
});
});
My understanding of what you were trying to do is:
When the button is clicked, the <a> tag will change its href to the jQuery page.
When that link is clicked, the original values will be reset
If this is correct, here is how I would do it:
//-- $(function () {...}) is shorthand notation for $(document).ready(function () {...});
$(function () {
//-- I stored the lookup for #w3s to prevent duplicate calls to $()
var $link = $('#w3s');
//-- store the original attribute values using jQuery data()
$link.data({
'href': $link.attr('href'),
'title': $link.attr('title')
});
//-- This is essentially the same as your $('button').click(), but using delegation
$(document).on('click', 'button', function () {
//-- update the attributes
$link.attr({
'href': 'http://www.w3schools.com/jquery',
'title': 'W3Schools jQuery Tutorial'
})
//-- on click, reset the original values
$link.on('click', function (event) {
//-- event.preventDefault() will stop the link from performing its default functionality
//-- in this case, that would be following the href
event.preventDefault();
//-- pull the original values from jQuery data()
$link.attr({
'href': $link.data('href'),
'title': $link.data('title')
});
});
});
});
JSFiddle link: http://jsfiddle.net/9x56L/
Note: I disabled the link in this example. I am not sure what the context of this is, but redirecting away from the page is probably not the intended result.
I am trying out this simple code. What I want is that when a paste event is fired on the second input textbox, it should be cleared, after copying its contents, removing the readonly attribute of the previous textbox, and pasting it there. however, nothing is happening.
The paste event is fired alright, because if I replace the code in the timer by a simple alert, it works. Can anyone tell me what's wrong here?
<!DOCTYPE html>
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js">
</script>
<script>
$(document).ready(function(){
$(".boo").bind("input paste",function() {
elem = this;
setTimeout(function() {
$(".foo").removeAttr("readonly");
$(".foo").text($(elem).text());
$(elem).text("");
},100);
});
});
</script>
</head>
<body>
<input class = 'foo' type = 'text' /><input class = 'boo' type = 'text' />
</body>
</html>
First of all, you should use .val() instead of .text() with input control.
$(document).ready(function () {
$("input.boo").bind("paste", function () { //also changed the binding too
var elem = $(this);
setTimeout(function () {
$(".foo").val(elem.val());
elem.val("");
}, 100);
});
});
Also, your bound event(s) were fired twice when text is pasted in the control. That's because, you have bound both input and paste events to the element(s) with "boo" class.
So here, instead of:
$(".boo").bind("input paste", function() {});
Use this:
$("input.boo").bind("paste", function() {});
This will bind only the paste event to input elements with "boo" class.
See updated jsFiddle example.
Here is my issue:
I am creating dynamically a button with an onclick function like this:
$("#test).html('<input type="button" value="Close" onclick="remove('+param1+','+param2+');" />');
The parameters are well read but the function is not trigger, and I've got this error message:
"bob is not defined" when bob is the string value of the param1.
Apparently it seems that bob is read as a variable when it should be read as a string, but I don't understand why.
Thanks much for your help!
That's because this string right here:
'onclick="remove('+param1+','+param2+');"'
Will look like this in the end:
'onclick="remove(foo, bar);"'
You probably want it to look like this:
'onclick="remove(\'foo\', \'bar\');"'
So change it to this:
'onclick="remove(\''+param1+'\', \''+param2+'\');"'
You could also do this:
$("#test").html('<input type="button" value="Close" />').find('input[type=button]').click(function () {
remove(param1, param2);
});
Edit: I also noticed that you were missing one " from your $()-call: $("#test) should be $("#test").
I can suggest you this
<script type="text/javascript">
//<![CDATA[
var i = 0;
$(function () {
$("#lnkAdder").click(function () {
// appending new item
$("#Container").append(
$("<a>").attr({ "href": "javascript:;" }).text("Click me").click(function () {
var data = ++i;
alert("I'm clicked, I'm number " + data);
})
);
});
});
//]]>
</script>
Add item
<div id="Container"></div>
The key here is the javascript closure.
As you can see there a link called lnkAdder. It is responsible to add anew item into the container. On click it appends a new item into the container. While appending you use jQuery API and create a new element, add attributes and add event listener. In the event listener body you copy the value into an internal variable. They use it as appropriate.
I have an <input> field in my web page, and I want to add a particular method on it, let say fooBar().
Here is what I do:
<input id="xxx" .../>
<script type="text/javascript">
$("xxx").fooBar = function() { ... };
</script>
This works well. However, for some reasons I will not detail here (in fact the HTML is generated by JSF components), the <script> will be declared before the <input> tag.
So in others words, I will have that in my HTML:
<script type="text/javascript">
$("xxx").fooBar = function() { ... };
</script>
<input id="xxx" .../>
So of course this code will not work correctly, as the script will try to get ($("xxx")) and modify an element that does not exist yet.
If I want to stick on the exact order of these two tags, what is the best way to accomplish what I want?
Edit
In my case, $ refers to prototype, but I am also using jQuery in my application. And I must be compatible with IE6 :o(
You need to run your script after the document is loaded. With jQuery you'd do that with:
$(document).ready(function () {
//do stuff here
});
I can't tell which library you're using here, but they all have an equivalent of jQuery's document ready.
Here's the prototype equivalent:
document.observe("dom:loaded", function() {
// do stuff
});
Try putting your code in load event:
$(window).load(function(){
$("#xxx").fooBar = function() { ... };
});
If the code has to be directly before the input, you can check if it has loaded after a certain period of time.
<script type="text/javascript">
//Sets up a function to execute once the input is loaded
f = function ()
{
//Checks if 'xxx' exists (may vary between frameworks)
if ($("xxx") !== undefined)
{
$("xxx").fooBar = function() { ... };
//Escapes the timer function, preventing it from running again
return true;
}
//If still not loaded check again in half a second (0.5s or 500ms)
setTimeout(f,500);
return false;
}
f();//Initialize the timer function
</script>
<input id="xxx" .../>
Instead of adding a method to the dom node, why not make it a separate function, so instead of
$("xxx").fooBar = function() {
doStuff(this);
};
you would have something like
function xxx_fooBar () {
var me = document.getElementById('xxx');
doStuff(me);
};
Another suggestion: If you can add attributes to the <input> element, you could do something like this...
<script>
function xxx_init (e) {
e.fooBar = function () {
doStuff(this);
};
}
</script>
<input onload="xxx_init(this)" id="xxx" .../>
Or you could do as others suggest and attach the scripts to the window.onload event.