Find observable from input-field - javascript

When an input gets focus, I want to pop up a warning if the input is invalid.
The message is in the observable.
So given this code, how do I find the observable bound to it.
$(document).on("focus", "input.invalid", function(){
console.log("ahaaaa!");
//your code here
//dig out observable from this and find the message
//create element with class invalid-message and place it next to this
}).on("blur", function(){
$(".invalid-message").remove();
});
I'm using knockout validation and I only want to show the error message when the field has focus. Other suggestions are welcome.
EDIT:
When I'm using dataFor:
$(document).on("focus", "input.invalid", function(){
console.log(this);
console.log(ko.dataFor(this));
...
I get this in the console:
The underlined observable is the one I'm after.
EDIT2:
I'm working around it like this:
$(document).on("focus", "input.invalid", function(){
var fieldName = $(this).attr("name");
var errorMessage = ko.dataFor(this)[fieldName].error;
...

You can use:
ko.dataFor(this)
which will give you the observable of the current element.
For more details, look here:
Using unobtrusive event handlers

Why not simply use Knockout's event binding to set up handlers for focus and blur? Your handlers will be called with the value of the input as their first parameter; no need to play around with jQuery.

Related

How to use MDC-Web methods (e.g. MDCIconButtonToggle)

I'm having trouble getting the MDC-Web methods/ framework methods to work. Specifically I'm trying to get the MDCIconButtonToggle to work. I have an icon button that can change when clicked. I thought the way I set it up was correct, but it won't toggle when clicked.
import {MDCIconButtonToggle} from '#material/icon-button';
import {MDCIconButtonToggleFoundation} from '#material/icon-button';
const iconButtonRipple = new MDCRipple(document.querySelector('.mdc-icon-button'));
iconButtonRipple.unbounded = true;
function handleToggleButtonClick(){
console.log("clicked");
const toggleBtn = new MDCIconButtonToggleFoundation(expBtn);
toggleBtn.handleClick();
}
var expBtn = document.getElementById("config-audio-button");
expBtn.addEventListener("click", handleToggleButtonClick);
When I run this, every time I click the button "clicked" is displayed in the console, as expected, but the icon doesn't change/ toggle. If I change MDCIconButtonToggleFoundation to MDCIconButtonToggle, I get an error message in console, but the button toggles.
The error message claims that either expBtn.addEventListener is not a function, or that handleClick is undefined.
I've looked through the main docs, and this, but haven't been able to figure out what I'm doing wrong.
Well done on finding a work-around this.
But for someone else that might be stuck with the same problem, here's the clear cut on how you can properly listen to events directly on a component,a button as an example:
Assume we have a button below:
const someButton = new MDCIconButtonToggle(document.querySelector('.someButton'));
We want to alert("yes") when it's clicked. We would the register the event as follows:
someButton.listen('click', ()=> { alert("yes"); });
Note:
The event name is a normal javascript event like "abort", "scroll", "change" etc.
So after even more searching around I found a listen() method in the MDC Dialog documentation. Just ctrl+f for listen and you will find a few examples.
For whatever reason this is the first and only place I've found a listen() method mentioned. If anyone knows where listen() is explicitly documented, I'd be happy to have a link to it to learn more about it.
Below is my solution. I first get an HTML collection of all the toggle-able elements. Then I iterate over them, and add the listen() event listener method to listen for a change event. Once the change event occurs, the buttons will execute handleClick()/ toggle on/off.
// Get "array" of toggle-able arrow dropdowns.
var expandableArrowButtons = document.getElementsByClassName("mdc-icon-button add-margin-bottom");
// Iterate over all 3 expandable arrow icon buttons, and listen for a change event.
[].forEach.call(expandableArrowButtons, function(element){
const toggleBtn = new MDCIconButtonToggle(element);
toggleBtn.listen('MDCIconButtonToggle:change', function(){
console.log("clicked");
const tb = new MDCIconButtonToggleFoundation(toggleBtn);
tb.handleClick();
});
});

jQuery Text Editor (jqte), using change event

I am trying to write some code for change() event using jQuery Text Editor (jqte), I have two functions which give jqte functionality to textarea's
One for editors loaded with JavaScript, when clicking some elements in a page:
function onLoadEditor(){
jQuery(".comment-editor").jqte({
// some jqte params, such as fsize: false,indent: false...
change: function(){ observeEditor(); }
});
}
And other, generic function, for pages with one single editor
jQuery(function() {
jQuery(".comment-editor").jqte({
// some jqte params, such as fsize: false,indent: false...
change: function(){ observeEditor(); }
});
});
I want to access the id of the concrete textarea (all textareas in the page have an id) which has fired the change() event
How should I write observeEditor() function to achieve this? Or... how I should define the function in jqte change property?
After reading this jQuery blur event with ID and value I have solved it, with following code (simplified)
function onLoadEditor(){
jQuery(".comment-editor").each(function(idx, elem) {
jQuery(this).jqte({
// some jqte params, such as fsize: false,indent: false...
change: observeEditor(elem.id),
});
}
jQuery(function() {
onLoadEditor();
});
But now I have another problem...
As you can read in the original question, onLoadEditor() is called when clicking some elements in a page. Then another javascript function jsComment() is called, builds a form (with a textarea.comment-editor field included) and it is rendered this way
function jsComment(){
...
var form = '<div class="comments_wrapper ... ';
jQuery(form).insertAfter(some_element).fadeIn('fast');
onLoadEditor();
}
Problem is change() event is being fired only once, when form fades in, while the idea is the opposite, event should fire when user adds some text, not when appearing... Any tips?
UPDATE
After reading Event binding on dynamically created elements? I have solved it this way
function onLoadEditor(){
jQuery('.comment-editor').each(function(idx, elem) {
jQuery(this).jqte({
// some jqte params, such as fsize: false,indent: false...
});
jQuery(document).on('change',
jQuery('.comment-editor'),
function(){
observeEditor(elem.id);
}
);
});
}
jQuery(function() {
onLoadEditor();
});
Although finally I am not using change() event, as it was being fired constantly. Performing better with keyup() & paste(), for instance

How to associate onClick with a dynamically generated div with dojo?

I am using dojo 1.9.2, and is trying to attach an onClick function on a piece of HTML code that I created on the fly, like this:
clickableDiv = "<div data-dojo-attach-point=\"testBtn\">Click Me!</div>";
self.racks.innerHTML = clickableDiv;
and then I want to give it an onClick function after, so right below the code I putted:
connect(this.testBtn, "onclick", alert("You Clicked It!"));
For some reason not only this wont work, when I refresh the page the alert "You Clicked It!" would pop up without me clicking anything...
I Have to use this dojo version, it's part of the requirement...
Any idea or suggestion on how I can go about doing this?
Well, dojo is part of javascript, so you can probably use some javascript function, for example:
clickableDiv = "<div id=\"testBtn\">Click Me!</div>";
self.racks.innerHTML = clickableDiv;
document.getElementById('testBtn').onclick=function(){alert("You Clicked It!");};
The code mentioned in the question is correct, except for one mistake. The "onclick" event needs a handler function, not the code directly. So, enclose that alert statement by a function.
connect(this.testBtn, "onclick", function(){alert("You Clicked It!")});
Or a separate function elsewhere can be linked here a handle by passing the function or just name of the function.
function abcd() {
alert('You clicked It');
}
connect(this.testBtn, "onclick", "abcd");//same as connect(this.testBtn, "onclick", abcd);
When providing an event handler (or a callback in general), you have to provide the function as reference. When you use:
connect(this.testBtn, "onclick", alert("You Clicked It!"));
You're actually saying that you want to connect the onClick event handler to the return value of that alert(). What you actually want is like the other answers already explained by wrapping it inside a function that is passed through by reference:
connect(this.testBtn, "onclick", function() {
alert("You Clicked It!")
});
However, since you're using data-dojo-attach-point which is generally used in widgets, you could also define your event handler in a similar way, for example:
clickableDiv = "<div data-dojo-attach-point=\"testBtn\" data-dojo-attach-event=\"onClick: myClickHandler\">Click Me!</div>";
Then you can just write a function called myClickHandler in your widget that shows the alert, for example:
myClickHandler: function() {
alert("You Clicked It!");
}
He's using dojo 1.9.2. connect is deprecated and he should be using on:
on(this.testBtn, "click", function(){
alert("You Clicked It!")
});
Your data-dojo-attach-point won't get picked up in dynamically placed HTML. You would put that in a custom widget template to provide the actual reference to your node/widget. If you did have that element in a template to begin with, you could simply use the attribute on your element:
data-dojo-attach-event="onClick: someFunction"

Declaratively setting jQuery.Data property for a HTML link

Assuming I have a HTML link in my rows inside a datagrid or repeater as such
DoSomething
Now also assuming that I have handled the click event for all my DoSomethings in jQuery as such
$(".DoSomething").click(function (e) {
//Make my DoSomethings do something
});
What is the correct technique for passing data to the click event that is dependent on the link clicked?
Without jQuery you would typically do something like this.
DoSomething
but this technique obviously doesn't work in the jQuery case.
Basically my ideal solution would somehow add values for to the jQuery.Data property for the link clicked but doing so declaratively.
Use HTML5 data- attributes. jQuery support is built-in for 1.4.3+
http://api.jquery.com/data/#data2
click here
$('.product-link').click(function (e) {
alert($(this).data('productid'));
});
You could use the attr() function.
http://api.jquery.com/attr/
$("#Something").attr("your-value", "Hello World");
$("#Something").click(function (e) {
//Make my DoSomethings do something
var value = $(this).attr("your-value");
alert(value); // Alerts Hello World
});
your question was not clear to me but may be this will help
$(".DoSomething").click(function (e) {
//Make my DoSomethings do something
$(this).data("key","value");
//later the value can be retrieved like
var value=$(this).data("key");
console.log(value);// gives you "value"
});

Observing events on dynamically inserted objects in the DOM

On load, I add a desired behavior on all textareas on a page.
Event.observe(window, 'load', function() {
$$('textarea').each(function(x) {
x.observe('keydown', dosomethinghere)
});
});
This works because the textareas are already in the DOM, but how should I treat textareas that are dynamically added after the page loads (ex: if I have a button that says "Add More"). I would like these newly created textareas to have the same behavior.
The way I do it is by just observing the new textarea when I add it, like this:
function doSomethingWithTextAreas(){
//do something.
}
document.observe("dom:loaded", function() {
$$('textarea').each(function(s){
s.observe('keydown', doSomethingWithTextareas);
});
$('add_more').observe('click', function(){
textarea = new Element('textarea');
textarea.observe('keydown', doSomethingWithTextareas); //Observes the new textarea.
Element.insert($('textarea_container'), {bottom:textarea});
});
});
Consider using jQuery Live.
$.live() would work as STAii mentions, but there is discussion of implementing a similar function in prototype as well. That would probably be of more benefit so you don't have to add another library.
Well, the answer is a bit tricky. The only way to do this is to maintain a cache of events listeners for your textareas. When adding a new textarea to your page, you would need to call Event.stopObserving on all your cached events. You would then call your $$('textarea').each(...) code again to bind to all the elements.
Thankfully, someone has done this for you already in a very handy lightweight prototype extension called lowpro: http://www.danwebb.net/2006/9/3/low-pro-unobtrusive-scripting-for-prototype
You can do what you wish as simply as:
Event.addBehavior({
'textarea:keydown': function(e) {
dosomethinghere(); // e.g. this.hide();
}
});
Then whenever you add a new textarea dynamically, you simply call Event.addBehavior.reload();
I should point out that "e" is the Event object, and "this" is the element inside the context of the function(e) {} definition.
A nice way of doing this is to have the javascript function which adds the text areas fire an event which any other function can observe and act on. So:
function add_textarea() {
// Code creates a new <textarea> and adds it to the page
var textarea = new Element("textarea");
$("some-form").insert(textarea);
textarea.fire("textarea:add")
}
document.observe("textarea:add", function(event) {
event.target.observe('keydown', dosomethinghere);
});
This allows your 2 functions--one that adds a new textarea and one which attaches observers--to be loosely coupled and not know anything about each other. One simply needs to fire a custom event which the other can observe.

Categories