Showing posts with label javascript. Show all posts
Showing posts with label javascript. Show all posts

Sunday

An example of converting object to an array in javascript


const ingredients = {
 salad: 2,
 tomato: 1,
 cheese: 3,
 meat: 2
}

const transformedIngredients = Object.keys(ingredients)
  .map(iKey => {
     return [...Array(ingredients[iKey])].map((_, i) => {
       return iKey ;
   });
}); 

console.log(transformedIngredients.toString());
the output is: salad,salad,tomato,cheese,cheese,cheese,meat,meat

**Object.keys(ingredients) returns key list:   salad,tomato,cheese,meat
**Array(ingredients[iKey])   returns the value of the given key like salad. for instance,the output for salad: Array(2). so the second map loops 2 time and returns salad twice.

Monday

postMessage API >> send messages & call parent's js function: between jsp and react app (in iframe)

I tried to:
- open a react app in an iframe from jsp
- send message by postMessage API>> from jsp to react, from react to jsp
- call parent's function by postMessage API inside iframe(react app)

http://localhost:8080 >> jsp 
http://localhost:3000 >> react

jsp example:
 ....
<tiles:put name="body" type="string">
   
 <div id="reactIframeLoading" style="height:50px; color:red; font-size:12px; 
      margin-left:2px;">
      React Iframe Loading...<br> 
      <a href="javascript:loadReactIframe()">Retry</a>
 </div> 

 <iframe 
      id="reactIframe" 
      style="display:none;"
      onload="reactIframePostMessage(); reactIframeLoaded();"
      src="http://localhost:3000/"
      width="100%" height="200" border="0" marginwidth="0"
      marginheight="0" scrolling="no">
 </iframe> 
  
 <script type="text/javascript">    
     const dataForReactPostMessage = {
           isReadOnly: false,
           someData: {
               someDataChild: 'eda'
          }
      }

     function callMeFromReact(msg) {
         console.log('callMeFromReact: params: ' + msg);
     }
  
     function reactIframeLoaded() {
        document.getElementById("reactIframe").style.display='';
        document.getElementById("reactIframeLoading").style.display='none';
     }  
  
     function loadReactIframe(){
         document.getElementById("reactIframe").src="http://localhost:3000/";
     }
  
     function reactIframePostMessage(){
         document.getElementById("reactIframe").contentWindow.postMessage(
              dataForReactPostMessage, 'http://localhost:3000/'
         );
     }
  
    window.addEventListener('message', handleFrameTasks);

    //get messages from iframe or run function given by iframe  
     function handleFrameTasks(event) {
           if(event.origin !== "http://localhost:3000") {
              return;
           }

           //if function is given
           var data = event.data;
           if(typeof(window[data.func]) == "function") {
                 window[data.func].call(null, data.params[0]);

          //if data is given
          } else if(data.event_id === 'my_first_message') {
                console.log('post message from react to jsp // event_id: my_first_message= ' + JSON.stringify(event.data));
          }
     }
  </script>
</tiles:put>

react example:
import React, { Component } from 'react'

class Example extends Component {

    constructor(props) {
        super(props);
        this.handleFrameTasks = this.handleFrameTasks.bind(this);
        this.sendParentPostMessage = this.sendParentPostMessage.bind();
    }

    componentWillMount() {
        window.addEventListener('message', this.handleFrameTasks);
    }

    componentWillUnmount() {
        window.removeEventListener("message", this.handleFrameTasks);
    }

    handleFrameTasks(event) {
        if(event.origin !== "http://localhost:8080") {
           return;
        }
        console.log('postmessage from jsp to react // event.data= ' + JSON.stringify(event.data));
    }

    sendParentPostMessage() {
        const dataForJspPostMessage = {
            event_id: 'my_first_message',
            someData: {
                someDataChild1: 'eda 1', 
                someDataChild2: 'eda 2'
            }
        } 
        //send data to parent
        window.parent.postMessage(dataForJspPostMessage, 'http://localhost:8080'); 

        //call js function named as 'callMeFromReact' in parent
        window.parent.postMessage(
            {'func':'callMeFromReact','params':['SomeMessages']}, 
            'http://localhost:8080'
        ); 

        window.parent.postMessage(
            {'func':'nonExistingMethod','params':['SomeMessages']}, 
            'http://localhost:8080'
        );
    }

    render() {
        return (
            <div>
                <h1>Hello, world!</h1>
                <button onClick={this.sendParentPostMessage}>sendParentPostMessage</button>
            </div>
        );
    }

}

