is there a good way to call methods dynamically in js? - javascript

I have 2 js functions:
function onRegionMouseOver()
{
}
function onRegionMouseOut()
{
}
Is it possible to call these js functions dynamically doing something like this?:
var type = 'Out'
//the following line would exec onRegionMouseOut() above:
call(onRegionMouse[type]())

You can use this:
var onRegionMouseHandlers = {
out: function () {},
in: function () {}
}
// and using like this
var whatToUse = 'in';
// use
onRegionMouseHandlers[whatToUse]()
Also, you can remove your which choose what function have to be called. You can just add two handlers to two different events.

You can define the functions as properties of an object, use bracket notation to call the function.
const methods = {
onRegionMouseOver() {console.log("Over")},
onRegionMouseOut() {console.log("Out")}
}
let fn = "onRegionMouse";
let type = "Out";
methods[`${fn}${type}`]();
type = "Over";
methods[`${fn}${type}`]();
without template literal or let
var methods = {
onRegionMouseOver: function onRegionMouseOver() {console.log("Over")},
onRegionMouseOut: function onRegionMouseOu() {console.log("Out")}
}
var fn = "onRegionMouse";
var type = "Out";
methods[fn + type]();
type = "Over";
methods[fn + type]();

You can do something like that, provided you declare an object that contains the functions.
var onRegionMouse = {
Out: onRegionMouseOut,
Over: onRegionMouseOver
};
Now you can just do
var type = 'Out';
onRegionMouse[type]();

what about:
var myFunctions = {
out: function onMouseOut()...,
enter: function onMouseEnter()...
}
You can call it now with myFunctions[ "out" ] ()

Related

How to create a object with prop as function and attribute

I need to create a fake object that accepts the following calls:
object.loading()
object.loading.close()
I've tried to create something like:
obj = {
loading: function() {
close: function() {
}
}
}
But it doesn't work.
This is one approach:
const object = {};
object.loading = function() {console.log('loading')};
object.loading.close = function() {console.log('closing')};
object.loading();
object.loading.close();
If you need something to be both a function and have its own methods, you need to create the function and then assign the methods to it afterward. What you tried above is to put close in the body of the function, and that won't work.
Try this:
var obj = {
loading: function () {
}
};
obj.loading.close = function () {};
obj.loading(); // no error
obj.loading.close(); // no error

AngularJS bind object parameter to object var

I have some code like this
$scope.grabItems = function(data) {
data.model = ['test'];
console.log($scope.ui.projects);
}
$scope.ui.projects = [];
$scope.grabProjects = function() {
$scope.grabItems({model: $scope.ui.projects});
}
I'm trying to change the $scope.ui.projects variable using the parameter of another function (this is so that I can write an abstract grabItems function using any variable).
The problem is it looks like the data.model = ['test'] isn't changing the $scope.ui.projects variable at all but is creating a brand new variable.
How would I modify the outer variable in a reusable way like this?
Note that $scope.ui.projects could potentially be any variable.
You are not actually not changing $scope.ui.projects, Try like this
$scope.grabItems = function(data) {
data.model = ['test'];
console.log($scope.ui.projects);
}
$scope.ui.projects = [];
$scope.grabProjects = function() {
$scope.grabItems($scope.ui.projects);
}
If it's not clear, share what is your expected object.
You could achieve it by pushing items into the array:
$scope.grabItems = function(data) {
if(!angular.isArray(data.model))
throw new Error('Array expected');
data.model.length = 0; // empty array
data.model.push('test'); // push items
console.log($scope.ui.projects);
}
$scope.ui.projects = [];
$scope.grabProjects = function() {
$scope.grabItems({model: $scope.ui.projects});
}

Use of debounce on Ext 3.4 framework

I want to implement the debounce function on Ext.Button, so I extended it and override the onClick function, like this:
MyButton = Ext.extend(Ext.Button, {
onClick: function(e) {
var that = this;
var args = e;
clearTimeout(this.timeoutDebounce);
this.timeoutDebounce = setTimeout(function(){
MyButton.superclass.onClick.apply(that, [args])
}, this.debounce);
}
});
Debounce is a parameter passed on the x-type declaration.
The problem here is that the "args" parameter I'm passing to onClick has changed when it's called from "click" to "mouvemove" and it doesn't fire the events it should.
Is there a way to record the "e" parameter received in the function to pass to onClick on superclass?
The function passed to setTimeout must be wrapped in order to keep the value presented in current scope:
function createCallback(args) {
return function() {
MyButton.superclass.onClick.apply(that, [args]);
}
}
Also, e is passed by reference, so you need to create a copy of it. Using ExtJS, you can use Ext.apply method:
Ext.apply({}, e);
The full code should be:
var MyButton = Ext.extend(Ext.Button, {
onClick: function(e) {
var that = this;
function createCallback(args) {
return function() {
MyButton.superclass.onClick.apply(that, [args]);
// you can also use call since you know the arguments:
// MyButton.superclass.onClick.call(that, args);
}
}
clearTimeout(this.timeoutDebounce);
var copy = Ext.apply({}, e);
this.timeoutDebounce = setTimeout(createCallback(copy), this.debounce);
}
});
You should clone the object:
var args = Ext.apply({}, e);
this.timeoutDebounce = setTimeout((function(args){
return function(){MyButton.superclass.onClick.apply(that, [args])};
})(args), this.debounce);

Pass HTML element to JavaScript function

