顯示具有 js 標籤的文章。 顯示所有文章
顯示具有 js 標籤的文章。 顯示所有文章

2022年10月20日 星期四

Adding body parser in loopback JS

Problems

By default loopback JS does not include body parser although it is based on Express JS, and official documentation does not mention how to configure in order to add the body parser feature.

Solutions

Update $APP_HOME/server/middleware.json and add the body parser block
"parse": {
    "body-parser#json": {},
    "body-parser#urlencoded": {"params": { "extended": true }}
}

References

- How can I use body-parser with LoopBack?

 

2021年6月5日 星期六

Frequently used web programming / design techniques

1. Use "data-*" to pass data to event listener

There are many times we need to pass parameters to the event listeners but may not want to use bind or arrow function to prevent frequent unnecessary re-rendering in React, in this case we can add "data-*" html attribute to accomplish.

e.g.: 

<a href="#someLink" onCLick={onClickHandler}>
  <span data-idx={valToOnclickListener}>someSpanText</span>
</a>

Then in "onClickHandler" function, we can use event object "e" to retrieve the data-idx parameter we would like to make use for further processing in this way.

const onClickHandler = (e) => {
  const valToOnclickListener = e.target.dataset.idx;

  // do anything here with valToOnclickListener

}

Sometimes the listener will capture the child element even though you actually put the "data-idx" attribute to the parent, in this case use e.currentTarget,  the target capture must be the one which attaches the listener.


2. Specify child DOM using JSS

Use > to specify the child, use together with the class name, e.g.:

{
  someClassName: {
        '& > :first-child': {
                borderLeft: '2px solid transparent',
         }
    }
}


References

2020年4月24日 星期五

[JS] Onclick listener confusion in div inside div

Background
Sometimes we face situations when we have 2 layers of components (e.g. DIVs), while original (outer) div already configured with onclick listener but on top of the parent div, we also want the child div to have the same onClick listener.


Needless to say, the onclick action listener will be at the top will be fired first, and the parent one (underneath), which is not what we want, we want only child one to be detected and fired events


Solutions
This is related to event bubbling and event capturing. For event bubbling, clicking the inside DIV will trigger the event outside DIV, we need to stop both bubbling event and capturing event by e.stopPropagation and e.cancelBubble

References

2020年2月22日 星期六

[Android] JS debugging

Problems
I know for many of them it may be an old news, but I am quite surprise chrome debugging can be so easy even in Android device. Facing some weird bugs, when the front-end tries to fire an API to perform some server actions, it only succeed in desktop chrome but not mobile chrome.

I know it has a high chance of not a coding issue, but some specific settings that only occurs in mobile chrome, and even more, the API call works in incognito mode, which makes me even more curious on why it happens.
Solutions
To find out what actually malfunctioned behind, I planned to find a way to let me get a sort of like "remote logging", which connects my android device to the development machine and view the console log of the Android chrome for further bug tracing.

Turns out, it is quite easy, which use me only 5 minutes to setup

1. Enable USB debugging in Android device

2. Connect the Android device and accept the permission dialog raised on phone

3. Open the desktop chrome > console log > more tools > remote devices

