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()
Related
Im trying to merge multiple codes from multiple files into one. All have different js classes but all the same slick slider settings inside. I mean the part initSlider() {...}); Any idea how to merge them into one?
// Code inside File one
window.$ = window.jQuery = $ = jQuery;
class BRPScarousel{
constructor() {
this.els = $('.msbrps');
this.slidesToShow = maxbrp_data.slides_to_show;
this.initSlider();
}
initSlider() {
$('.new_products').css("visibility","visible");
this.els.not('.slick-initialized').slick({
// always the same
});
}
}
var sc = new BRPScarousel();
// Code inside File two
window.$ = window.jQuery = $ = jQuery;
class XCPScarousel{
constructor() {
this.els = $('.msxcps');
this.slidesToShow = maxcrp_data.slides_to_show;
this.initSlider();
}
initSlider() {
$('.bestr_products').css("visibility","visible");
this.els.not('.slick-initialized').slick({
// always the same
});
}
}
var sc = new XCPScarousel();
From the comment on #Zulfe's answer...
"For the OP's use case one needs exactly a single (but of cause generic enough implemented) ProductCarousel. At instantiation time one, in addition to the slideshow specific data object (e.g. maxbrp_data or maxcrp_data, etc.), has to pass both root node selectors one for this.els (e.g. '.msbrps' or '.msxcps', etc.) and another one for initSlider (e.g. '.new_products' or '.bestr_products', etc.). Of cause there needs to be an initialization task, which e.g. at DOMContentLoaded time takes care of whatever needs to be initialized."
// e.g. file ... src/utils/ProductCarousel.js
class ProductCarousel {
constructor(data, elementsSelector, sliderSelector) {
this.els = $(elementsSelector);
this.slidesToShow = data.slides_to_show;
this.sliderSelector = sliderSelector
this.initSlider();
}
initSlider() {
$(this.sliderSelector).css("visibility", "visible");
this.els.not('.slick-initialized').slick({
// always the same
});
}
}
export default ProductCarousel;
// end of file.
// e.g. file ... src/main.js
import ProductCarousel from 'src/utils/ProductCarousel.js'
$(document).ready(() => {
const brpsCarousel =
new ProductCarousel(maxbrp_data, '.msbrps', '.new_products');
const xcpsCarousel =
new ProductCarousel(maxcrp_data, '.msxcps', '.bestr_products');
});
// end of file.
Use inheritance for this.
class SimpleCarousel {
constructor(className, data) {
this.els = $('.' + className);
this.slidesToShow = data.slides_to_show;
this.initSlider();
}
initSlider() {
$('.bestr_products').css("visibility", "visible");
this.els.not('.slick-initialized').slick({
// always the same
});
}
}
class BRPScarousel extends SimpleCarousel {
constructor() {
super('msbrps', maxbrp_data);
}
}
class XCPScarousel extends SimpleCarousel {
constructor() {
super('msxcps', maxcrp_data);
}
}
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 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
In my Javascript there is a parent Base class that will be extended by others.
I'd like to:
define in it a method getSubject() that could be common to all children, when it is not overridden.
make getSubject() rely on a Base property, that eventually could be overridden as well.
always call the getSubject() method in the context of the caller (the children classes or the Base class)
To clarify (hopefully) what I want to do..
I wrote (non-valid) PHP code as an example.
<?php
class Base
{
const SUBJ_SELECTOR = 'input';
public function init()
{
$this->wrapper = ....;
$this->subject = $this->getSubj();
if ($this->subject.attr('data-active')) {
// ... do stuff
}
}
public function getSubj() // One definition in parent
{
return $this->wrapper.find(self::SUBJ_SELECTOR);
}
}
class Select extends Base
{
const SUBJ_SELECTOR = 'select' // Override just the selector
}
class Textarea extends Base
{
const SUBJ_SELECTOR = 'textarea[name=foo]';
public function getSubj() // Eventual overriding
{
$subjs = $this->wrapper.find(self::SUBJ_SELECTOR);
foreach ($subjs as $subj) {
if ($subj.attr('multiline')) {
return $subj;
}
}
return $subjs;
}
}
I'd like to achieve the same result with Javascript (and JQuery eventually).
Actually I wrote some code (that I still didn't test) as a sketch:
var Base = function() {
this.options = {};
this.subject_selector = 'input';
this.wrapper = $('.container');
};
Base.prototype.getSubject = function() {
return this.wrapper.find(this.subject_selector);
}
Base.prototype.init = function() {
subj = this.getSubject();
if(subj.attr('data-active')) {
// ... do stuff
}
}
var Select = function() {
this.subject_selector = 'select';
}
Select.prototype = new Base();
Select.prototype.constructor = Select;
var Textarea = function() {
this.subject_selector = 'textarea';
}
Textarea.prototype.getSubject = function() {
subjs = this.wrapper.find(this.subject_selector);
for (var i = subjs.length - 1; i >= 0; i--) {
if(subjs[i].attr('multiline')) {
return subjs[i];
}
};
return subjs;
}
Textarea.prototype = new Base();
Textarea.prototype.constructor = Textarea;
Would it work correctly? Is this a proper use of the inheritance model?
Am I callling the method in the right way and will I get the expected result when executing the init() method?