How to effectively attach eventListeners to DOM elements

Anonymous functions are great way to quickly get the job done, but can be a huge problem when used carelessly. It is especially when attaching eventListeners to DOM elements. Take the code below for example. Here we are attaching an eventListner to the element for the “click” event. Now, later lets say for some reason or requirement we need to remove this “click” listener.


var element = document.getElementById("my-id");
element.addEventListener("click", function() {
// handle event
});

After this point we don’t have any reference to this handler since we forgot to keep a reference to it hence we cannot call the removeEventListener on the element, and the function stays in the browse memory.

Now assume the same scenario with multiple elements. An appropriate example of it might be when a NxN grid of elements is created. Lets assume that the cells in the grid is being created dynamically and appended to the DOM. If these cells need to have some event handler we might end-up doing the following:


var newCell = getNewCell(); // function to create a new cell

newCell.addEventListenet("click", function() {
// handle code
});

This way we ended up creating NxN anonymous functions to which we don’t have references to, in case event listeners need to be removed. Even after the element does not exist in the DOM, it is the browser to decide when to remove these abandoned listeners from its memory. But as a programmer its our job to clean up the mess we created.

How to fix this:

A better approach to add eventListeners to DOM elements would be to have some kind of reference to them as below:


function myListener(event, target) {
// handle the event
}

var newCell = getNewCell();

newCell.addEventListener("click", myListener);

Now whenever needed, this listener can to removed from the element:


newCell.removeEventListener("click", myListener);

Sometimes, there is a requirement of firing en event listener only once (for example an init button to be clicked for initializing the application). In that case, the addEventListener method can accept an optional object parameter with a Boolean property “once” to tell the browser that this listener needs to be fired only once and after that the listener needs to be removed. So in such cases adding anonymous function as eventListeners can be considered fine (but not with multiple elements as we are still creating several anonymous functions which will sit there untill the event occurs for the first time).


myElement.removeListener("click", function() {}, {capture: false, once: true, passive: true});

So it is quite essential to take precautions when attaching anonymous functions as eventListeners especially with multiple elements.

Advertisements

My Favorite Programming Jokes

This time these jokes are specifically for programmers including Web Developers to System Programmers, Java guy or Python people. So here it is:

  1. I thought I would start this list with a serious note, but I didn’t know how everyone would React.
  2. Q. Why do Java guys wear specs?
    A. Because they can’t C#.
  3. Google doesn’t like straight lines, so they make Angular.
  4. Q. What do you call a snake that is approximately 3.14 units long?
    A. Python
  5. My wife asked me to go to the grocery store to get bread, and if they have eggs get twelve.So, I came with 12 bread packets and now she is mad; no idea why!!!
  6. Q.Four MySQL guys walk into a NoSQL bar but came out after some time.
    A. Because they couldn’t find a table.
  7. Q.How do programmers walk?
    A.
    void walk() {
    step++;
    }
  8. Q.Do you have any expertise in SQL?
    A. No I know No SQL.
  9. Q.How do functions break up?
    A. They stop calling each other.
  10. Duck duck = new Duck();

My Favorite Jokes for Nerds

Here I am listing down few of my favorite Science or Technology related jokes. Any person into Science, Math or Computers should be able to get them at least few some of them. So here it is:

Q. Why did the decimal win the case?
A. Because he made a good point.

 

Q. What did the triangle say to the circle?
A. Why are you so pointless.

 

Q. Why did the chicken cross the mobius strip?
A. To get to the same side.

 

Q. Where did the bad triangle go?
A. To the PRISM.

 

A Neutron walks into a bar and asks the bartender: how much for a drink?
The bartender says: for you Sir!!! no charge.

 

Q. What is the best thing about TCP jokes?
A. I will keep sending until you get them.

 

Math jokes never work on me.
I have trouble differentiating them.

 

Math jokes never work on me.
They are not an integral part of my life.

 

Four SQL guys walk into a bar but came out quickly. Why???
Because they couldn’t find a table.

 

Q. Why did the shapes disappear?
A. Because they were polygons.

 

That is it for now; hope everyone enjoyed them.

Change Header on Scroll in Angular2 Typescript

As I was migrating from Angular 1.x to Angular 2, I needed to implement a header which changes its background when the page is scrolled somewhat similar to this fiddle fork. The basic idea is to change or apply a class on the header on the scroll event after some scrolling.

Now in Angular2 it is done on the same principal but a little bit differently. Here is what I came up with to do this.

First, create a component generally at the root level and assign a handler for the scroll event using the host property(or attribute or metadata) of the component as below:

@Component({
    selector: 'cubcode-app',
    templateUrl: './modules/welcome/templates/welcome.html',
    host: {
        '(window:scroll)': 'updateHeader($event)'
    }
})
export class AppComponent {
    isScrolled = false;
    currPos: Number = 0;
    startPos: Number = 0;
    changePos: Number = 100;

    constructor() {}

    updateHeader(evt) {
        this.currPos = (window.pageYOffset || evt.target.scrollTop) - (evt.target.clientTop || 0);
        if(this.currPos >= this.changePos ) {
            this.isScrolled = true;
        } else {
            this.isScrolled = false;
        }
    }
}

In the above code the updateHeader(evt) is the handler attached to the onscroll event on the window object.
The updateHeader method first calculates the current position of the scroll and then decides on the position at which the header to be changed. Here it only sets the isScrolled to true or false to denote that the header is ready to be updated or not.

Now using this Boolean value we can add or remove a CSS class for the header. Below is how I did it:

<header class="my-header" [ngClass]= "{'page-scroll-header': isScrolled}"></header>

