jQuery: execute function on matched elements returned via Ajax - ruby-on-rails-3

This jQuery selector matches a Rails 3 HTML form for a new model: $('form[id^="new_"]')
I'd like to have a simple focus function run each time a matching form loads. Sometimes the forms are loaded via a simple GET but also via Ajax. In the latter case, the content returned can be either HTML or escaped JS.
I was hoping jQuery would be able to match all cases via the selector, .on(), and the "load" event, but I can't seem to make that work for ANY case. Code:
$(document).ready(function() {
$('form[id^="new_"]').on("load", function(){
console.log("Matched!")
});
})
Any ideas?
Thanks Justice. I'm afraid I wasn't able to get your code to work. I'm using the following callback with the new custom event defined outside it as shown and I don't think the $('form') is triggering the event.
$('.shows-children').bind('ajax:success', function(evnt, data, status, xhr){
var boxSelector = '#' + $(this).data("shows");
$(boxSelector).html(xhr.responseText);
$('form').trigger('customevent');
});
$(document).on('customevent','form[id^="new_"]', function(){
console.log('Matched!')
});
(I'm surprised it seems more involved than expected to have jQuery act on HTML returned in an Ajax response.)

$(document).on("change","form[id^=\"new_\"]" function(){
console.log("Matched!")
});
For delegation, you want to delegate the original selector to a parent, as the event will bubble up.
However, load does NOT bubble up. In this case, change may suffice, but it'll trigger and attempt to see if the delegate is valid every time the document changes.
I would then suggest that you create a custom event after AJAX loads for the form.
Example:
$(document).on("customevent","form[id^="new_"]" function(){
console.log("Matched!")
$.ajax(url, function(response){
//success
$(document).append(response);
$('form').trigger('customevent');
});
});
HTH

Related

.dataTable() pagination breaks class .click responsiveness

When I construct a normal table and give each column a distinct class, the classes are responsive for all rows. However, when I call .dataTable() on my table, only page 1 of the paginated results is responsive. Page 2 and beyond are not responsive.
Example code:
var dataTableID = 'questionsTable';
var columns = {
questionID: "ID",
CategoryString: "Cat",
difficultyLevel: "Diff",
timesAsked: "Qty",
questionText: "Question Text"
};
// my own little function that builds the HTML table. <TD> classes are column names
//-- eg .questionID, .CategoryString, etc
var tableHTML = makeTable(questions, columns);
$('#' + dataTableID).html(tableHTML);
// dataTable works nicely except only page 1 .click is responsive!
$('#' + dataTableID).dataTable();
// works fine if I remove .dataTable() above. ONLY works for first page of results
// if I keep .dataTable()
$('.questionID').on("click", function() {
alert('Click called');
});
When using pagination, dataTables change the visible rows by moving <tr>'s back and forth the DOM. $('.questionID').on is processed for columns on the first page only, since those columns is the only visible (accessible) columns after initialization.
So you must assign the click handler (or whatever you want to attach) on page change rather than on initialization. Here by the use of the fnDrawCallback event :
function clickHandler() {
alert('Click called');
}
var dataTable = $('#example').dataTable({
fnDrawCallback : function() {
$('.questionID')
.off("click", clickHandler)
.on("click", clickHandler)
}
});
see demo -> http://jsfiddle.net/U9Jmg/
Notice the use of .off. dataTables actually moves the <tr>'s back and forth the DOM and a table in memory, including any attached events. If previous attached events is not released, we will end up in multiple alerts for each column.
Also note I have only used only one class .questionID for all the columns in the demo. The example is 1.10.x but this works in 1.9.x as well.
As you can see of the comments below, you could also use a delegated event instead of direct event binding. It changes the setup and perhaps it is not suitable for your needs, but anyway :
$('#example tbody').on('click', '.questionID', clickHandler);
see demo -> http://jsfiddle.net/L29Dq/
When using DataTables pagination feature (as you do), only the first page of your data is present in the dom when you attach the click event handler. That's why the handler is attached to the elements on the first page and only to those elements.
When going to another page, DataTables will redraw the table which in effect removes the attached event handler. You have to reattach the event handler after every table draw. The drawCallback option should be the right place for that:
$('#' + dataTableID).dataTable({
"drawCallback": function(settings){
$('.questionID').on("click", function(){
alert('Click called');
});
}
});
As #davidkonrad pointed out in his answer, the click handler should be removed (using off) to avoid handling the event multiple times.
The DataTables page has a section on this as well: Advanced Initialisation - DOM/jQuery events. The example there uses delegated events.

Enquire.js: Don't get the purpose of "setup" handler

I don't quite get the idea behind enquire.js' "setup" handler.
Case:
I want to load content through ajax once when you're not in a small viewport (lt 600px).
Naturally I would do enquire.register('(min-width: 600px)', { setup: myFunction });.
Problem:
Now I tested this multiple times but the setup handler also gets fired when you're in a small screen, which totally eliminates the benefit of the setup handler imo, because you would want to only load the ajax content once you enter a viewport bigger than 600px, wouldn't you?
See example jsfiddle.
Conclusion:
So actually I wouldn't even need the setup handler because I simply could load the content outside the enquire register and would have the same effect. (Which of course isn't what I want...)
Can someone tell me if I just misunderstood the purpose of setup or is there something I'm missing?
Combine with the deferSetup flag to defer the setup callback until the first match. This example illustrates the feature:
enquire.register(someMediaQuery, {
setup : function() {
console.log("setup");
},
deferSetup : true,
match : function() {
console.log("match");
},
unmatch : function() {
console.log("unmatch");
}
});
You can see a working example here: http://wicky.nillia.ms/enquire.js/examples/defer-setup/

