JqGrid - How to execute custom functionality for each grid of application on jqGridInitGrid event - jqgrid

In our application we have more than 100 grids and we need to display help button on Title bar of grid, for that I have created a plugin using
$.jgrid.extend({
EnableHelpButton: function(value) {
var $t = this;
...............;
}
});
Currently, I go to each .html page of grid and need to call the EnableHelpButton as shown in below code.
-----------------Index1.html-------------------------
$("#TestGrid1").bind("jqGridInitGrid", function () {
$(this).EnableHelpButton(true);
});
-----------------Index2.html-------------------------
$("#TestGrid2").bind("jqGridInitGrid", function () {
$(this).EnableHelpButton(true);
});
How I can create a generic way to call this EnableHelpButton on jqGridInitGrid events of each grid. It should write once on single place and it should work for each grid.

You have to have some specific call of your custom function on every page. One way will be to define you plugin so
$.jgrid.extend({
EnableHelpButton: function(value) {
var $t = this;
...............;
},
myInit: function () {
return this.each(function () {
$(this).bind("jqGridInitGrid", function ({
$(this).EnableHelpButton(true);
});
});
}
});
Even in the case you need to include .jqGrid("myInit") call on every page. You can make the call of myInit before the <table> is converted to grid. For example instead of
$("#grid").jqGrid({
... // parameter used to create jqGrid
});
you will be use now
$("#grid").jqGrid("myInit").jqGrid({
... // parameter used to create jqGrid
});
Only if you never use onInitGrid callback in any your grids you can use the callback instead of jqGridInitGrid. In the case you need just define the callback in some JavaScript code which you included in every your page:
$.extend(true, $.jgrid.defaults, {
onInitGrid: function () {
$(this).EnableHelpButton(true);
}
});
In the way you will set default implementation of onInitGrid for every grid.
Thus the definition of common initialization inside of onInitGrid callback produces the shortest implementation, but have restriction that you shouldn't use the callback in no of your grids. Alternatively you defines the method myInit which makes all bindings add you can add .jqGrid("myInit") on every your grids. The last approach will work for every jqGrid.

Related

jquery/ajax load scripts - best practices

I'm trying to get the hang of using ajax loads (mostly via jquery) to make my site more efficient. Wondering if anyone can provide any suggestions re "best practices" for using ajax?
Is there a way to simplify a script for multiple ajax calls? For example, I currently have the working script:
$(document).ready(function() {
$('#dog').click(function () {
$('#body').load("dog.html");
});
$('#cat').click(function () {
$('#body').load("cat.html");
});
$('#bird').click(function () {
$('#body').load("bird.html");
});
$('#lizard').click(function () {
$('#body').load("lizard.html");
});
});
The script just gets longer and longer with each additional function. Is there a simpler, more efficient way to write this script to cover multiple load scripts?
Also, should I be using ajax loads to replace the majority of actual links?
Here is a suggestion, since the code you posted seems to have a pattern between the id and the filename:
$(document).ready(function () {
$(document).on('click', 'commonParentElementHere', function (e) {
$('#body').load(e.target.id + ".html");
});
});
This suggestion uses .on() and you just need to add a commonParentElementHere, a id or a class of the common parent of those elements.
Another option is to use a class on all elements that should be clickable, and then use the code passing the id to the html file name, like:
$(document).ready(function () {
$(document).on('click', '.theCOmmonClass', function () {
$('#body').load(this.id + ".html");
});
});
I'd say give all the elements you want to click on a class say ajax then.
$(document).ready(function() {
$('.ajax').click(function () {
$('#body').load(this.id + ".html");
});
});
Assuming that the id matches the file name the script can be simplified to:
$(document).ready(function() {
$('#dog,#cat,#bird,#lizard').click(function () {
var fileName = this.id + ".html";
$('#body').load(fileName);
});
});
This script simply specifies each id in a single selector that separates each id with a comma. This will calls the click function to be fired for each element. With the anonymous function attached to the click event, the id of each element is obtained and concatenated to create the file name which is then passed to the load function.
If the id doesn't always match the element you could use the following approach.
var mappings = [
{id: "fileName1", file:"file.html"},
{id: "fileName2", file:"file2.html"}
];
$(document).ready(function() {
for(var i = 0; i < mappings; i++){
createMapping(mappings[i]);
}
function createMapping(mapping){
$("#" + mapping.id).click(function(){
$('#body').load(mapping.file);
});
}
});

How to check if a button is clicked in JavaScript

How to check if a button is clicked or not in prototype JavaScript?
$('activateButton').observe('click', function(event) {
alert(hi);
});
The code above is not working.
With this button:
<button id="mybutton">Click Me</button>
Use this:
$('mybutton').observe('click', function () {
alert('Hi');
});
Tested and works, here.
You might want to encase it in a document.observe('dom:loaded', function () { }) thingy, to prevent it executing before your page loads.
Also, just an explanation:
The single dollar sign in Prototype selects an element by its id. The .observe function is very similar to jQuery's .on function, in that it is for binding an event handler to an element.
Also, if you need it to be a permanent 'button already clicked' thingy, try this:
$('mybutton').observe('click', function () {
var clicked = true;
window.clicked = clicked;
});
And then, if you want to test if the button has been clicked, then you can do this:
if (clicked) {
// Button clicked
} else {
// Button not clicked
}
This may help if you are trying to make a form, in which you don't want the user clicking multiple times.
How one may do it in jQuery, just for a reference:
$('#mybutton').on('click', function () {
alert('Hi');
});
Note that, the jQuery code mentioned above could also be shortened to:
$('#mybutton').click(function () {
alert('Hi');
});
jQuery is better in Prototype, in that it combines the usage of Prototype's $ and $$ functions into a single function, $. That is not just able to select elements via their id, but also by other possible css selection methods.
How one may do it with plain JavaScript:
document.getElementById('mybutton').onclick = function () {
alert('Hi');
}
Just for a complete reference, in case you need it.
$('body').delegate('.activateButton', 'click', function(e){
alert('HI');
});

How to use events and event handlers inside a jquery plugin?

I'm triyng to build a simple animation jQuery-plugin. The main idea is to take an element and manipulate it in some way repeatedly in a fixed intervall which would be the fps of the animation.
I wanted to accomplish this through events. Instead of using loops like for() or while() I want to repeat certain actions through triggering events. The idea behind this: I eventualy want to be able to call multiple actions on certain events, like starting a second animation when the first is done, or even starting it when one animation-sequence is on a certain frame.
Now I tried the following (very simplified version of the plugin):
(function($) {
$.fn.animation = function() {
obj = this;
pause = 1000 / 12; //-> 12fps
function setup(o) {
o.doSomething().trigger('allSetUp');
}
function doStep(o, dt) {
o.doSomething().delay(dt).trigger('stepDone');
}
function sequenceFinished(o) {
o.trigger('startOver');
}
function checkProgress(o) {
o.on({
'allSetup': function(event) {
console.log(event); //check event
doStep(o, pause);
},
'stepDone': function(event) {
console.log(event); //check event
doStep(o, pause);
},
'startOver': function(event) {
console.log(event); //check event
resetAll(o);
}
});
}
function resetAll(o) {
/*<-
reset stuff here
->*/
//then start over again
setup(o);
}
return this.each(function() {
setup(obj);
checkProgress(obj);
});
};
})(jQuery);
Then i call the animation like this:
$(document).ready(function() {
$('#object').animation();
});
And then – nothing happens. No events get fired. My question: why? Is it not possible to use events like this inside of a jQuery plugin? Do I have to trigger them 'manualy' in $(document).ready() (what I would not prefer, because it would be a completely different thing – controling the animation from outside the plugin. Instead I would like to use the events inside the plugin to have a certain level of 'self-control' inside the plugin).
I feel like I'm missing some fundamental thing about custom events (note: I'm still quite new to this) and how to use them...
Thx for any help.
SOLUTION:
The event handling and triggering actually works, I just had to call the checkProgress function first:
Instead of
return this.each(function() {
setup(obj);
checkProgress(obj);
});
I had to do this:
return this.each(function() {
checkProgress(obj);
setup(obj);
});
So the event listening function has to be called before any event gets triggered, what of course makes perfect sense...
You need set event on your DOM model for instance:
$('#foo').bind('custom', function(event, param1, param2) {
alert('My trigger')
});
$('#foo').on('click', function(){ $(this).trigger('custom');});​
You DOM element should know when he should fire your trigger.
Please note that in your plugin you don't call any internal function - ONLY DECLARATION

