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

2019年9月10日 星期二

Configuring Gitlab account in Linux & Windows

Background
I need to create a git working environment on my Windows 10 installed desktop, I then setup the git account, add the ssh key of the machine through the gitlab control panel but gitlab replied me with no access right when trying to git pull my project.

I tried



  • Re-generate the RSA key and load again
But not working...

Solution
Turn out the username and the user account must match the one created in gitlab, git client will make use that account for the verification process with git server. I misunderstand that the user account can be arbitrary created on the fly.

Procedure

  1. Configure the username and user account (MUST match with the one in gitlab / github, skip the --global parameter if you are managing multiple users)
    • git config --global user.name "yourname"
    • git config --global user.email“your@email.com"
  2. Remove known_hosts (may not be necessary, it depends)
  3. ssh-keygen -t rsa -C "whateverName"
  4. Copy all text in /Users/your_user_directory/.ssh/id_rsa.pub
  5. Go to setting in gitlab and add the public key for authentication
  6. Set the git remote url with "git remote set-url origin https://gitUsername:gitPassword@gitlab.com/yourRepo.git"
Points to Note
Sometimes, login still failed with

sign_and_send_pubkey: signing failed: agent refused operation
Permission denied (publickey).
fatal: Could not read from remote repository.

Due to ssh-agent cannot find the keys attached, in such case we need to add the private key identities by running command


ssh-add


repeat step 6 and the remote origin may now be read



But in case...
If it sill fails to log in for some error messages like no access rights to the repo, navigate to ~/.ssh/config, add the entry as follows.


Note: You can also specify multiple IdentityFile entries if you have same hostname using different key pairs, just add 1 more IdentityFile entry would be done, remember, you should put the private key in the IdentityFile option
Host gitlab.com
  PubkeyAcceptedKeyTypes +ssh-rsa
  HostName gitlab.com
  IdentityFile ~/.ssh/id_rsa_anywhere /*Private key directory here!!*/
  User git

And use all the possible keys for login



ssh git@gitlab.com -vv
After the configuration, gitlab should be able to login and fetch updates again

References


2019年9月4日 星期三

[Onenote] Setting Default Mail Client When Outposting

Background
I usually use onenote's "Email Page" function but the default email client used to sent is always thunderbird.

I tried

  • Setting mailto default in windows 10 default open application settings
  • Setting preferred Outlook as default mail client
Both not working

Solution
Good job, M$Soft, finally I used the following method to solve (removing registry).


Just remove the key under mail and mailTo folder, and that's it, no need to restart

2018年8月17日 星期五

[NodeJS] Import Module Without Executing the Script

When working on my nodeJS project, I encounter some kind of difficulties on the following scenario

I wrote an expressJS application, which in turn being allocated to be unit tested, the problem is I want to pass the expressJS application to my test program, so I figure out I can export the "app" from the "index.js", so I add

export default app


in my index.js, so finally I can export the app variable and import it to my unit test. But the problem is when I import the module, I also execute the code associated with module which is not what I want, is there anything like Python's if __name__ == "__main__"?

I just want to import the module without executing it, so I end up with the following strategies

I wrap all the actions in a function and return my app at the end

export function initApp() {
   app.use...
   app.use...
   return app;
}

Then I add this important snippet

if (require.main === module) {
    initApp();
}

This is important ! It tells nodeJS only if this file being run by node can the initApp being executed, so in my unit test case, I could just safely import this module without unintentionally execute the initApp function

2018年8月10日 星期五

[Ubuntu] Fix Microsoft Mouse Scroll Distance

Background
When using Microsoft mouse in Ubuntu 16, I found the scrolling distance is too large to adapt to, the following helps to fix it to normal

Solution
1. Run xinput list
2. Then run xinput list-props x | grep 'Scrolling Distance' where x is the id of your input device
3. Run xinput set-prop x 'Evdev Scrolling Distance' 10, 10, 10 to save the desired value
4. Add the command to .profile file if you want to save the settings permenantly

2018年1月17日 星期三

[Webpack] Limitation of number of files watch

When watching files with webpack, please make sure there are default limits on the number of files it can watch, (i.e.: 8192), if you want to watch more, please follow the below instructions

The current watch limit can be seen through the command
$ cat /proc/sys/fs/inotify/max_user_watches
In my case it was 8192 which is the default value for linux X64 systems
To change it temporarily we need to run the following commands
$ sudo sysctl fs.inotify.max_user_watches=524288
$ sudo sysctl -p
For permanently setting it we should run run
$ echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf
$ sudo sysctl -p

2017年11月5日 星期日

Set up Synergy - A Mouse and Keyboard Sharing Software

Synergy is a well-known mouse and keyboard sharing software across PCs with different platforms. The need of writing this is to demonstrate how it is setup.

Environment
PC1
- Windows 10 Pro 64 bit
- Synergy Windows Version 64 bit (v1.6.2)

PC2
- Ubuntu 16.04 64 bit
- Synergy Linux Version 64 bit  (v1.6.2)

Procedure / Points to Note
1. Download both version of Synergy. (Note: now the latest version charges money, use the old version would still be fine)

2. Remember, setting up the computer name in server side is important, the client name must match the name in the client PC, other it will not work. Also the name of both server and client must not contain special characters like "-", or it may not work

3. Every update of setup requires restart of synergy services

4. "Scroll Lock" to lock the mouse and keyboard in same machine


References
1. Making Synergy Startup After Windows Bootup
https://symless.com/forums/topic/2708-is-there-a-way-to-get-synergy-to-auto-start-on-windows-10-boot-up/

2. Synergy for Windows
http://www.snapfiles.com/downloads/synergy/dlsynergy.html

3. Making Synergy start with Ubuntu Bootup
https://askubuntu.com/questions/495962/how-to-autostart-synergy-on-ubunutu-14-04