Photo by Sam Moqadam on Unsplash
I share one trick a day until the original scheduled date of the end of the COVID-19 quarantine in Switzerland, April 19th 2020. Seven days left until this first milestone. Hopefully better days are ahead.
We are using a couple of JavaScript functions across the multiple applications and Web Components of DeckDeckGo.
Maybe these can be useful for your projects too?
Unifying Mouse And Touch Events
If you are implementing functions which have to do with user interactions through mouse or touch devices, there is a good change that their outcome are the same.
For example, presenters can draw over their presentations using our remote control. For such purpose we use canvas and are attaching events such as:
const canvas = document.querySelector("canvas");
canvas.addEventListener("mousedown", this.startEvent);
canvas.addEventListener("touchstart", this.startEvent);
As you can notice, both mouse
and touch
events are handled by the same functions, which is good, but unfortunately, can’t work out without a bit of logic if you would like to access to positions information as for example clientX
or clientY
.
Indeed, touch
positioning are not available at the root of the object but rather in an array changedTouches
.
function startEvent($event) {
// MouseEvent
console.log($event.clientX);
// TouchEvent
console.log($event.changedTouches[0].clientX);
}
That’s why, we are using a function we have called unifyEvents
to get the positioning regardless of the devices.
export function unifyEvent($event) {
return $event.changedTouches ? $event.changedTouches[0] : $event;
}
Which can be use as the following:
function startEvent($event) {
// TouchEvent and MouseEvent unified
console.log(unifyEvent($event).clientX);
}
Debouncing
I covered the topic debouncing with JavaScript in a previous article but if you are looking to add such feature to your application without any dependencies, here’s a function to do so.
export function debounce(func, timeout?) {
let timer;
return (...args) => {
const next = () => func(...args);
if (timer) {
clearTimeout(timer);
}
timer =
setTimeout(next, timeout && timeout > 0 ? timeout : 300);
};
}
User Agent
Earlier this year, Google has announced its decision to drop support for the User-Agent string in its Chrome browser (article / GitHub).
Therefor the following methods should be used wisely, knowing they will have to be replaced in the future.
That being said, here are a couple of handy functions which help detects information about the type of browser or device.
isMobile
Detect Mobile Browsers is providing an open source list of mobile devices which can be use to test our navigator to detect if the user is browsing or using the application on a mobile device or not.
export function isMobile() {
if (!window || !navigator) {
return false;
}
const a =
navigator.userAgent || navigator.vendor ||
(window as any).opera;
// Regex Source -> http://detectmobilebrowsers.com
return (
/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od|ad)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(
a
) ||
/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(
a.substr(0, 4)
)
);
}
isIOS
To detect if our user is using an Apple mobile devices, we can test the navigator against the keywords iPad|iPhone|iPod
.
export function isIOS() {
if (!window || !navigator) {
return false;
}
const a =
navigator.userAgent || navigator.vendor ||
(window as any).opera;
return /iPad|iPhone|iPod/i.test(a);
}
isIPad
Likewise, we can reduce the query to iPad
only to guess if the user is on an iPad.
export function isIPad() {
if (!window || !navigator) {
return false;
}
const a =
navigator.userAgent || navigator.vendor ||
(window as any).opera;
return /iPad/i.test(a);
}
isFirefox
Likewise, you can detect if the client is using a specific browser as for final example Firefox.
export function isFirefox() {
if (!window || !navigator) {
return false;
}
const a =
navigator.userAgent || navigator.vendor ||
(window as any).opera;
return /firefox/i.test(a);
}
Full screen
Our presentations can be edited and browse in standalone or in full screen mode, that’s why we have to detect such state. For such purpose, we compare the window.innerHeight
to the screen.height
, if these are equals, the browser is in full screen mode.
export function isFullscreen() {
if (!window || !screen) {
return false;
}
return window.innerHeight == screen.height;
}
Remove Attribute From HTML String
Let say your DOM contains an element which you would like to parse to a string
with the help of JavaScript.
<div contentEditable="true" style="color: #ff0000">
Red
</div>;
const div = document.querySelector("div").outerHTML;
For some reason, you might not be able to touch or clone the DOM element but would be interested to remove an attribute from string
value anyway.
Respectively, you would be interested in such result:
<div style="color: #ff0000">Red</div>
To clean up or remove an attribute from a string you can use the following handy RegExp:
const result = div
.replace(/(<.*?)(contentEditable=""
|contentEditable="true"
|contentEditable="false"
|contentEditable)
(.*?>)/gi, '$1$3');
Basically, it searches all attribute possibilities and create a new string
containing what’s before and after the selection.
My favorite tricks of all of these 😉.
Summary
DeckDeckGo is open source, you can find the above functions in our GitHub repo or their related npm packages.
Stay home, stay safe!
David