Backbone.js - event trigger not work after rendering other views

There's a addPost function in my router. I don't want to re-create the postAddView every time the function is invoked:
addPost: function () {
var that = this;
if (!this.postAddView) {
this.postAddView = new PostAddView({
model: new Post()
});
this.postAddView.on('back', function () {
that.navigate('#/post/list', { trigger: true });
});
}
this.elms['page-content'].html(this.postAddView.render().el);
}
Here's the PostAddView:
PostAddView = backbone.View.extend({
events: {
'click #post-add-back': 'back'
}
, back: function (e) {
e.preventDefault();
this.trigger('back');
}
});
The first time the postAddView is rendered, the event trigger works well. However, after rendering other views to page-content and render postAddView back, the event trigger won't be trigger anymore. The following version of addPost works well, though.
addPost: function () {
var that = this, view;
view = new PostAddView({
model: new Post()
});
this.elms['page-content'].html(view.render().el);
view.on('back', function () {
delete view;
that.navigate('#/post/list', { trigger: true });
});
}
Somewhere you are calling jQuery's remove and that
In addition to the elements themselves, all bound events and jQuery data associated with the elements are removed.
so the delegate call that Backbone uses to bind events to your postAddView.el will be lost. Then, when you re-add your postAddView.el, there are is no delegate attached anymore and no events are triggered. Note that Backbone.View's standard remove method calls jQuery's remove; a few other things in jQuery, just as empty will do similar things to event handlers. So the actual function call that is killing your delegate could be hidden deep inside something else.
You could try calling delegateEvents manually:
this.elms['page-content'].html(this.postAddView.render().el);
this.postAddView.delegateEvents();
or better, just throw the view away and create a new one every time you need it. Your view objects should be pretty light weight so creating new ones should be cheap and a lot less hassle than trying to keep track of the existing views by hand.
If you really want to reuse the current DOM and View you do not need to set again and again the element as you are doing, everything that you call .html() you are destroying the DOM of the View and generating again and losing events. Also I prefer always to add the "el" in the DOM before render the View. I will have your function in this way:
addPost: function () {
if (!this.postAddView) {
this.postAddView = new PostAddView({
model: new Post()
});
this.postAddView.on('back', this.onBack);
this.elms['page-content'].html(this.postAddView.el);
}
this.postAddView.render();
},
onBack : function () {
this.navigate('#/post/list', { trigger: true });
}
I'm not fan of the use of local variables to refer to "this". If all of your Views uses _.bindAll(this) in the initialize method you could bind your events to your view and could use this(check how I transformed onBack).
With my code there is not a need to manually call this.delegateEvents()