How can I hide a dijit/form/button?

I think it is a common sense that providing a simple way to hide/show and enable/disable a button, but I cannot find any document that describe dojo has done such thing.
Any way, I hope it is my fault that I have missed out something while googling, thanks!
The following coding is what I have tried but they just make the button's text invisible:
dojo.style(btnInsert, {'visibility':'hidden'});
dojo.style(btnInsert, {'display':'none'});
UPDATE Question:
To oborden2:
I have tried your code, the result is same as the above code, here is the captured screen:
To MiBrock:
I have also tried your code and also get the result that same as the above code:
Form widgets in Dijit are special. For all normal Dijit widgets, the domNode (outermost node) of the widget receives the id property. However, with form widgets, the focusNode (which corresponds to the <input> element) receives the ID instead, so that things like <label for="foo"> work properly. In this case, the outermost node has no ID, and you’re actually just hiding the inner HTML input element.
If you already have reference to the widget:
require([ 'dojo/dom-style' ], function (domStyle) {
domStyle.set(widget.domNode, 'display', 'none');
});
If you only have a reference to the ID of the widget/original DOM node:
require([ 'dojo/dom-style', 'dijit/registry' ], function (domStyle, registry) {
domStyle.set(registry.byId(nodeId).domNode, 'display', 'none');
});
Try
require(["dojo/dom-style","dojo/domReady!"], function(domStyle){
domStyle.set(dojo.byId(domNode),'display','none');
});
The variable "domNode" stays for the id of the Node that should be influenced. This is the way we make it.
Regards, Miriam
Try using the Toggler module
require(["dojo/fx/Toggler"], function(Toggler),{
// Create a new Toggler with default options
var toggler = new Toggler({
node: "btnInsert"
});
// Hide the node
toggler.hide();
// Show the node
toggler.show();
});
http://dojotoolkit.org/reference-guide/1.9/dojo/fx/Toggler.html
I imagine you would want to link this to some event using Dojo's on module. Link it up to whatever condition triggers the button's need to be hidden.

set jqGrid page before url is called

I am looking for a way to set the page of a jqGrid to x...
My use case is someone is using my grid...
They click on a patient to edit that patient (I am not using jqGrids modal edit screen... to many modal windows already)...
When the save what they did to that patient, I want to redirect the browser back to the screen where they clicked on that patient, and back to the SAME PAGE...
The thing to keep in mind.
I am using asp.net MVC4. I call the first page via an action method. The url variable of my grid is another action in the same controller. That action is what I send my page and row variables down to. I am sure that this can be done, However, I have no idea of how to achieve it. So far I have tried to set the page variable and rows variable in my document.ready before I call the jqGrid...
tbl.jqGrid({
loadBeforeSend: function () {
page: pageFromTemp;
rows: rowFromTemp
}
});
basically I have tried different ways to do it. The above is just one of them.
I have tried to reload the grid in the document.ready. But that doesn't make any sense. Why reload the grid when you haven't given it any of the parameters it needs...
I have tried to set the variable in the beforeRequest event. I have a function that I try and set it in...
beforeRequest: function () {
if ((rowFromTemp != "") && (pageFromTemp != "")) {
$(this).trigger('reloadGrid', [{ page: pageFromTemp, rowNum: rowFromTemp, url: '/Encounters/GetAjaxPagedGridData/' }]);
//$.extend($(this).setGridParam({ page: pageFromTemp })),
//$.extend($(this).setGridParam({ rowNum: rowFromTemp })),
//$.extend($(this).setGridParam({ url: '/Encounters/GetAjaxPagedGridData/' }))
//$.trigger('reloadGrid', [{ page: pageFromTemp, rowNum: rowFromTemp, url: '/Encounters/GetAjaxPagedGridData/'}]);
}
},
But that doesn't work either. I am obviously missing something. What am I doing wrong...
Got it to change to the right page using loadComplete and $("frTable").trigger({})
But now I am getting a flashing Loading screen which indicates to me that it is still loading the data...
If I set a breakpoint in my code, I can confirm that it is loading the data. I am not doing something right here.
Load the grid in document ready, have it's datatype set to local, have it's url unassigned, and have it hidden. When you want to have it load, trigger the load after setting the parameters and then show it to the user.

ExtJS4 trigger doLayout on store load

I have a grid with store: cdStore defined. The grid's records are edited using a form which is bound to the grid data. When updating a record, I would like for the refreshed records to show in the grid.
Currently I have
handler : function() {
areaForm.getForm().submit({
params: { action: "update" }
});
cdStore.loadPage(cdStore.currentPage);
areaGrid.doLayout();
}
It seems like this fails sometimes and older data remains displayed in the grid - perhaps doLayout() is called before the page is fully loaded.
Can I trigger a doLayout on loadPage somehow?
// ...
cdStore.load({
callback: function(){areaGrid.doLayout();},
page: cdStore.currentPage
});
Update
I would appreciate a line or two with an explanation if you would be so kind
You said that "doLayout() is called before the page is fully loaded" and you were right. So the doLayout must be called after the data is loaded. The one way to do that is to use load method. You can pass array of options into this method:
store.load({
page: 2,
limit: 50,
// and
callback: function(){ /*do something*/ }
});
The function you pass as callback is called exactly after the data is loaded. So doLayout() put into callback produces correct behaviour.