How to focus a DOM child element from a Meteor event handler - dom

I have an event handler that sets a session variable to change the content within a DOM element -- in this case a table cell.
'dblclick td.itemName': function (evt) {
Session.set("editItemName",true);
evt.currentTarget.children[0].focus();
},
<td class="itemName">
{{#unless editItemName}}
{{name}}
{{else}}
<input class="editItemName" type="text" value="{{name}}" style="width:100px;">
{{/unless}}
</td>
Pretty straight forward...
However evt.currentTarget.children doesnt work. Once the input takes place of the text, I'd like to make it automatically focus... The meteor docs say that this is a DOM object so its weird that the children function doesnt work...
Thanks
Chet

When you double click, and your function runs, you set the session editItemName to true, and then you're trying to give the input-element focus, but the template has not been re-rendered yet, so the input-element hasn't been created (the template will be re-rendered some time after your function returns). In other words: evt.currentTarget.children[0] is not a reference to the input-element.
Possible solution 1
In HTML 5 there's an attribute called autofocus, which you can use (at least I can in Chrome). Just add it to the input-element:
<input autofocus="autofocus" class="editItemName" type="text" value="{{name}}" style="width:100px;">
Possible solution 2
Otherwise you have to focus it with JavaScript when the template been rendered and your input-element exists in it:
Template.yourTemplate.rendered = function(){
var input = this.find('.editItemName')
if(input){
input.focus()
}
}

You are trying to set the focus to a DOM element that has not been rendered yet.
The issue has been bothering me for a while. I have tried to use the autofocus='autofocus' HTML attribute: it has no effect in Firefox, and in Chrome, it seems to only work the first time the element is rendered.
So we need a handler that is called just after the template is rendered, in order to set the focus with javascript. Template.templateName.rendered looks like the way to go, but there is an issue:
What didn't work for me:
<template name="itemName">
<td class="itemName">
{{#unless editItemName}}
{{name}}
{{else}}
<input type="text" value="{{name}}">
{{/unless}}
</td>
</template>
Template.itemName.rendered = function()
{
this.$('input').focus()
}
When doing this, Template.yourTemplate.rendered seems to fire only the first time you click on the item (you get the focus correctly only once).
What worked for me:
<template name="itemName">
<td class="itemName">
{{#unless editItemName}}
{{name}}
{{else}}
{{> itemNameEdit}}
{{/unless}}
</td>
</template>
<template name="itemNameEdit">
<input type="text" value="{{name}}">
</template>
Template.itemNameEdit.rendered = function()
{
this.$('input').focus()
}
Any explanation from a Meteor expert?

As #Chet pointed out, Template.[name].rendered no longer fires whenever a template is updated, but instead, only when the template is first rendered, and only once.
One can pass a callback to Tracker.afterFlush which will fire every time the template is updated.
i.e. all reactive updates are processed
Template.myTemplate.events({
'dblclick td.itemName': function(e, t) {
Session.set("editItemName",true);
Tracker.afterFlush(function() {
this.find('input').focus();
}.bind(t));
}
});

Related

Submitting a Form using Jquery

Okay so I am converting some code to jQuery and currently the js is just changing the focus to a button with the target id using whenever you press enter or double click in a <select> tag. document.getElementById.focus() and then document.getElementById.click() and returning true to submit this form. Just looking for some example on how to do same thing using jQuery instead. I understand that there is a .keypress() and a .dblclick() function in jQuery and thats what I think I should be using but passing the values of the input box or the select values are a little difficult since there are multiples of each in the form. FYI this is a search page that sends SQL to an oracle database.
Update-
$(document).ready(function(){
$('form').submit(function(){
$(this).keypress()
if(event.which ==13){
}
});
});
This is what i have so far not sure if i am on the right track or not.
so here is an example of how the form is.
<form>
<tr>
<td nowrap="nowrap"><b> Search by Number </b></td>
<td style="vertical-align:top"><input type="text" name="revisor_number" value=revisor_number>" size="55" maxlength="100" /><br/><span style="font-size:75%">commas between numbers (10,15,20), dash for range(10-20)</span><br/></td>
<td> <input type="submit" name="submit_number" id="submit_number" value="GO"/></td>
</tr>
<tr>
<td style="vertical-align:top" nowrap="nowrap"><b> Search by Type </b></td>
<td>
<select name="subtype[]" size="3" multiple="multiple" onkeypress="keyPress(event, 'submit_subtype');" ondblclick="keyPress(event, 'submit_subtype');">
<option value="">>--- All ---</option>
<td style="vertical-align:top"> <input type="submit" name="submit_subtype" id="submit_subtype" value="GO"/></td>
You need to move it outside of your submit function, replace it with:
$('input, textarea').keypress(function(e) {
if(e.which == 13) {
$(this).blur();
$('#submit').focus().click();
}
});
Assuming '#submit' is the ID of your button.
I don't know if i understand what you want,
but submitting a form with a button in jQuery is something like :
$('button').on('click', function(){
$('yourForm').submit();
});

Meteorjs - select DOM of a template from another template

I have the following
<div id="header">
{{> header}}
</div>
<div class="hidden content_box">
{{> content}}
</div>
"content_box" is hidden at the start.
template "header" has a single button.
<template name="header">
<button id="display_content">Click to display content</button>
</template>
template "content" is just a simple div
<template name="content">
It's me, content
</template>
When I click on the button in the header, I want to "show" the content_box.
How do I achieve this? - or better yet, what is the best way to achieve this type of effect where you need to access the DOM of a template from an event of another template?
Template.header.events "click button#display_content": (e) ->
Template.content.show() ?????
I don't know if it is the best way to do it, but in similar situations what I've done before is to use a session parameter to store the show/hide status of the div. In your click event, you then only need to change the value of the session flag. In the template of the div you want to show/hide, you just return the class name.
Example in JS:
Template.header.events({
"click button#display_content": function () {
Session.set('contentShow', true);
}
});
Template.content.className = function (input) {
return Session.equals('contentShow', true) ? '' : 'hidden';
};
Html
<template name="content">
<div class="{{className}} content_box">
It's me, content
</div>
</template>
You'd need to initialise the session flag to false in Meteor.startup() for example Session.set('contentShow', false);. As session is reactive, the div class name will be re-evaluated automatically when you change the session flag.

jQuery selector for .parent().parent()

Given a series of a form's Label and Input elements like:
<div class="labelEditwrap">
<div class="editor-label">
<label for="Address">Address</label>
</div>
<div class="editor-field">
<input class="text-box single-line" id="Address" name="Address" type="text" value="" />
<span class="field-validation-valid" data-valmsg-for="Address"></span>
</div>
</div>
I'm trying to select the outer most div when the textbox gets focus so I can highlight both label and input:
$("input").focus(function () {
$(this).parent().parent().addClass("curFocus")
});
I've tried a few combinations including:
$(this).parent().parent() // seems the most obvious
$(this).parent().parents("div:first")
Another question here asking about .parent().parent() was solved by finding a syntax error unrelated to the selector. However, in this case, I can see my hightlighter class if I go up only one parent level (only highlights the editor's div) and also if I climb 3 levels (highlights the container holding the full form).
thx
OK....its not the selector. All the suggested alternates (and the original) are correctly 'selecting' the outside wrapper div. The problem was the CSS and how Floats are being applied to the Label and Editor divs. This CSS will produce correct highlighting and also let the label/editor fields align themselves correctly. [whew]
Up to you guys the best way to close/edit/retitle the question in hopes of helping other avoid my 4 hour toubleshooting ordeal.
-highly appreciate the time taken-
Possible Solutions:-
$('.text-box').live('focus', function(){
$(this).parent().parent().css('border', '1px solid red');
});
$('.text-box').live('blur', function(){
$(this).parent().parent().css('border', 'none');
});
or
$('.text-box').bind('focus', function(){
$(this).parent().parent().css('border', '1px solid red');
});
$('.text-box').bind('blur', function(){
$(this).parent().parent().css('border', 'none');
});
The solution you suggested should work correctly
$(this).parent().parent();
I think the issue here is that your event is being bound before there is an object to bind it to. Have you bound your function on document ready?
Something like:
$(function(){
$("input").focus(function () {
$(this).parent().parent().addClass("curFocus")
});
});
Otherwise using 'live' or 'on' to bind the event will work dynamically.
so like:
$('input').live('focus', function(){
$(this).parent().parent().addClass("curFocus");
});

Why is FilteringSelect in declarative dijit form causing invalid submit?

Help me understand this.
Isn't dijit.form.FilteringSelect (extended from ValidationTextBox) supposed to have property required = false by default?
Why is it that simply including a FilteringSelect in a declarative form like so below automatically results in dijit.form.Form.isValid() == false?
Even manually setting the filteringselect's required prop to false results in an invalid form submit. I feel like there's something I'm missing here.
I'm Using dojo toolkit version 1.6.1.
<!-- form.html -->
<form id="form" dojoType="dijit.form.Form">
<table>
<tr>
<td id="friend">
<select name="friend" id="friend-input" dojotype="dijit.form.FilteringSelect"></select>
</td>
</tr>
<tr>
<td>
<input type="submit" id="submit-input" value="Submit" label="Submit" dojotype="dijit.form.Button">
</td>
</tr>
</table>
</form>
/* form.js */
dojo.require("dijit.form.Button");
dojo.require("dijit.form.FilteringSelect");
dojo.require("dijit.form.Form");
dojo.ready(function() {
var form = dijit.byId("form");
var friendInput = dijit.byId("friend-input");
friendInput.required = false;
dojo.connect(form, "onSubmit", function(event) {
event.preventDefault();
if (form.isValid()) {
alert("Ready to submit data: " + dojo.toJson(form.get("value")));
} else {
alert("Form is not valid.");
}
});
});
Like Frode mentioned, we need to set the required to false.
But, lots of fields might be used. Not a good idea to set 'required' for each, in the dojo.ready section.
<select name="friend" id="friend-input"
dojotype="dijit.form.FilteringSelect" required="false"></select>
The better way is to mention it as attribute in the html itself. Let me give an example why it is better.
If the field is included in a tab, and if the tab is refreshed on certain actions, the html will be arsed again. So, in that scenario, the required will be true again for that field. So, therefore, provide it in the html declaration of the widget itself to avoid these scenarios.

jquery - how to select element and all children, except specific child

I have a .mouseover() event triggered on all elements of class 'node'. It works fine, and is also triggered when user hovers over any child of .node. This works well for me, however, I do not want this event triggered if the user mouse overs a specific child, namely, an image.
Why is the selector $('.node :not(img)') not working?
Oddly enough, it does work when I try it out at http://www.woods.iki.fi/interactive-jquery-tester.html, but not in my actual implementation.
My html:
<div id="container">
<div class="node" id="abc">
<h2>Node Title</h2>
<div class="nodeChildren">
<h3 id="a1">Some text</h3>
<h3 id="a2">Some text</h3>
<h3 id="a3">Some text</h3>
</div>
<img src="diagonal-left.gif" />
</div>
</div>
My jquery:
//start with third tier not visible
$('.nodeChildren').hide();
$('.node :not(img)').mouseover(function(){
$(this).children('div').show();
});
$('.node').mouseout(function() {
$('.nodeChildren').hide();
});
});
My failed attempts
$('.node :not(img)') //no mouseover is triggered
//for the following selectors, the mouseover event is still triggered on img
$('.node').not('img')
$('.node').not($('.node').children('img'))
Thanks for any help :)
The problem is the event is "bubbling" up to the parents which triggers the mouse over. You need to add a mouseover to the img to stop this.
$(".node img").bind("mouseover", function(event) {
event.stopPropagation();
});
in the callback function of bind, you can check the target. in your case, Something like this
$(".node").bind('mouseover',function(e){
if(e.target.nodeName != 'IMG'){
$(this).children('div').show();
}
});