So every time the page is scrolled up to or more than 100 pixels this class will be added to the header.

Now is the CSS we can specify the styling to give our header a new look as below:

.page-scroll-header {
    background-color: #ccc !important;
    opacity: 0.9;
}

That’s all what I did to update my header, but we can also add some transition to give the user good experience:

.my-header {
    transition: background-color 2s ease-out;
}

Now what if we don’t want to change the styling of our header, but want to add or remove a new element from it. For that too we can make use of the isScrolledvariable and use the *ngIf directive to add or remove any element. This way the element with *ngIf directive will be added if the page is scrolled up to or more than 100 pixels.

Constants in ECMA Script 6 and their implementations

Web browsers have already started providing ECMA Script 6 functionalities to the users,

BUT 

before utilizing these features there are few anomalies in the implementations in different web browsers, and one of them is constant. Constants were among the most awaited features in JavaScript. Below is a brief look at constants and their behavior in different browsers.

Lets say we need a variable(that does not change over time) in our application, for example the time zone of the user(since for a normal user the time zone does not change very frequently).

So ECMA Script6 provides the following construct to declare a constant:

const TIME_ZONE = "IST+0530";

Now later, somewhere in the code even if the TIME_ZONE is tried to be assigned new value,  it will still hold the initial value:

TIME_ZONE = "ABC+0500"; // does not work
console.log(TIME_ZONE);

prints:

"IST+0530"

In case of constants holding objects as values the properties of the object can be altered but the constant itself cannot be assigned any new object or value. Take a look at the snippet below of instance:

const CENTER = {x: 24, y: 50};

now the rule for assignment of new object or value stays same i.e.:

CENTER = {a: 10, b: 20};
console.log(CENTER);

will print

{x: 24, y: 50}

but the following can be done:

CENTER.x = 10;
CENTER.y = 20;

So the code below will output the object with updated values of its properties:

console.log(CENTER);
{x: 10, y: 20}

But if the same constant is tried to be re-written again in the same scope as below a TypeError is thrown saying that the specified constant has already been defined.

function abc () {
    const PI = 3.14; 
    const PI = 3.14159; // TypeError/re-declaration
    console.log(PI);
}

Anomalies in browser implementations

In case of re creating constant in different scopes different browsers may behave differently. For example, the following code will work in IE edge and firefox 44.0.2 but not in chrome 48.0.2564.109 m.

//Works in IE Edge and Firefox but not in chrome
function abc () {
 const PI = 3.14; 
 console.log(PI);
 {
     const PI = 3.14159;
     console.log(PI);
 }
 console.log(PI);
}

Output in firefox and IE Edge

3.14
3.14159
3.14

but in chrome

Uncaught SyntaxError: Identifier 'PI' has already been declared

So there are still few in consistencies among web browsers in the implementations on ECMA Script6 features and recommendations.

Handling The Junk Code

While writing applications most of us have the bad habit to abandon few pieces of code here and there in the process of optimization and performance tuning. Few lines of codes get completely replace by better ones and few need little tweaks here and there though, there is a good amount of code which is replaced by better ones not because they are useless but not suitable for that particular situation. Since we know this truth, we find it very hard to delete that code, instead we keep a copy of it somewhere in the same program in an area where few other codes are dumped. This place looks like a junk yard which has high potential but definitely not very organized one.

If somebody likes the code very much and does not want to throw it into the junk corner, they hide it under the comment section and put add a TODO or UTILS line above it, surely a very bad practice for production.

code

So, What to do with this Lovely Junk?

So what to do with this box full of good but unused code and where do we put it so it can be utilized in the later course of time? Definitely this box has to be kept far far away from the production code. Why? Since these codes have been replaced by others there is a big chance that the new code(generally a method, function or a Class) happens to have the same name and often same signature too. Its pretty clear that having multiple codes with same signature can have catastrophic effect in the later run when a new developer join the team.

A good solution would be to take the code away and put it in a repository where it feels safe and can be revisited and shared with other members. If the project is Open Source in nature, putting the junk code in an online code repository and in the organization’s own private code repository. One thing that has to be taken care of is that, it has to be put in a repository separate from the actual project. This will surely save time as developer does not have to re write the code again from scratch.

Happy Coding 🙂

Element not clickable at point Selenium Webdriver

Issue:

Element not clickable at point (x, y)

Reason:

This issue normally occurs if the target element is not clickable, which means that the element is not in the state of user interaction. This is due to the following reason
A.) Element is in list and is currently not in the view-able area of the browser

How To Fix

  1. (Case A)Scroll the page so the element comes in the viewable area of the browser
    for example:

    // Get the element
    WebElement targetElement = driver.findElement(By.id("itemid"));
    
    // Create the JavascriptExecutor object
    JavascriptExecutor jse = (JavascriptExecutor)driver;
    
    // Scroll down the page to the element with JavaScript
    jse.executeScript("window.scrollTo(0,'+elementToClick.getLocation().y+')");// Click on the element
    targetElement.click();
  2. (General Case) This method doesn’t care about the current state of the target element. No matter if the element is at the bottom of the page and requires scroll to access it.
    So this method is a bit hackish since from the user point of view you cannot click(or interact with) an element if the element is present at the bottom of the page and requires some scrolling.

    In this method we use JavaScript to perform the click. This method will succeed as long as the element is present in the page.

    Here is how to do this:

    
    //Get the element
    WebElement we = driver.findElement(By.id("elementid"));
     
    // Create the JSExecutor object
    JavascriptExecutor executor = (JavascriptExecutor)driver;
     
    // Perform the click with javascript
    executor.executeScript("arguments[0].click();", we);