jQuery Event when Validation Errors Corrected

I have buttons that trigger jQuery validation. If the validation fails, the button is faded to help draw attention away from the button to the validation messages.
$('#prev,#next').click(function (e)
{
var qform = $('form');
$.validator.unobtrusive.parse(qform);
if (qform.valid())
{
// Do stuff then submit the form
}
else
{
$('#prev').fadeTo(500, 0.6);
$('#next').fadeTo(500, 0.6);
}
That part works fine.
However, I would like to unfade the buttons once the invalid conditions have been cleared.
Is it possible to hook into jQuery Validation to get an appropriate event (without requiring the user to click a button)? How?
Update
Based on #Darin's answer, I have opened the following ticket with the jquery-validation project
https://github.com/jzaefferer/jquery-validation/issues/459
It might sound you strange but the jQuery.validate plugin doesn't have a global success handler. It does have a success handler but this one is invoked per-field basis. Take a look at the following thread which allows you to modify the plugin and add such handler. So here's how the plugin looks after the modification:
numberOfInvalids: function () {
/*
* Modification starts here...
* Nirmal R Poudyal aka nicholasnet
*/
if (this.objectLength(this.invalid) === 0) {
if (this.validTrack === false) {
if (this.settings.validHandler) {
this.settings.validHandler();
}
this.validTrack = true;
} else {
this.validTrack = false;
}
}
//End of modification
return this.objectLength(this.invalid);
},
and now it's trivial in your code to subscribe to this event:
$(function () {
$('form').data('validator').settings.validHandler = function () {
// the form is valid => do your fade ins here
};
});
By the way I see that you are calling the $.validator.unobtrusive.parse(qform); method which might overwrite the validator data attached to the form and kill the validHandler we have subscribed to. In this case after calling the .parse method you might need to reattach the validHandler as well (I haven't tested it but I feel it might be necessary).
I ran into a similar issue. If you are hesitant to change the source as I am, another option is to hook into the jQuery.fn.addClass method. jQuery Validate uses that method to add the class "valid" to the element whenever it is successfully validated.
(function () {
var originalAddClass = jQuery.fn.addClass;
jQuery.fn.addClass = function () {
var result = originalAddClass.apply(this, arguments);
if (arguments[0] == "valid") {
// Check if form is valid, and if it is fade in buttons.
// this contains the element validated.
}
return result;
};
})();
I found a much better solution, but I am not sure if it will work in your scenario because I do not now if the same options are available with the unobtrusive variant. But this is how i did it in the end with the standard variant.
$("#form").validate({
unhighlight: function (element) {
// Check if form is valid, and if it is fade in buttons.
}
});

Resources