I am passed 3 html elements as parameters to JS function. JS function is in separate file. I have problem to bind 'click' event with _confBtn object (which is parameter). My complete JS file:
window.HAS = window.HAS || {};
HAS.MyApp = HAS.MyApp || {};
(function (_this, $, undefined) {
var _sessionTimeOut = false;
var _startCountDown = false;
var _counterTime;
var _countDownTime;
var _dialogWrap;
var _confBtn;
var _counter;
_this.init = function (showDialogTime, logofCountDownTime, dialogWrap, counter, confirmationButton) {
_counterTime = 5;
_countDownTime = 0;
_dialogWrap = $('#' + dialogWrap);
_confBtn = $('#' + confirmationButton);
_counter = $('#' + counter);
alert(_confBtn.text());
createSessionTimeOut();
$(document).bind("mousemove keypress mousedown mouseup", resetTimeOut);
}
_confBtn.on('click', function () {
window.clearInterval(_startCountDown);
_dialogWrap.css('visibility', 'hidden');
createSessionTimeOut();
$(document).bind("mousemove keypress mousedown mouseup", resetTimeOut);
});
function createSessionTimeOut() {
_sessionTimeOut = window.setTimeout(function () {
_dialogWrap.removeAttr("style");
_counter.text(_counterTime);
$(document).unbind("mousemove keypress mousedown mouseup");
startCountDown();
}, 2000);
}
function startCountDown() {
_startCountDown = window.setInterval(function () {
if (_counterTime >= 0) {
_counter.text(_counterTime--);
}
_countDownTime++;
if (_countDownTime >= 4) {
logOutUser();
return;
}
}, 1000);
}
function resetTimeOut() {
window.clearTimeout(_sessionTimeOut);
_sessionTimeOut = false;
createSessionTimeOut();
}
function logOutUser() {
$.ajax({
url: '/MyApp/Account/LogOut',
type: 'GET',
success: function () {
document.location.href = '/MyApp/Account/Login';
}
})
}
}(window.HAS.MyApp.SessionTimeOut = window.HAS.MyApp.SessionTimeOut || {}, jQuery));
I call in separate page like in following:
SessionTimeOut.init('5', '5', 'dialog-wrap', 'confirm-button', 'counter');
I have issue with _confBtn when I try to call click event. Browser show that is undefined.
Please help.
It would probably better to do something more dynamic like this:
function SomeFunction (element1,element2) {
var e1 = $("#"+element1),
e2 = $("#"+element2);
// Do something with variables e1 and e2
}
and you would call like this:
//html:
<div id="one"><div>
<div id="two"><div>
//javasctript:
SomeFunction('one','two');
No, you are mixing a function declaration with a function call somehow. You can't provide function arguments when defining a function. This however will work fine:
function someFunction($element1, $element2) {
//Do something with the elements
}
someFunction($("#element1"), $("#element2"));
Note that $element1 and $element2 are just variable names, and the leading $ doesn't have anything to do with jQuery. It is just a common convention to identify variables referencing jQuery selections.
You can of course do it, just by using the normal jQuery way of including multiple selectors. Your code is slightly incorrect because you are actually only defining the function without calling it, and you are not supposed to pass arguments/variables into the function when defining it.
Unless you have the intention to distinguish between two groups of elements, I would refrain from declaring elements individually as you have used in your question, because sometimes you will never know the length of the selected items.
function someFunction($ele) {
// jQuery objects will be accessible as $ele
}
// Call the function
someFunction($('#selector1, #selector2'));
However, if the former is the case, you can always do so:
function someFunction($ele1, $ele2) {
// jQuery objects will be accessible as $ele1 and $ele2 respectively
// Example: $ele1.hide();
// $ele2.show();
}
// Call the function
someFunction($('#selector1'), $('#selector2'));
For example, you can refer to this proof-of-concept JSfiddle: http://jsfiddle.net/teddyrised/ozrfLwwt/
function someFunction($ele) {
// jQuery objects will be accessible as $ele
$ele.css({
'background-color': '#c8d9ff'
});
}
// Call the function
someFunction($('#selector1, #selector2'));
If you want to pass some elements to function you can use jQuery constructor to standardize arguments
function SomeFunction (element1,element2) {
element1 = $(element1);
element2 = $(element2);
// and you have 2 jQuery objects...
}
// and now you can pass selector as well as jQuery object.
SomeFunction($('div.a'),'#b');
You can pass paramters as much as you want this way. I use jQuery in this code and created a simple function.
var item=$("#item-id");
var item1=$("#item1-id");
makeReadOnly(item,item1);
function makeReadOnly(){
for(var i=0;i<arguments.length;i++){
$(arguments[i]).attr("readonly", true);
}
}

Javascript concatenate a function similar to how text can be added

In javscript we can do this
var text = "the original text";
text+=";Add this on";
If a library has a function already defined (e.g)
//In the js library
library.somefunction = function() {...};
Is there a way to add something on so that I can have two functions run?
var myfunction = function() {...};
Something like:
library.somefunction += myfunction
So that both myfunction() and the original library.somefunction() are both run?
You can use this kind of code (leave scope empty to use default scope):
var createSequence = function(originalFn, newFn, scope) {
if (!newFn) {
return originalFn;
}
else {
return function() {
var result = originalFn.apply(scope || this, arguments);
newFn.apply(scope || this, arguments);
return result;
};
}
}
Then:
var sequence = createSequence(library.somefunction, myFunction);
I think what you want to create is a Hook (function) - you want to call library.somefunction but add a bit of your own code to run before. If that's the case, you can make your myfunction either call or return the library function after it's done with your bit of code.
var myfunction = function() {
// your code
// ...
return library.somefunction();
}

Categories

Resources