export default Example

UPDATE: last version for post message listener:
window.addEventListener('message',  function (event) {
      if(event.origin != null && event.origin.includes(".int.teb.com.tr")) {
            var data = event.data;
            if(data != null && typeof(window[data.func]) == "function"){
                if(data.params != null && data.params.length > 1) {
                  var args = new Array();
                  for(var i = 0; i < data.params.length; i++){
                       args.push(data.params[i]);
                  }

                  window[data.func].apply(this, args);
                  
                } else {
                  window[data.func].call(null, data.params);
                }
            }
      }
}); 

Javascript tips

Some important concepts:

1.  "hoisting" : Javascript moves all declarations to the top before executing the code. It other words, a variable can be used before it is declared.

Advice: If you want to avoid confusion, declare variables at the beginning of the function.
Note: Javascipt does this only for declarations. Initializations aren't hoisting to the top.
<script>
    var x = 3;  
    elem = document.getElementById("demo");      
    elem.innerHTML = "x is " + x + " and y is " + y; 
    var y = 4;  
    //result: x is 3 and y is undefined
</script>



<script>
    var x = 3; 
    var y;
    elem = document.getElementById("demo");      
    elem.innerHTML = "x is " + x + " and y is " + y; 
    y = 4;  
    //result: x is 3 and y is undefined
</script>



<script>
    var x = 3; 
    var y = 4; 
    elem = document.getElementById("demo");      
    elem.innerHTML = "x is " + x + " and y is " + y; 
    //result: x is 3 and y is 4
</script>


<script>
    x = 3; 
    y = 4; 
    elem = document.getElementById("demo");      
    elem.innerHTML = "x is " + x + " and y is " + y; 
    var x, y;
    //result: x is 3 and y is 4
</script>

2.  
var a = 1 >> declares the variable in the current scope which can be local or global.
       a = 1 >> if the variable couldn't be found anywhere in the scope chain, it becomes global.This usage is very bad practice!!!

3.  Arrow functions aren't same with regular functions. 'this' keyword not bound to the element when it is used in arrow functions.
Try not to use arrow functions with constructors, click handlers, class/object methods!



Sunday

Javascript - Functions and Objects

Let's talk a little about javascript functions and objects. I'll use Atom text editor, you can find lots off tutorial about using Atom.

Named functions:
function multiply(a,b) {
  var result = a*b;
  return result;
}

var multiplied = multiply(3,4);
console.log(multiplied);
console output:

12

function multiply(a,b) {
  var result =  ["my result:", a*b];
  return result;
}

var multiplied = multiply(3,4);
console.log(multiplied);
console.log(multiplied[0] + " >>>> " + multiplied[1]);
console output:

[ 'my result:', 12 ]
my result: >>>> 12

Anonymous functions:
var a = 4;
var b = 3;

 //only execute if we call the variable as if it is a function
var multiplied = function() {
  var result =  a*b;
  console.log(result);
}

// which means inside multiplied variable there is a anonymous function, run it!
multiplied();
console output:

12

//only execute if we call the variable as if it is a function
var multiplied = function(a,b) {
  var result =  ["my result:", a*b];
  return result;
}

// which means inside multiplied variable there is a anonymous function, run it!
console.log(multiplied(4,5));
console.log(multiplied);
console output: 

[ 'my result:', 20 ]
[Function: multiplied]

Immediately invoked functional expressions:
//inside the variable, we have an immediately  invoked function expression
//run the function with below arguments
var multiplied = (function(a,b) {
  var result =  ["my result:", a*b];
  return result;
})(4,5) // arguments are here

console.log(multiplied);
console output:

[ 'my result:', 20 ]

//result is NaN, why i'm in trouble?
//the browser runs the function(immediately invoked expressions) when it is encountered
//so the variables should be before the function
var multiplied = (function(a,b) {
  var result =  ["my result:", a*b];
  return result;
})(a,b) // arguments are here

var a = 3;
var b = 4;

console.log(multiplied);

variables:
***For scope control, you should always declare your variables using the var prefix.
There is a difference between var a = 1 and a = 1.
var a = 1 --> declares the variable in the current scope which can be local or global.
a = 1 --> if the variable couldn't be found anywhere in the scope chain, it becomes global.
This usage is very bad practice!!!

***With ES2015 two new types could be used:
const (cannot be changed once defined)
let (block scope variable. smaller scope then var)
















const MYCONSTANT = 3;
console.log(MYCONSTANT);

MYCONSTANT = 4; // gets error
console output:

