jgGrid and event ResetFilterToolbar - javascript

I use last version free-jqGrig by Oleg.
I know that in versions, free-jqGrid, many other events are added in difference from jqGrid.
http://www.trirand.com/jqgridwiki/doku.php?id=wiki:events#list_of_events
Has re-read many similar answers, but events don't work for me.
jqGrid 'clearToolbar' without grid reload
Here something similar, but in an example an event when pressing the custom button.
It is necessary for me that when pressing on to ClearToolbar to add the custom check on event "jqGridToolbarBeforeClear" or "jqGridToolbarAfterClear".

The main reason of your problem is the usage of wrong event. The event jqGridToolbarBeforeClear will be triggered inside of the method clearToolbar, but you want to prevent processing of reloading of the grid inside of triggerToolbar. Thus you should use jqGridToolbarBeforeSearch event instead.
The mostly correct implementation of event handler jqGridToolbarBeforeSearch looks like the following:
$("#grid").on("jqGridToolbarBeforeSearch", function (e) {
var filters = $(this).jqGrid("getGridParam", "postData").filters;
if (typeof filters === "string") {
filters = $.parseJSON(filters);
}
if (filters) {
/* add here you custom tests */
return "stop";
}
return e.result; // forward the result of the last event handler
});
The main advantage of the usage events comparing to callback is the following: one can define multiple event handlers, but only one callback. If one event returns "stop" to prevent processing then the next event could overwrite the value with another value. To allow to stop processing in case of any event handler return "stop" one should use event.result in every event handler.

Related

Attaching an Event to an element and dispatching it correctly

I need to attach an Event called render to a panel element, that does nothing but being dispatched to warn all the listeners whenever panel is rendering.
Following the The old-fashioned way section of this link, I came up with this code:
/**
* **Static** Re-draw the layer panel to represent the current state of the layers.
* #param {Element} panel The DOM Element into which the layer tree will be rendered
*/
static renderPanel(panel) {
// Create the event.
var render_event = document.createEvent('Event');
// Define that the event name is 'render'.
render_event.initEvent('render', true, true);
// Listen for the event.
panel.addEventListener('render', function (e) {
// e.target matches panel
}, false);
panel.dispatchEvent(render_event);
This seems to have worked but as this is my first time doing this, I am not quite sure how to check the correctness of this method.
Looking inside the console I can see my panel element dispatching the render Event, but I'd like to ask if there's something I am missing or to be worried about before moving on.
To debug the result, I tried add an event listener to the document element like document.addEventListener("render",console.log("ciao")), which in turn printed ciao once in the console, but only just once.
I thought I would be able to see as many "ciao" in the console as the times the render Event was triggered, but this does not seem the case.
If you're trying to check everytime your event is fired, the second argument of addEventListener (taking into account what you're willing to achieve) should be a function callback using an event object as argument, like this for example:
document.addEventListener("render", function(e) { console.log("ciao"); });
In your example you're executing console.log("ciao"), not passing a function reference (anonymous or not), this is why it executes only one time: when the page loads/evaluates your script.
mdn guide on creating and dispatching custom events (same as your link)
The old fashioned method seems to still be working fine when I tried it, I saw the document event listener console log each time I triggered the event.
The updated way is:
panel.dispatchEvent(new CustomEvent('render'));
let div = document.querySelector('div');
div.addEventListener('old-event', () => {console.log('Old-fashinoed event caught')});
div.addEventListener('new-event', () => {console.log('New-fashioned event caught')});
let oldEvent = document.createEvent('Event');
oldEvent.initEvent('old-event', true, true);
let newEvent = new CustomEvent('new-event');
setInterval(() => {
div.dispatchEvent(oldEvent);
div.dispatchEvent(newEvent);
}, 1000);
<div>I emit an old-fashioned and a new-fashioned event every 1 second</div>

Ignite UI IgCurrencyEditor

