I create this class using pure javascript:
var SelectFeature = /*#__PURE__*/(function (Select) {
function SelectFeature() {
Select.call(this, {
condition: ol.events.condition.click
});
}
this.on('select', function (e) {
//some logic
});
if (Select) SelectFeature.__proto__ = Select;
SelectFeature.prototype = Object.create(Select && Select.prototype);
SelectFeature.prototype.constructor = Select;
return SelectFeature;
}(ol.interaction.Select));
as you can see I pass ol.interaction.Select as a parameter to the class and using Select.call() the method in SelectFeature as a constructor.
Here is a description of ol.interaction.Select class.
The ol.interaction.The select class has a member who is called getFeatures().
I try to access this method when some DOM element is clicked(this block is inside SelectFeature class):
$("#popupFeat-closer").click(function () {
this.getFeatures();
});
The code above is fired when DOM element is clicked but, on this row:
this.getFeatures();
I get this error:
Uncaught TypeError: this.getFeatures is not a function
My question how can I access getFeatures function which is located in click event handler?
Like it is mention in the comments, you have a context problem. Almost every library or framework has a method to keep the context, in jQuery you can achieve this with proxy method. Something like this should work,
$("#popupFeat-closer").click($.proxy(function () {
this.getFeatures();
}), this);
I would say that is always good to use the library/framework way of solving these, but the "old" way works too,
var self = this;
$("#popupFeat-closer").click(function () {
self.getFeatures();
});
jQuery Docs - proxy
Related
I am making a app in Vue.js and Leaflet.
In this app, I have a Select in leaflet created with L.DomUtil
this.select = L.DomUtil.create('select','leaflet-countryselect',this.div);
I do not find the way for put 'v-on:change' in this 'Select', so, I have to call a event function, inside to a Function Method in Vue.js.
methods: {
firstFunction{
},
secondFunction() {
this.select.on('change', function(e){
this.firstFunction()
}
}
}
But it not working, the error is "this.firstFunction() is not a function"
I tried to put
.../
var _self = this
_self.firstFunction()
../
But not working, anyway.
How can I do it? Thanks.
You should use arrow function ()=>{...} to get access to the component instance this as follows :
secondFunction() {
this.select.on('change', (e)=>{
this.firstFunction()
}
}
I want to call myFunction. Then I want to verify it was called with a Unit Test.
Javascript:
var self = this;
self.myFunction= function myFunction() {
// do stuff
};
self.onClickChange = function onClickChange() {
$('.checkBox').on('mouseleave', function(){
self.myFunction();
});
};
I have tried this test:
it('should call myFunction', inject(function ($compile, $rootScope) {
spyOn(this.instance, 'onClickChange').and.callThrough();
spyOn(this.instance, 'myFunction').and.callThrough();
this.instance.onClickChange('messageBoard');
var scope = $rootScope.$new(),
element = $compile('<md-checkbox class="checkBox"></md-checkbox>')(scope);
element.triggerHandler('mouseleave');
scope.$digest();
expect(this.instance.myFunction).toHaveBeenCalled();
}));
I have also tried using
scope.$broadcast('mouseleave');
And
var event = document.createEvent('MouseEvents');
event.initEvent('mouseleave', true, true);
$('.checkBox').dispatchEvent(event);
And this instead of the last line in the previous three lines:
document.body.dispatchEvent(event);
How can I get .on('mouseleave') to work and ferify that myFunction has been called?
Several things here. First, to answer your immediate question, you are calling: this.instance.onClickChange('messageBoard'); before you have created any DOM. So, you are going to try adding the click handler to absolutely nothing.
You need to add the click handler only after you create the DOM when you call compile.
But, there's another problem. You are compiling the directive and creating a DOM element, but it is not rooted in the document, so using the jquery $ on the document will not work.
It is bad style to use jQuery selectors in angular.
You could do something like this, where you use the $element of the current scope.
var self = this;
var $element = getElement(); // do some magic to get the current element
self.myFunction= function myFunction() {
// do stuff
};
self.onClickChange = function onClickChange() {
$element.on('mouseleave', function(){
self.myFunction();
});
};
And then your tests could work in the same way. The difference is that the $element never needs to be added to the DOM in order for the code to work.
But really, I would avoid this whole approach. You should not be using jQuery inside of angular. That is an outdated style. Instead, I recommend using ng-click to add the handler directly to the DOM.
Problem:
I have some selects with options in my HTML code and I have set an on change event handler, to figure out, when a selection will be changed.
The following code shows the jQuery code to get the on change:
$(document).on('change', '.anyHtmlSelect', updateState);
I have an existing Javascript function, that should be used as callback function.
The Javascript function looks like:
function updateState(element)
{
var currentId = element.attr("id");
}
Question:
How can I get the changed select as element?
I have tried the following:
$(document).on('change', '.anyHtmlSelect', updateState($(this));
but it doesn't work.
The first argument that is automatically passed to an event handler is a reference to the event itself, not the element that caused the event. To access the DOM element that triggered the event, use this:
Simply change:
function updateState(element)
{
var currentId = element.attr("id");
}
to:
function updateState(event) {
var currentId = this.attr("id");
}
After some research I have found a solution I would share with you.
In my solution, I created an anonymous function, which calls the updateState function with $(this) as parameter.
$(document).on('change', '.anyHtmlSelect', function () {
updateState($(this));
});
Is there a better solution?
Assuming I have something like:
var MyApp = function() {
this.name = "Stacy"
}
MyApp.prototype.updateName = function(newname) {
this.name = newname;
}
In my main page I have a :
$(function () {
var instance = new MyApp();
})
I have a button event handler that would update the name:
$("#button").on("click", function(evt) {
// Update the name in MyApp to something else...
instance.name = "john" // I do not like using instance here, because it has to be "instance" has to be created before I can use it. I want to be able to make this independent of "instance" being created or not
});
What is the proper way to do it such that the button handler would update "MyApp" to have the correct name, without explicitly using the created "instance" of myapp as part of the button's click handler?
ideally I would like to shove that jquery event handler somewhere into "MyApp" such that I could do something like:
MyApp.prototype.events = function() {
$("#button").on("click", function(evt) {
this.name = "john"
});
}
Though it doesnt work because this refers to something else.
How to properly structure my application such that the event handler is more or less updating the properties of the "MyApp" so that it can be independent of the created "instance" (i.e. i no longer have to use the "instance.")?
First, if you create an setter function, it's a good idea to use it !! :D
$("#button").on("click", function(evt) {
// Update the name in MyApp to something else...
//instance.name = "john"
instance.updateName("john");
});
And then, it does not make sense to do put an event handler inside of a method of your object MyApp, since it will never bind the onclick event until you fire events()
Then... my way to organize this, is to use the jQuery document onload to bind all the DOM objects with the function of your applications. Usually something like this:
MYAPP = {};
MYAPP.say_something = function () {
alert('lol, you clicked me!');
};
...
$(function () {
$('#my_button').click(MYAPP.say_something);
$('#other_element').mouseenter(MYAPP.another_method);
});
And for big applications, where you have to work with a lot of elements, you can organize your code much better if you have a namespace for your DOM elements, something like this:
MYAPP.fetch_dom = function () {
return {
my_button: $('#my_button'),
other_element: $('#other_element')
};
};
And you can bind the events in a very neat way
$(function () {
// first initiate DOM
my_dom = MYAPP.fetch_dom();
// Then bind events
my_dom.my_button.click(MYAPP.say_something);
my_dom.other_element.mouseenter(MYAPP.another_method);
});
This way you don't have to look for the specific elements in the DOM from a thousand points of your programme, spreading hardcoded id's everywhere and performing noneffective searches against the DOM structure.
Finally, it is much better to use literals in JS rather than using the word new. JS is a prototypical OOP language and new is a little bit "against nature" that can be a pain in the ass.
I am using a namespace for my javascript code, and I think I have hit a brick wall with a onchange attribute for a select element. When I attempt to call a function with (or without) my namespace the error console is reporting that the function is not found.
var MYNS = {}; //namespace
MYNS.modifySearchPage = function () {
....
var eSelect = document.createElement("select")
.....
eSelect.setAttribute('onchange', 'MYNS.handleChange(this)');
.....
//set up the options (value, textcontent, eSelect.appendChild(theOption)
...
// add the eSelect to the DOM
}
MYNS.handleChange = function (select) {
//parse the select options
}
The result I get in the console when I select an item from the dropdown list is:
Uncaught ReferenceError: MYNS is not defined
I have attempted to add the namespace to the windows but that does not seem to help (and I'm not convinced that is a safe thing to do).
I have tried adding a onclick handler to the select element but obviously that is a bad idea as select does not handle onclicks.
Stripping the MYNS from both the call and function definition also didn't help.
Any ideas?
Thanks,
mwolfe
Don't use attributes to attach handlers - use properties:
eSelect.onchange = function() {
MYNS.handleChange(this);
};
More generically you could also use the standard and more recommended addEventListener:
function changeHandler() {
MYNS.handleChange(this);
}
if (eSelect.addEventListener) {
eSelect.addEventListener('change', changeHandler, false);
} else if (eSelect.attachEvent) {
eSelect.attachEvent('onchange', changeHandler); // fallback for IE
}
It's also worth noting that you can call
eSelect.addEventListener('change', MYNS.handleChange, false);
You will need to modify your callback though - the argument passed will be an event object and this inside the function will refer to the element that triggered the event.
You just code a different word of wrong case MyNS.handleChange, it should be MYNS.handleChange. In JavaScript variables are case sensitive.