3
[stdin]:6
MYCONSTANT = 4;
           ^

TypeError: Assignment to constant variable.
    at [stdin]:6:12
    at Script.runInThisContext (vm.js:96:20)

function example() {
  var localVariable = 4;

  if(localVariable) {
    var localVariable = "different localVariable"; //changes local variable for entire scope, to resolve that problem we should use type of let
    console.log("nested localVariable: " + localVariable);
  }

  console.log("localVariable: " + localVariable);
}

example();
console output:

nested localVariable: different localVariable
localVariable: different localVariable

function example() {
  var localVariable = 4; // or let localVariable = 4;

  if(localVariable) {
    let localVariable = "different localVariable";
    console.log("nested localVariable: " + localVariable);
  }

  console.log("localVariable: " + localVariable);
}

example();
console output:

nested localVariable: different localVariable
localVariable: 4

objects:
var ltmc = new Object();

var ltmc = {
  description: "Less Talk More Code",
  year: "2018",
  //objects can also have function that uses or changes object's properties
  updateYears: function() {
    return ++ltmc.year;
  }
}

// or you can define as below:
// ltmc.description = "Less Talk More Code";
// ltmc.year = "2018";

console.log("all object: " + ltmc);
console.log("one property of object: " + ltmc.description);

ltmc.updateYears();
console.log("updated: " + ltmc.year);
console output:

all object: [object Object]
one property of object: Less Talk More Code
updated: 2019

//object constructor examples
function Ltmc(description, year) {
  this.description = description;
  this.year = year;
  this.updateYears = function() { //anonymous function
    return ++this.year;
  };
}

var ltmc01 = new Ltmc("Less Talk More Code", "2018");
var ltmc02 = new Ltmc("Less Talk More Code2", "2019");
console.log(ltmc01);
console.log("************");
console.log(ltmc02);

var ltmcList = [
  new Ltmc("Less Talk More Code3", "2020"),
  new Ltmc("Less Talk More Code4", "2021"),
];

console.log("************");
console.log(ltmcList);
console output:

Ltmc {
  description: 'Less Talk More Code',
  year: '2018',
  updateYears: [Function] }
************
Ltmc {
  description: 'Less Talk More Code2',
  year: '2019',
  updateYears: [Function] }
************
[ Ltmc {
    description: 'Less Talk More Code3',
    year: '2020',
    updateYears: [Function] },
  Ltmc {
    description: 'Less Talk More Code4',
    year: '2021',
    updateYears: [Function] } ]

// ltmc01["year"]  -->  bracket notation example
//  ltmc01.year    and    ltmc01["year"]  are same

function Ltmc(description, year) {
  this.description = description;
  this.year = year;
}

var ltmc01 = new Ltmc("Less Talk More Code", "2018");

console.log(ltmc01["year"]);

I'll mention about closures in an another post.
(much more examples:  https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures )

Friday

How to check for the existence of undeclared variable in js

You can check for the existence of undeclared variable in javascript without getting ReferenceError:
if (x !== undefined){} // gets error if x undeclared
if (x !== 'undefined'){} // gets error if x undeclared
if (typeof x !== undefined){} // gets error because typeof x returns "undefined"

if (typeof x !== 'undefined'){} //right one

Tuesday

JavaScript Cookies example

If you want to run your ajax or other code blocks once a day(or any other), you can use cookies.

In the below, we created cookie that would expire at midnight (timezone issues could be).
If cookie isn't there or has expired we run ajax else we do nothing.

Also you can see the cookie details from developer tools >> application >> cookies >> your adress (for chrome 61)

$(document).ready(function() {
       var myCookie = getCookie("MY_cookieName");  

       if(myCookie == "")  {   //cookie is not created or has expired
             $.ajax({
                //Do your job
             });
           var createdTime = new Date().toString();
           setCookieExpireAtMidnight("MY_cookieName", createdTime);
       }
});

function getCookie(cname) {
       var name = cname + "=";
       var ca = document.cookie.split(';');
       for(var i = 0; i < ca.length; i++) {
             var c = ca[i];
             while (c.charAt(0) == ' ') {
                    c = c.substring(1);
             }
             if (c.indexOf(name) == 0) {
                    return c.substring(name.length, c.length);
             }
       }
       return "";
}

function setCookieExpireAtMidnight(cname, value) {
       var midnight = new Date();
       midnight.setHours(23,59,59,0);
       var expires = "expires=" + midnight.toString();
       document.cookie = cname + "=" + value + ";" + expires + "; path=/";
}