I am trying to programmatically update a currency field to run the value changed event which holds a numeric calculation. I want the value to set to zero using something like.
$('.tester').igCurrencyEditor("setFocus");
$('.tester').igCurrencyEditor('option','value', 0);
Then when I blur out, or not sure what to do here, the valueChanged event should trigger as per the API docs (It can be raised on lost focus or on spin events).
But I can't seem to trigger the value changed event, it only works when I manually click into the input and change the number.
The valueChanging and valueChanged events would trigger when a user interaction changes the displayInput value of the editor, and the corresponding valueInput value is different from the display input one. The editors have adopted the same approach as all other Ignite UI controls where events do not trigger on API calls, because when an API call is performed, the developer can choose whether to invoke their event handler after the API call, or not.
There's two things that you can do to invoke your event handler. First one is to cache the event handler method and invoke it manually:
$('.tester').igCurrencyEditor({
...
valueChanged: valueChanged,
...
});
function valueChanged(event, ui) {
// event handler
};
$('.tester').igCurrencyEditor("setFocus");
$('.tester').igCurrencyEditor('option','value', 0);
valueChanged(null, { /* if you need arguments */ });
The second one is to extend the currency editor and override the method that performs the check whether these events should be triggered, and make it always trigger the events:
$.widget("ui.igCurrencyEditorExtension", $.ui.igCurrencyEditor, {
_processValueChanging: function (value) {
this._triggerInternalValueChange(value);
}
}
The second approach requires you to switch to using the igCurrencyEditorExtension and may cause side effects, as the method performs other checks as well.
Anyways, what Alex Marinov has suggested should work, but it depends on your editor configuration, depending on whether you've set nullValue, allow null values in the editor, etc.
you need a function like this:
function clearValue() {
$('.tester').igCurrencyEditor('option','value', "");
$('.tester').igCurrencyEditor('field').blur();
}
The result will be that the displayed value inside the currency editor is "$0.00" and the valueChanged event is fired.

Can I catch a js triggered change event?

I can use jquery to easily catch a change event of a select option when a user clicks it, however if javascript changes the select value, the 'change' event never triggers and needs to be manually triggered.
Is it possible to catch the value changing without manually having to trigger('change')?
Example fiddle here: https://jsfiddle.net/1fhbha4o/1/
Is it possible to catch the value changing without manually having to trigger('change')?
No. No event is fired when JavaScript code sets the value of a select. So your options are:
Have a common function you call both in response to a change event and also whenever your code changes the value (perhaps centralize changing the value so you don't forget to call it).
.trigger('change')
Polling the value to see if it changes (blech).
Re #1 and #2, you could give yourself a valWithNotify:
$.fn.valWithNotify = function(arg) {
if (arguments.length == 0) {
return this.val();
}
return this.each(function() {
$(this).val(arg).trigger("js-change"); // or just "change", but I'm not a
// fan of synthetic user events
});
};

Replacing all element's click bindings with a single document.on('click')?

I've always added click listeners to every separate element that needs to be listened, which can create a big messy Javascript with a lot of event bindings.
I was now thinking of doing it another way; by binding the click event to the entire document and upon click, see if the targeted element has a 'data-action' attribute and if present, execute the function in it. So that clicking:
Will execute function ajax_load_stuff()
It would make my code much cleaner, especially in ajax environments, but I want to know about performance and efficiency of this method. Are there any disadvantages to this approach?
UPDATE code example:
document.body.addEventListener("click", function (e) {
if (e.target) {
var action = e.target.getAttribute("data-action");
if (action) {
e.stopPropagation();
var params = e.target.getAttribute("data-params");
var data = [];
if (params) {
data = params.split(',');
}
window[action].apply(e.target, data);
}
}
}, false);
Ofcourse this approch has several advantages and disadvantages.
First discussing the disadvantages.
Need to handle event propagation perfectly otherwise it could make your system slow.
Passing parameter to click event will be difficult. Maybe need to introduce another attribute like : data-action-param
Advantages:
Less event handling code.

Preventing form submission with Dojo

I have a Dojo SubmitButton with jsId="saveParamButtonWidget". I overrided its onClick method by putting:
saveParamButtonWidget.onClick = editParam
I defined the editParam() function like this:
function editParam(eventObj) {
dojo.stopEvent(eventObj);
// ...
}
dojo.stopEvent() is supposed to stop event bubbling and default processing. However, the browser will submit the form anyway. I also tried with the following:
function editParam(eventObj) {
eventObj.stopPropagation();
eventObj.preventDefault();
// ...
}
Same thing. The only way I've managed to prevent form submission is by returning "false" from the event handler:
function editParam(eventObj) {
// ...
return false;
}
Can someone tell me why the first two ways did not work? Thanks.
Okay, after doing some digging through the source, I believe I can answer your question definitively.
The reason dojo.stopEvent() doesn't work, but return false does, is entirely due to how dijit.form.Button is coded. If you're interested, it's time for a little field trip. Keep your hard hats on.
When a dijit.form.Button is clicked...
The button's _onButtonClick method is invoked. (This is hooked up in the template, to the special ondijitclick event which captures not only mouse click but also certain keypresses, for a11y purposes.)
The _onButtonClick method first invokes the _onClick method, which, presuming the button is not disabled (which it's not in this case), invokes and returns the result of the onClick method. This is of particular interest since it's the method you're overriding!
Coming back to _onButtonClick, if _onClick returned precisely false (e.g. if your onClick handler returned false), _onButtonClick immediately bails out. This is why returning false makes your code work as desired. But what happens if it doesn't bail out there? Let's follow the trail further...
Next, _onButtonClick checks whether this button not a descendant of an actual HTML form, but is a descendant of a widget with an _onSubmit method (duck-typing). I'm assuming that in your case it is inside a real form (dijit.form.Form counts), so we'll skip over this. (I am under the impression that this code path wouldn't actually end up submitting, whereas yours apparently does.)
One final condition is checked: if the button has a valueNode defined (it does), the click method of this node is invoked. Unfortunately, this produces an entirely new event object on an invisible input type="submit" node under your form, and thus anything you tried to tell the original event is rendered immaterial, and the form goes on to submit! This is why dojo.stopEvent did not work - this code in dijit.form.Button pays it absolutely no heed.
I cooked this up as a somewhat-limited proof of concept (be sure to open firebug/etc. to get the logs): http://jsfiddle.net/Bf5H8/
Perhaps this is something that should be logged as a bug, but I suppose the initial thought may have been that supporting the well-known return false mechanism would be enough.
All this being said, it's quite possible that overriding onSubmit of the form is more in-line with your interests than overriding the button's onClick anyway (as S.Jones suggested), but at least this should solve the mystery.
Interesting question. +1
I believe you have to use dojo.connect to connect your function to a DOM event to get access to those methods with an event object.
See: The Event Object (DojoTollkit.org Reference Guide)
The Event Object
When you connect a function to a DOM
event with dojo.connect,
Dojo passes your function a normalized
event object. This means that,
regardless of the client's browser,
you can count on a set of standard
attributes about the event and a set
of methods to manipulate the event.
Assume that your function has been
called by dojo.connect and takes an
argument named event, like:
dojo.connect(dojo.byId("node"), "onclick", function(event){
// the var 'event' is available, and is the normalized object
});
...
Dojo normalizes the following methods with an event object:
event.preventDefault — prevent an event's default behavior (e.g., a link from loading a new page)
event.stopPropagation — prevent an event from triggering a parent node's event
Additionally, dojo.stopEvent(event)
will prevent both default behavior any
any propagation (bubbling) of an
event.
That said, placing a function like the one below in your form to perform some logic before submitting it, is a fairly clean, easily understood & maintainable approach.
<script type="dojo/method" event="onSubmit">
if (!this.validate()) { // or whatever else you'd like to evaluate
// insert calls here...
return false;
}
return true;
<script>
Cheers.
I had the same issue for using dojo.stopEvent
This issue is solved the form submission issue like this - here it is a simple form used to connect through dojo:
this.formId = dojo.byId("formId");
dojo.connect(this.formId, 'onsubmit', function(evt) {
var val_main = validate_this_form(0);
if(val_main == false)
dojo.stopEvent(evt);
});

Categories