I have an element with an on('mouseenter') event handler attached. The problem is the event does not fire on the selected element if the response time that transition to a sub node element of the element that the event is really attached to.
Querying: element.tagName gives the correct value sometimes and wrong other times causing event firing issues.
Solution: the solution was to add an array with valid tag names then query the parent of the element the event fired on until a valid tag name is found.
EXTJS is well annoying.
var elements = Ext.select('tag1, tag2, tag3', true);
elements.on('mouseleave', function(e, el){
var tags = ['TAG1', 'TAG2', 'TAG3']; // valid event Tags in caps;
var els = el;
if(tags.includes(els)){
while(true){
els=Ext.get(els).parent("",true);
if(tags.includes(els.tagName)){break;}
}
}
// now els contains the correct tag
}, this);
// duplicate function and change event for on('mouseleave');
elements.on('mouseleave', function(e, el){
var tags = ['TAG1', 'TAG2', 'TAG3']; // valid event Tags in caps;
var els = el;
if(tags.includes(els)){
while(true){
els=Ext.get(els).parent("",true);
if(tags.includes(els.tagName)){break;}
}
}
// now els contains the correct tag
}, this);
// duplicate function and change event for on('mouseleave');
Related
In my KendoUI datasource, I have the following defined:
change: function (e) {
if (e.action === "itemchange") {
// auto-format Display As
var geoDisplay, geoUrl;
if (e.items[0].GeoState.length > 0) {
geoDisplay = e.items[0].GeoCity + ", " + e.items[0].GeoState;
} else {
geoDisplay = e.items[0].GeoCity;
}
//this.dataItem(this.select()).GeoDisplay = geoDisplay;
e.items[0].GeoCity = "updated: " + e.items[0].GeoCity; // visually updates if editing this field
e.items[0].GeoDisplay = geoDisplay; // field is not updated
}
console.log("change: " + e.action);
console.log(e);
// do something else with e
},
Essentially I want to update other fields on a row being edited based on a field's input.
In this example, GeoCity is updated. The itemchange event is fired and only the GeoCity field gets updated with the new value. However I can see from the data that the other fields' data have been updated.
I have tried doing a .sync() and a few other methods to get this to appear, but no luck so far.
Incidentally, my grid is defined within an AngularJS directive and it's onEdit event isn't what I'm looking for, as I want the events that fire when each field is updated, not the whole row.
How can I get the other fields to visually update?
I managed to solve the issue by placing the following code in the data source code:
change: function (e) {
if (e.action === "itemchange") {
// auto-format Display As
var thisRow = $("#accountGeoLocationEditorGrid tbody").find(".k-grid-edit-row");
// update geo display
if (e.field === "GeoCity" || e.field === "GeoState") {
var geoDisplay, geoUrl;
if (e.items[0].GeoState.length > 0) {
geoDisplay = e.items[0].GeoCity + ", " + e.items[0].GeoState;
} else {
geoDisplay = e.items[0].GeoCity;
}
if (e.items[0].GeoDisplay.length == 0) {
e.items[0].GeoDisplay = geoDisplay;
thisRow.find("input[name=GeoDisplay]").val(geoDisplay);
}
}
}
I was really looking for another way to do this, as I don't really want to be doing DOM lookup, etc in a defined datasource.
Other suggestions welcome.
Did you try the grid refresh() method? At the end of your changes in the change event, call this line (with your grid's correct id):
$("#grid").data("kendoGrid").refresh();
I've tested this on my grid and kendo's samples and it works fine like this. You are editing the datasource but the grid is not aware of the extra changes you have done, except the cell that was edited. Calling refresh will update all the cells on the grid to reflect the datasource.
I have links on a table to edit or delete elements, that elements can be filtered. I filtered and get the result using ajax and get functions. After that I added (display) the result on the table using inner.html, the issue here is that after filtering the links on the elements not work, cause a have the dojo function like this
dojo.ready(function(){
dojo.query(".delete-link").onclick(function(el){
var rowToDelete = dojo.attr(this,"name");
if(confirm("Really delete?")){
.......
}
});
I need to trigger the event after filtering, any idea?
(I'm assuming that you're using Dojo <= 1.5 here.)
The quick answer is that you need to extract the code in your dojo.ready into a separate function, and call that function at the end of your Ajax call's load() callback. For example, make a function like this:
var attachDeleteEvents = function()
dojo.query(".delete-link").onclick(function(el){
var rowToDelete = dojo.attr(this,"name");
if(confirm("Really delete?")){
.......
}
});
};
Then you call this function both in dojo.ready and when your Ajax call completes:
dojo.ready(function() { attachDeleteEvents(); });
....
var filter = function(someFilter) {
dojo.xhrGet({
url: "some/url.html?filter=someFilter",
handleAs: "text",
load: function(newRows) {
getTableBody().innerHTML = newRows;
attachDeleteEvents();
}
});
};
That was the quick answer. Another thing that you may want to look into is event delegation. What happens in the code above is that every row gets an onclick event handler. You could just as well have a single event handler on the table itself. That would mean there would be no need to reattach event handlers to the new rows when you filter the table.
In recent versions of Dojo, you could get some help from dojo/on - something along the lines of:
require(["dojo/on"], function(on) {
on(document.getElementById("theTableBody"), "a:click", function(evt) {...});
This would be a single event handler on the whole table body, but your event listener would only be called for clicks on the <a> element.
Because (I'm assuming) you're using 1.5 or below, you'll have to do it a bit differently. We'll still only get one event listener for the whole table body, but we have to make sure we only act on clicks on the <a> (or a child element) ourselves.
dojo.connect(tableBody, "click", function(evt) {
var a = null, name = null;
// Bubble up the DOM to find the actual link element (which
// has the data attribute), because the evt.target may be a
// child element (e.g. the span). We also guard against
// bubbling beyond the table body itself.
for(a = evt.target;
a != tableBody && a.nodeName !== "A";
a = a.parentNode);
name = dojo.attr(a, "data-yourapp-name");
if(name && confirm("Really delete " + name + "?")) {
alert("Will delete " + name);
}
});
Example: http://fiddle.jshell.net/qCZhs/1/
I need to replace old event listener code with a new, but without deleting old:
onchange="func1();func2();"
need to be replace by:
onchange="newFunc();func1();func2();"
Adding new code to element's onChange event via JQuery was simple:
var element = $('element');
var _onchange = element.onchange;
element.onchange = function() {
//some additional code
if (typeof(_onchange) == 'function') {
_onchange();
}
};
Now I need to rewrite it using Prototype.. I suppose it will be like:
element.observe('change', function() {
// new code here
// then old onChange
}.bindAsEventListener(element)));
How can I grab existing onChange's code?..
You actually don't need to .bindAsEventListener() except in rare cases
so adding the event observing to an element
$('element').observe('change',function(){
//onchange code
});
If you do this - it will add the new code as an observer without deleting any other observers setup for that element and event
I don't think this is a Drupal-specific question, but more of a general jquery/ajax issue:
Basically, I'm trying to use javascript to add up form fields and display the result in a "subtotal" field within the same form. Everything is working fine until i click the option to add another field (via ajax), which then changes my "subtotal" field to zero, and won't work again until I remove the field.
Here is the function that adds up the fields:
function calculateInvoiceFields(){
var total = 0;
var rate = 0;
var quantity = 0;
var i = 0;
var $ = jQuery;
$("#field-aminvoice-data-values tr").each(function(){
// quantity field number
quantity = $("#edit-field-aminvoice-data-und-"+i+"-field-aminvoice-quantity-und-0-value").val();
// rate field as number
rate = $("#edit-field-aminvoice-data-und-"+i+"-field-aminvoice-rate-und-0-value").val();
if(!isNaN(quantity) && !isNaN(rate)){
total += quantity*rate;
}
i++;
});
return total;
}
And here are the functions that get fired for .ready and .live:
jQuery(document).ready(function(){
var $ = jQuery;
$(".field-type-commerce-price input").val(calculateInvoiceFields());
});
jQuery(function(){
var $ = jQuery;
$(".form-text").live('change', function(){
$(".field-type-commerce-price input").val(calculateInvoiceFields());
});
});
Any ideas would be a big help. Thanks in advance!
I recommend using 'on' for any binding statement. and 'off' for unbinding.
The reason it doesn't work after an AJAX call, is because you need to be watching for that element to be added to the DOM, and an event attached to it after it gets loaded. If you load a new element in, and there is nothing watching for it, it won't add the event watch to that new DOM element.
As below:
function calculateInvoiceFields(){
/*..*/
return total;
}
$(document).ready(function(){
$(".field-type-commerce-price input").val(calculateInvoiceFields());
$("body").on('change', ".form-text", function(){
$(".field-type-commerce-price input").val(calculateInvoiceFields());
});
});
usually it stops working when an error has been thrown. did you check out your javascript console (firefox firebug, or built in for chrome) for any indication of an error?
thanks so much in advance...here is the problem...
I am trying to add dynamic HTML element (EX. [delete]),everytime on a event call using FBJS.I am able to append the element using following code.
var oldFriendHtml = document.getElementById('friend_container');
var numi = document.getElementById('theValue');
var num = (document.getElementById("theValue").getValue()-1)+2;
numi.value = num;
var newElementId = "new"+num;
var newFriendHTML = document.createElement('div');
newFriendHTML.setId(newElementId);
newFriendHTML.setInnerXTML("HTML TO BE ADDED");
oldFriendHtml.appendChild(newFriendHTML);
The problem I am facing is that FBJS parses out the onClick part (event call ) out from the original HTML added .This stops me in the further activity on the added element .It also removes the styling added in the HTML ..
Regarding onclick being parsed out of setInnerXHTML, you can add the event later by using addEventListener.
Here is some sample:
var my_obj = document.getElementById('test');
// add a new event listener for each type of event you needed to capture
my_obj.addEventListener('click',my_click_func); // in your case is onclick
function my_click_func(evnt){
// some action
}
more details see http://developers.facebook.com/docs/fbjs#events