I(m trying to use a generic method to parse dom element and attach event Listener to them.
So I add an html5 data attribute to specify the method that should be call when we trigger the event.
What I'm looking for is a way to call the method inside the class by her string value :
static addEvent(element, trigger, action)
{
element.on(trigger, action);
}
where element is the dom element where to attach eventListener, trigger is the type of listener and action is the method that we should call inside this class (here I want to call toggleFullscreen).
Is there a way to do that?
Edit : need to avoid eval solution, and I made a test with this[action] but it's not the excepted result.
Here is my code
dom element :
<div class="interface">
<span class="home_common-fullscreen action fa fa-desktop" data-action="toggleFullscreen" aria-hidden="true"></span>
</div>
javascript function :
class Interface {
constructor() {
this.domElements = jQuery(".interface");
this.attachAction();
}
attachAction()
{
let fullScreenButtonElement = this.domElements.find(".action");
if(fullScreenButtonElement !== undefined)
{
if(Array.isArray(fullScreenButtonElement))
{
jQuery(fullScreenButtonElement).each(function()
{
Interface.parseAction(this);
});
}
else
{
Interface.parseAction(fullScreenButtonElement);
}
}
}
static parseAction(element)
{
let action = element.attr("data-action");
if(action === undefined)
{
throw new InterfaceError("Trying to parse action element without defined data-action attribut");
}
let trigger = typeof element.attr("data-trigger") !== 'undefined' ? element.attr("data-trigger") : "click";
try
{
Interface.addEvent(element, trigger, action);
}
catch(err)
{
console.log(action + "not found in Interface")
}
}
static addEvent(element, trigger, action)
{
element.on(trigger, action);
}
toggleFullscreen()
{
alert("foo");
}
}
JSFiddle
class Interface {
// This method is a property of the class itself
static addEvent(element,trigger,action) {
element.on(trigger,Interface[action]);
}
// May need to be static if you don't plan on creating objects
static toggleFullscreen() {
console.log("It Works");
}
}
// Or the Event Handler could be in another object
class EventHandlers {
// It'd be accessed with EventHandlers["toggleFullscreen"];
static toggleFullscreen() {
}
}
// Or make it a global function
// Which would be accessed with window["toggleFullscreen"];
function toggleFullscreen() {
}
Do you need something like this:
class XClass {
f2() {
console.log("Message from f2");
}
f4() {
eval("this.f2()");
}
}
But I think static will not work for this approach.
Related
I have two classes: first on checks that file exists and it's valid; second one make some stuff with that file:
class Validator {
constructor(){
this.file = './file.json';
}
check(){ ... }
}
class Modificator {
action1(){ ... }
action2(){ ... }
}
What I want is the method from first class automatically calls inside each method from the second class.
It's a bit tricky stuff, but I'm really don't want to do it manually, like so:
class Validator {
constructor(){
this.file = './file.json';
}
static check(){ ... }
}
class Modificator {
action1(){
let status = Validator.check();
...
}
action2(){
let status = Validator.check();
...
}
}
By using a wrapper
class Validator {
static check () {console.log('checked')}
static checkCbk (fn) {
return _ => {
this.check()
//then callback
fn()
}
}
}
class Modificator {
//via public instance field
action1 = Validator.checkCbk(function () {
console.log('mod::action1')
})
}
//or by prototype
Modificator.prototype.action2 = Validator.checkCbk(function(){
console.log('mod::action2')
})
var m = new Modificator()
m.action1()
m.action2()
However notice that if you were to subclass Modificator, you could forget to rewrap your methods...
By making a contract
More commonly by making a contract and delegating to implem if contract is fulfilled.
This way you don't have to worry when extending since check is made in base class anyway.
class Validator {
static check () {console.log('checked')}
}
class Contract {
action1 () {
Validator.check()
this._action1()
}
}
class M2 extends Contract {
_action1 () {
console.log('mod2::action1')
}
}
var m = new M2()
m.action1()
I am creating a Class instance, I am kinda stuck on variable reassign, like below
class A {
constructor() {
this.checkBoolen = false
}
checkBoolen = false // error, asks to install #babel/plugin-proposal-class-properties to get support.
click() {
document.addEventListener('click', e => {
this.checkBoolen=true // <- a class constructor's prototype property can't be reassigned.
})
}
doSomthing() {
if(this.checkBoolen = true // <- never get there) {
console.log('do something')
setTimeout(function(){ this.checkBoolen = false}, 3000)
}
}
}
Looks like either I need to use #babel/plugin-proposal-class-properties? or change the Class to a function? I am wondering if there is a way to change variable inside Class or it is a bad practice?
There are multiple mismatch brackets, class keyword is uppercased
class A {
constructor() {
this.checkBoolen = false
}
checkBoolen = false // error, asks to install #babel/plugin-proposal-class-properties to get support.
click() {
document.addEventListener('click', e => {
this.checkBoolen=true // <- a class constructor's prototype property can't be reassigned.
});
}
doSomthing() {
if(this.checkBoolen = true )// <- never get there) {
console.log('do something')
}
}
And you can use it like this
let obj = new A();
obj.checkBoolen=true
obj.doSomthing()
I would not make my structure like this, but perhaps you should take a look.
class WTF{
constructor(clickElement){
this.clickElement = clickElement; this.checkBool = false;
clickElement.onclick = e => {
this.click();
console.log(this.checkBool);
}
}
click(){
this.checkBool = !this.checkBool;
return this;
}
}
let wtf = new WTF(document);
Just keep clicking on the page.
you have typeo
1- start class with lowercase class
2- check eventlistener syntax
class D {
constructor() {
this.checkBoolen = false;
}
checkBoolen = false // error, asks to install #babel/plugin-proposal-class-properties to get support.
click() {
document.addEventListener('click', (e) => {
this.checkBoolen=true; // <- a class constructor's prototype property can't be reassigned.
});
}
doSomthing() {
if(this.checkBoolen = true ) {
console.log('do something');
}
}
}
I've created an event emitter class. It works properly. Let me tell you how:
This is the class:
class EventEmitter{
constructor() {
this.events = {};
}
on(eventName,callback) {
if(this.events[eventName]) {
this.events[eventName].push(callback);
} else {
this.events[eventName] = [callback];
}
}
trigger(eventName, ...rest) {
if(this.events[eventName]) {
this.events[eventName].forEach(cb => {
cb.apply(null,rest);
});
}
}
}
With this class i can listen to certain events. Like so :
const ee = new EventEmitter();
ee.on('change', (aa) => {
console.log(aa);
});
Then i can trigger it with the trigger method
ee.trigger('change','Argument');
Now i want to listen to events with certain conditions.
for example :
ee.on({'change': 'barack the boss'}, (aa) => {
console.log(aa);
});
The above bit of code should only execute when trigger looks like this:
//wont run
ee.trigger('change','barack is no boss');
//will run
ee.trigger('change','barack the boss');
I wonder how to do this. I am not asking you to write my code, I would like an example or a step in the right direction.
Thank you in advance.
Whole code:
class EventEmitter{
constructor() {
this.events = {};
}
on(eventName,callback) {
if(this.events[eventName]) {
this.events[eventName].push(callback);
} else {
this.events[eventName] = [callback];
}
}
trigger(eventName, ...rest) {
if(this.events[eventName]) {
this.events[eventName].forEach(cb => {
cb.apply(null,rest);
});
}
}
}
//events has been created and is currently an empty object
const ee = new EventEmitter();
//even has been created, this event has a function which will be executed when event is triggered
ee.on({'change': 'barack the boss'}, (aa) => {
console.log(aa);
});
//wont run
ee.trigger('change','barack is no boss');
//will run
ee.trigger('change','barack the boss');
What I would do is use Object.Keys on the .on() event register. This would allow you to iterate trough the object passed (which at the same time would give you the ability to register multiple events in a single call).
With Object.Keys you can iterate trough the argument object as if it were an array. Then you can register the the value of the key as a condition when triggering the event.
I have a subclass that does some validation stuff that calls a method in the parent class that extends it, this is working in all places except when I need to access the local scope in the parent class, see example below
subclass
export default class ElementEvent extends Core {
constructor(events){
super(events);
this.validation = this.validateEvent();
this.element = this.getElement();
this.triggered = false;
this.player = false;
this.waitForElementDelay = 3000;
if (this.validation){
if (this.element){
this.processEvent();
} else {
this.waitForElement();
}
}
waitForElement(){
const interval = setInterval(()=>{
const el = this.getElement();
if (el){
this.element = el;
this.processEvent();
clearInterval(interval);
}
}, this.waitForElementDelay)
}
}
parent
export default class Reading extends ElementEvent {
constructor(event) {
super(event);
this.readingZoneHeight = 50;
this.wordsPerMinute = 300;
this.timer = 0;
}
processEvent() {
//this.elementEntryPoint = this.getElementEntryPoint();
//this.elementExitPoint = this.getElementExitPoint();
console.log(this);
console.log(this.readingZoneHeight);
window.addEventListener('scroll', () => {
console.log('Inside Event Listener ' + this.readingZoneHeight);
//this.handleWindowScroll();
});
}
}
When I console log this is shows a Reading class with all the props it should readingZoneHeight, wordsPerMinute etc but this.readingZoneHeight is undefined, however inside the event listener this.readingHeight is the correct value so not sure whats happening here?
Anyone Help?
That happens because you are calling the Reading's processEvent method from the constructor of the ElementEvent. So this is actually called as part of the super(event) call in the constructor of the Reading class.
And since the super(event) happens before you actually assign anything to the this.readingZoneHeight it is undefined at the time you log it.
I'm trying to implement some basic operations to the Set object like says here
This is the code
export class Conjunto extends Set<any>{
constructor(initialValues?) {
super();
return new Conjunto(initialValues);
}
isSuperset(subset) {
//some code
}
}
Do you guys have any idea to make it work? or am I doing something wrong?
For the moment I'm using the hack this guy found here
if you are trying to add functions to the Set prototype, or add polyfills to Set, you can do the following:
declare global {
interface Set<T> {
// polyfill
isSuperset(subset: Set<T>) : boolean;
// new function
someNewFunc(): boolean;
}
}
// add polyfill to the Set prototype as mentioned in the doc you provided: https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Set
Set.prototype.isSuperset = function(subset) {
for (var elem of subset) {
if (!this.has(elem)) {
return false;
}
}
return true;
}
//add the new someNewFunc;
Set.prototype.someNewFunc = function() {
// some logic here...
return true;
}
to use:
stringSet = new Set<string>()
stringSet.isSuperset(someOtherSet);
stringSet.someNewFunc(); // returns true