4. Check "Discover USB devices", and wait until your device comes up to list (mine is Oneplus 7 pro, so the model is shown up as "GM1913"


















5. Interesting part comes up, when you type in the address and press open, the remote device will pop up chrome and navigate to the designated site! YES! We've now got a console log for our mobile version of chrome! 

6. Press "inspect fallback" or "inspect", a remote device devTools come up and you will see a REALTIME mapping of your device's chrome screen in the devTool, they are in sync now!















7. You can of course do anything just like you inspect your desktop site, like inspecting network tab, console logging, capturing back-end data etc. And more surprisingly, as both of them are insync, you can control the phone's surfing behavior through desktop browser's debugging window too!

















8. So finally I found the data save mode add a data save header causing my API call being cache and causing the failure. Disabling that mode brings the API call succeed again! 

References

2020年1月16日 星期四

[JS] Useful ES6 / ES2015 Syntax Enhancements (Keep Updating...)

Below are the es6 enhancements that are easily forgot but use a lot. Keep them noted here

Details
1. Function definitions in object (shorthand)
const obj = {
  foo() {
    return 'bar';
  }
}

2. Shallow copy using spread operator
let obj1 = { foo: 'bar', x: 42 }

let clonedObj = { ...obj1 }

3. Nested object properties destructuring
const nestedObj = {
	open: true,
	btnAct: {
		proceedLbl: 'aaa',
		cancelLbl: 'bbb',
	}
}
const {
	open,
	btnAct: {proceedLbl, cancelLbl}
} = nestedObj

proceedLbl and cancelLbl variable is created with value nestedObj.btnAct.proceedLbl and nestedObj.btnAct.cancelLbl

2019年11月3日 星期日

[JS] Something About Bubbling And Capturing

Background
During the implementation of a React application, I need to accomplish the following effect

Let's say we have an application with list of items listed, user can interact with the items, and the click event will trigger the calculation of another react component. More precisely, you can think of an app which user clicks to add products to carts, and the other component immediately checks and calculates the total price and show in menu bar. To better illustrate, I borrow the following image from google to present the idea






















When user scroll (either on smartphone or desktop), I want to make the floating menu disappear.


Problem
Following the thread https://medium.com/@pitipatdop/little-neat-trick-to-capture-click-outside-react-component-5604830beb7f, I first add ref to the components of the floating cart component, and add click event listener to the whole document DOM in componentDidMount, then for each user clicking event, use "contains" method, check whether the clicked DOM is the child of the floating cart component.

The idea seems nice, but the contains method always deduced the clicked DOM element as "false", that is not containing even when I clicked to the designated Paybox element. If this is not solved, the scroll to hide functionality will not work.


Findings and Solutions
Taking me an hour, finally the problem is caused by javascript's bubbling and capturing issues. Straightly speaking, the onclick event listener is being responded after the child onclick listener is determined.

The tricky point here is the addEventListener 's third userCapture argument. It is used to determine the order of responding the onclick when both parent and child element is equipped with onclick listener.

In my case, I have a "PayBox" DOM element which is inside the document DOM element, both of them are equipped with click event listener, and the interesting thing is I attach the document listener using


1
2
3
4
5
6
componentDidMount() {
  const {getProductList} = this.props;
  getProductList();
  // Add scroll event to whole app, when scroll, hide the order meal list
  document.addEventListener('click', this.handleDocumentScroll, false);
}

Here, I marked userCapture paramter to false, bubbling effect applies. That means Paybox DOM's onclick listener will be evaluated first and then the document element's listener comes after. The following better illustrates the alignment of elements.












And even more, I put the rendering of the Box element in the render function, which means, whenever there are changes of props within the component, it will have chance to trigger re-render, which in turn re-render the Box element.

Here is the capture of the target element, the parent element, and the results of the contain function.













The interesting thing here is that the parent of the target element is different from the one wrapped by the Box element (noted with the ***-root-290*** and ***-root-291***).

The reason behind is that, when user clicks, bubbling effects apply, js determines the event listener of the inner DOM first (i.e.: the box element), and because there are some changes of props in that onclick function, which in turn triggers the re-render of the box element, and that results in the renewal of the class name associated.

The document click event listener is then being determined afterwards, the event.target's DOM still keeps the reference of the last element (the ***-root-290*** class name's element), so the child of the outdated element is not included in the updated box element, that explains why the dropdown menu is not popping up anytime.

The solution is yet simple, just change the userCapture parameter from false to true. Capturing applies, and the document event listener now determined prior to the child's one, making the contain functions determined the desired result.

References
https://blog.othree.net/log/2007/02/06/third-argument-of-addeventlistener/
https://www.w3schools.com/jquery/tryit.asp?filename=tryjquery_event_stoppropagation
https://www.w3schools.com/jquery/event_stoppropagation.asp
https://stackoverflow.com/questions/34522931/example-for-bubbling-and-capturing-in-react-js

2015年1月14日 星期三

[AngularJS] Basic Concepts

Here are the basic concepts of Angularjs, these concepts are barely well documented by the officials.

  1. angular.config only accepts providers
  2. Every service and factory are the instances of the providers

    e.g.
    angular.module('myApp')
      .service('FooService', function(){
        //...etc
      })
      .config(function(FooServiceProvider){
        //...etc
      });
    
    
    
    Reference: http://stackoverflow.com/questions/17485900/injecting-dependencies-in-config-modules-angularjs