I have typescript function. Here is code
export class Step1{
constructor(){
this.begin_search();
this.results_ready();
}
private begin_search():void {
setTimeout(() => {
Searchfield.show_searchfield()
}, 100);
$('.search_box_overlay').show()
$('.search_box_overlay_top').show()
if (gon.search['search_type'] == 'package')
$('.search_box_overlay_top .package').show()
else if (gon.search['search_type'] == 'hotel')
$('.search_box_overlay_top .hotel').show()
else
$('.search_box_overlay_top .air').show()
window.seach_status_task = setInterval(Itinerary.check_search_status, 2000)
window.search_loading_itineraries = false
}
And then I importing this code into pack
Like this
$(document).ready(() => {
Translation.addDict(gon.translations);
Track.initialize();
new Searchfield();
if (!gon.search['searched']) {
Step1.begin_search();
}
if (gon && gon.search['id'] && $('.offer_hotel_addon').length > 0) {
check_status();
}
});
But when I run project, I have this error.
WEBPACK_IMPORTED_MODULE_3__components_step1.a.begin_search is not a function
Where can be problem and how I need to fix it?
The code defines begin_search as an instance method (a part of an instance), but is trying to use them as if they were static (a part of the class itself). Mark the method as static so that it belongs to the Step1 class itself:
private static begin_search():void {
See the handbook for more info on static methods. I'd also remove the this.begin_search(); call from the constructor as well. When the method is static, it doesn't exist on this anymore.
Related
Hi team im have a very small question, i have this code:
constructor(private mapper: any, private applyCallback: (arg0: INode) => void) {
super()
/** #type {GanttMapper} */
this.mapper = new GanttMapper(datamodel);
/** #type {function(INode):void} */
this.applyCallback = applyCallback;
// create the dummy node
this.dummyNode = new SimpleNode();
// switch off the default template
//type RouterClass = typeof ;
//interface RouterDerived extends RouterClass { }
console.log("routerClass");
this.template = new IVisualTemplate({
createVisual() {
return null;
},
updateVisual() {
return null;
}
});}
but in the part:
this.template = new IVisualTemplate({
createVisual() {
return null;
},
updateVisual() {
return null;
}
});
im have an error and the error is this: Cannot create an instance of an abstrac class
in JS this code is working fine but im trying to migrate it in angular and is not working.
im read the other part of same issues but i cant solved it......
im try all tipes of replays but is not working.
Thanks all.
This is because Angular (or rather TypeScript) is more strict than JavaScript. There are things you can do in JavaScript that cannot properly be expressed in a TypeScript definition file, without weakening the type-checks.
This is one of those things. It will work at runtime, but the TypeScript compiler does not understand this feature and will warn you not to use that unrecognized construct.
It's a feature, unique to the yFiles class library and it's called quick interface implementation.
The documentation also states this:
Quick Interface Implementation in TypeScript
The TypeScript .d.ts file doesn’t contain typings that allow quick interface implementations. They still work at runtime, but the TypeScript compiler will produce an error nonetheless. To work around this issue, you can either tell the compiler to ignore the offending line, or use an anonymous implementation of the interface:
// #ts-ignore
const customHitTestable = new IHitTestable((context, location) => location.x > 25)
const customVisualCreator = new class extends BaseClass<IVisualCreator>(IVisualCreator) {
createVisual(context: IRenderContext): Visual {
return new SvgVisual(document.createElementNS("http://www.w3.org/2000/svg", "g"))
}
updateVisual(context: IRenderContext, oldVisual: Visual): Visual {
return oldVisual
}
}
In newer version of yFiles for HTML (since 2.3), there is now a convenient short-hand that works great with typescript:
const customHitTestable = IHitTestable.create((context, location) => location.x > 25)
This does not require the ts-ignore and works for all interfaces: If there is only one method in the interface, all you need to do is pass its implementation to the .create method on the interface object. If there are more members, they need to be passed in via an option object with the names of the members. The typescript definition file provides full completion for this usecase, now.
{
createVisual() {
return null;
},
updateVisual() {
return null;
}
}
This is not valid JavaScript, try
{
createVisual: () => {
return null;
},
updateVisual: () => {
return null;
}
}
here is the code of IVisualTempleate
I looking for a way to inherit from WebElement object that webdriverio returns, without monkey-patching and with TS types support (autocompletion is a must). Is there a way to do something like this?
class Checkbox extends WebdriverIOWebElement {
constructor() {
super($('div'))
}
// overriding base method
isDisplayed(): boolean {
// blabla some new logic here
}
check() {
if(!this.isChecked()) {
this.click()
}
}
uncheck() {
if(this.isChecked()) {
this.click()
}
}
}
Lets take an example , When we have a New Tag (my-app) in HTML and we have to build a case to Login using webdriverIO ,
Assume this is the HTML :
What we would do is using the component object pattern , component object pattern attempts to reduce that repetition and move the component's api into an object of its own. We know that in order to interact with an element's shadow DOM, we first need the host element. Using a base class for your component objects makes this pretty straightforward.
Here's a bare-bones component base class that takes the host element in its constructor and unrolls that element's queries up to the browser object, so it can be reused in many page objects (or other component objects), without having to know anything about the page itself.
class Component {
constructor(host) {
const selectors = [];
// Crawl back to the browser object, and cache all selectors
while (host.elementId && host.parent) {
selectors.push(host.selector);
host = host.parent;
}
selectors.reverse();
this.selectors_ = selectors;
}
get host() {
// Beginning with the browser object, reselect each element
return this.selectors_.reduce((element, selector) => element.$(selector), browser);
}
}
module.exports = Component;
then what we would do is , We will write a subclass for our app-login component:
const Component = require('./component');
class Login extends Component {
get usernameInput() {
return this.host.shadow$('input #username');
}
get passwordInput() {
return this.host.shadow$('input[type=password]');
}
get submitButton() {
return this.login.shadow$('button[type=submit]');
}
login(username, password) {
this.usernameInput.setValue(username);
this.passwordInput.setValue(password);
this.submitButton.click();
}
}
module.exports = Login;
Finally, we can use the component object inside our login page object:
const Login = require('./components/login');
class LoginPage {
open() {
browser.url('/login');
}
get app() {
return browser.$('my-app');
}
get loginComponent() {
// return a new instance of our login component object
return new Login(this.app.$('app-login'));
}
}
Now this component object can now be used in tests for any page or section of your app that uses an app-login web component, without having to know about how that component is structured. If you later decide to change the internal structure of the web component, you only need to update the component object.
Now we apply the same approach with the Check Box Component by using Shadow Dom Support :
public class CheckBox extends Component {
public CheckBox(element) {
this.element = element;
}
get checkBoxSelector() {
return this.host.shadow$(element);
}
get void toggle() {
checkBoxSelector().click();
}
get void check() {
if (!isChecked()) {
toggle();
}
}
get void uncheck() {
if (isChecked()) {
toggle();
}
}
get boolean isChecked() {
return checkBoxSelector().isSelected();
}
}
Then We can write a Check Box Controller component that can get the instance of check box using id and verify what every is necessary.
const CheckBox= require('./components/CheckBox');
class CheckBoxController{
open() {
browser.url('/login');
}
get checkboxComponent() {
// Using this we can verify whether the Specific Check Box has been Selected or Not
let element = browser.$('[id="lpagecheckbox"]');
return new CheckBox(element);
}
}
Note :
Please bear this is not the actual code , This is just a part of the template which can help us to move towards the solution of the Problem .
Source Contends :
https://webdriver.io/docs/api/element/isSelected.html
https://webdriver.io/blog/2019/02/22/shadow-dom-support.html
https://webdriver.io/blog/2019/04/03/react-selectors.html
https://webdriver.io/docs/pageobjects.html
Moreover if we are using Selenium Webdriver , This can help us to Achieve it
Here we have an interface which actually combines all the webdriver interfaces , then we create a Specific implementation by inheriting the Element Class , finally Lets assume of any component you need we should be inheriting and using it with its own implementation , In this case lets assume the Check box that should be inherited from then Element Implementation Class and finally a Cranky way of using it by instantiating the object. CheckBox cb = new CheckBox(element);cb.uncheck();
Step 1:
Create an Interface that combines all of the WebDriver interfaces:
public interface Element extends WebElement, WrapsElement, Locatable {}
Step 2:
Element Implementation Inheriting the element class:
public class ElementImpl implements Element {
private final WebElement element;
public ElementImpl(final WebElement element) {
this.element = element;
}
#Override
public void click() {
element.click();
}
#Override
public void sendKeys(CharSequence... keysToSend) {
element.sendKeys(keysToSend);
}
// And so on, delegates all the way down...
}
Step 3:
Consider any component you use , Lets assume Check Box in this case
public class CheckBox extends ElementImpl {
public CheckBox(WebElement element) {
super(element);
}
public void toggle() {
getWrappedElement().click();
}
public void check() {
if (!isChecked()) {
toggle();
}
}
public void uncheck() {
if (isChecked()) {
toggle();
}
}
public boolean isChecked() {
return getWrappedElement().isSelected();
}
}
Way of Using It :
CheckBox cb = new CheckBox(element);
cb.uncheck();
If you want More Clear way of Implementing Something Like this : refer the third Link
public class Part2ExampleTest {
private final WebDriver driver;
#FindBy(id = "checkbox")
CheckBox checkBox;
protected Part2ExampleTest(WebDriver driver) {
this.driver = driver;
}
protected static Part2ExampleTest initialize(WebDriver driver) {
return ElementFactory.initElements(driver, Part2ExampleTest.class);
}
#Test
public void simple() {
WebDriver driver = new FirefoxDriver();
Part2ExampleTest page = initialize(driver);
PageLoader.get(driver, "forms.html");
Assert.assertFalse(page.checkBox.isChecked());
page.checkBox.check();
Assert.assertTrue(page.checkBox.isChecked());
driver.close();
}
}
Sources :
Extend Selenium WebDriver WebElement?
http://elisarver.com/2012/12/09/wrapping-webelement-1/
http://elisarver.com/2012/12/10/wrapping-webelement-2
IWebElement is an interface that you can just implement inside your driver class.
I'm training with LitElement and lit-html. I'm trying to make complex templates with functions and event listener. I have a module for the template module
and another for one component where I use the templates.
I'm having problem with a template for a buttom which I pass a function as parameter and when I clicked on the buttom call the function.
This works: it makes the call but the reference for this is lost. I thought a possible cause maybe the arrow function so I rewrote the function like this:
let timerElementOperation = function(operationTimer, operation,that){
operationTimer.bind(that);
return html` <button #click=${function(){operationTimer()}}>${operation}</button> `;
}
But the problem is still there. What's happening?
//timer-element.js
class TimerElement extends LitElement{
...
static get properties(){
return {
running: { type: Boolean, reflect: true}
};
}
render(){
let partialTemplate;
if( this.isPausable(this.running, this.finished) && this.time > 0 ){
partialTemplate = Template.timerElementOperation(this.pause, 'pause');
} else if(!this.running && this.time > 0){
partialTemplate = Template.timerElementOperation(this.resume,'resume');
}
pause(){
this.running = false; // this is lost.
}
}
//timer-templates.js
import {html} from '#polymer/lit-element';
let timerElementOperation = (operationTimer, operation) => {
return html` <button #click=${() => operationTimer()}>${operation}</button> `;
}
export timerElementOperation;
How should the template in Template.timerElementOperation know what this should be? It's an isolated function.
There's two ways about this - the first is to explicitly bind this: replace this.pause with this.pause.bind(this). This will work, but honestly makes for fairly idiosyncratic code.
The common practice is to use the fact that any #event binding in Lit will have this bound for you to the class it's in, so:
class TimerElement
extends LitElement{
...
renderTimerElementOperation(operation){
return html`<button #click=${this[operation]}>${operation}</button>`;
}
render(){
let partialTemplate;
if( this.isPausable(this.running, this.finished) && this.time > 0 ){
partialTemplate = this.timerElementOperation('pause');
} else if(!this.running && this.time > 0){
partialTemplate = this.timerElementOperation('resume');
}
return html`... ${partialTemplate} ...`
}
}
This is a lot simpler, and you generally want to keep the templates with or in the associated elements, rather than imported. If you want something re-usuable create another LitElement to reuse that, rather than importing functions that render templates in isolation.
I tried to craft a text slider, but I got weird result:
TypeError: HomeHeaderSlider.init is not a function
I am still learning es6 javascript.
Here are my classes:
import S from "skylake"
class HomeHeaderSlider {
init(e, t) {
function i() {
o.dataset.headerslider = h,
t()
}
let o = S.Geb.id("h-header"),
// some other variables
"h-header-arrow-btn-left" === e.target.id ? (h = 0 === c ? 5 : c - 1, d = -1) : (h = c < 5 ? c + 1 : 0, d = 1)
// some content
}
}
And here is the class extends...
class HomeController extends HomeHeaderSlider {
constructor(e) {
super();
S.BindMaker(this, ["addListeners", "getHomeHeaderSlider"]),
this.RO = new S.RO({
throttle: {
delay: 100,
atEnd: !0
}
})
}
init(e) {
let t = this
this.addListeners()
}
addListeners() {
this.listeners("add")
}
listeners(e) {
"add" === e ? this.RO.on() : this.RO.off(),
S.Listen(".h-header-arrow-btn", e, "click", this.getHomeHeaderSlider)
}
getHomeHeaderSlider(e) {
this.listeners("remove"),
HomeHeaderSlider.init(e, this.addListeners)
}
destroy(e, t) {
this.listeners("remove")
}
}
console.log(h)
// export default HomeHeaderSlider
const slidctrl = new HomeController()
slidctrl.init()
export default HomeController
It sems the code doesn't call the HomeHeaderSlider.init function.
My question is how can I call it?
HomeHeaderSlider is your class. There is no such function HomeHeaderSlider.init() on the class. The .init() method is on HomeHeaderSlider.prototoype.init or on an object instance of HomeHeaderSlider.
In this method:
getHomeHeaderSlider(e) {
this.listeners("remove"),
HomeHeaderSlider.init(e, this.addListeners)
}
it isn't entirely clear what you're trying to do there. If you want to call the base class version of .init() rather than your HomeController version of it, then you can use super.init() as in:
getHomeHeaderSlider(e) {
this.listeners("remove"),
super.init(e, this.addListeners)
}
It also looks like you may have an issue with the binding of this in this line:
S.Listen(".h-header-arrow-btn", e, "click", this.getHomeHeaderSlider)
where you need to change that to this:
S.Listen(".h-header-arrow-btn", e, "click", this.getHomeHeaderSlider.bind(this))
so that your getHomeHeaderSlider() method will have the proper value of this when it is called. When you pass this.getHomeHeaderSlider to a function, it looks on this, gets the reference to the getHomeHeaderSlider method and passes only the reference to that method. When the click handler later calls your method, there's no connection at all to the right object so the value of this is lost. Using .bind() the way I showed allows you to make sure the proper value of this stays connected to the method call. This is needed when passing a reference to a method of an object that is going to get called by some other agent that doesn't know anything about your object.
Greetings fellow Earthicans,
The following code is used on my website: brianjenkins94.me in order to handle baseline navigation functionality and while it was working previously I decided to leverage the class-based approach provided by the TypeScript Language in order to structure my code in a more readable fashion. In doing so I seem to have broken the functionality and now all #nav.on("click") events trigger the error Uncaught TypeError: Cannot read property 'removeClass' of undefined on Line 54 (see comment in code).
If anyone could identify why this code is nonfunctional or perhaps provide some insight as to whether there is a better way of going about doing this, (I'm really interested in proper design and right practice, the bug is just a convenient excuse to make a post and get input) it would be greatly appreciated.
Thanks ahead of time,
Brian
/// <reference path="jquery.d.ts" />
"use strict";
class Main {
//private SERVERNAME: string = "http://brianjenkins94.me/";
//private DOCUMENTROOT: string = "https://rawgit.com/brianjenkins94/local.blog.com/master/"
public init(): void {
$(function(): void {
var Nav: Navigation = new Navigation($("body"), $("#nav"), $("a[href=\"#nav\"]"));
Nav.init();
});
}
}
class Navigation {
private body: JQuery;
private nav: JQuery;
private navToggle: JQuery;
private navClose: JQuery = $("<a></a>");
constructor(bodyInit: JQuery, navInit: JQuery, navToggleInit: JQuery) {
this.body = bodyInit;
this.nav = navInit;
this.navToggle = navToggleInit;
// Create navClose element
this.navClose.attr({
href: "#",
tabIndex: 0
});
(this.navClose).addClass("close");
(this.nav).append(this.navClose);
};
public init(): void {
this.disablePropogation();
this.clickListener(this.body);
this.clickListener(this.navToggle);
this.clickListener(this.navClose);
this.clickListener(this.nav);
this.keyCodeListener();
}
private disablePropogation(): void {
(this.nav).on("click touchend", function(event: Event): void {
event.stopPropagation();
});
}
private clickListener(target: JQuery): void {
(target).on("click touchend", function(): void {
if (!(target === (this.body))) {
event.preventDefault();
event.stopPropagation();
if (target === this.navToggle) {
(this.nav).toggleClass("visible");
return;
}
}
(this.nav).removeClass("visible"); // They call me, line 54
});
}
private keyCodeListener(): void {
$(window).on("keydown", function(event: JQueryKeyEventObject): void {
if (event.keyCode === 27) {
(this.nav).removeClass("visible");
}
});
}
}
var main: Main = new Main();
main.init();
this is of the wrong type (window) and not the instance of the class. The best way to fix It is by using an Arrow function to capture the this reference like below:
private clickListener(target: JQuery): void {
(target).on("click touchend", () => {
if (!(target === (this.body))) {
event.preventDefault();
event.stopPropagation();
if (target === this.navToggle) {
(this.nav).toggleClass("visible");
return;
}
}
(this.nav).removeClass("visible"); // They call me, line 54
});
}
Check out the generated code on what it actually does. If you also want to use this provided by jQuery (the element in this case) you can also do
var that = this;
Right above the on call and use that for the class and this for your jQuery target. This is similar to what the arrow function generates but that generates _this instead of "that".
edit if you need to keep TSLint happy you should probably do () :void => { in the arrow function