/ Gists

Gists

On gists

useScrollToBottom

Vue.js

useScrollToBottom.js #

// pagination list, load more (or lazy load) 

import { onMounted, onUnmounted } from 'vue';

export const useScrollToBottom = (callback = () => { }) => {
  const handleScrolling = () => {
    if ((window.innerHeight + window.scrollY) >= document.body.scrollHeight) {
      callback();
    }
  }

  onMounted(() => {
    window.addEventListener('scroll', handleScrolling);
  });

  onUnmounted(() => {
    window.removeEventListener('scroll', handleScrolling);
  });
}

// usage 
useScrollToBottom(() => { console.log('Scrolled to bottom') })

On gists

useOnClickOutside

Vue.js

useOnClickOutside.js #

import { onMounted, onUnmounted } from 'vue';

export const useOnClickOutside = (ref = null, callback = () => {}) => {
  function handleClickOutside(event) {
    if (ref.value && !ref.value.contains(event.target)) {
      callback()
    }
  }

  onMounted(() => {
    document.addEventListener('mousedown', handleClickOutside);
  })

  onUnmounted(() => {
    document.removeEventListener('mousedown', handleClickOutside);
  });
}

// usage

<template>
    <div ref="container">View</div>
</template>
<script>
import { ref } from 'vue';
export default {
    setup() {
        const container = ref(null);
        useOnClickOutside(container, () => {
            console.log('Clicked outside'); 
        })
    }
}
</script>

On gists

useViewport

Vue.js

useViewport.js #

import { ref, onMounted, onUnmounted } from 'vue';

export const MOBILE = 'MOBILE'
export const TABLET = 'TABLET'
export const DESKTOP = 'DESKTOP'

export const useViewport = (config = {}) => {
  const { mobile = null, tablet = null } = config;
  let mobileWidth = mobile ? mobile : 768;
  let tabletWidth = tablet ? tablet : 922;
  let device = ref(getDevice(window.innerWidth));
  function getDevice(width) {
    if (width < mobileWidth) {
      return MOBILE;
    } else if (width < tabletWidth) {
      return TABLET;
    }
    return DESKTOP;
  }

  const handleResize = () => {
    device.value = getDevice(window.innerWidth);
  }

  onMounted(() => {
    window.addEventListener('resize', handleResize);
  });

  onUnmounted(() => {
    window.removeEventListener('resize', handleResize);
  });

  return {
    device
  }
}


// usage
const { device } = useViewport({ mobile: 700, table: 900 });

On gists

useCopyToClipboard

JS oneliners Vue.js

useCopyToClipboard.js #

function copyToClipboard(text) {
  let input = document.createElement('input');
  input.setAttribute('value', text);
  document.body.appendChild(input);
  input.select();
  let result = document.execCommand('copy');
  document.body.removeChild(input);
  return result;
}

export const useCopyToClipboard = () => {
  return (text) => {
    if (typeof text === "string" || typeof text == "number") {
      return copyToClipboard(text);
    }
    return false;
  }
}

// usage
const copyToClipboard = useCopyToClipboard();
copyToClipboard('just copy');

On gists

useNetworkStatus

Vue.js

useNetworkStatus.js #

import { onMounted, onUnmounted } from 'vue';

export const useNetworkStatus = (callback = () => { }) => {
  const updateOnlineStatus = () => {
    const status = navigator.onLine ? 'online' : 'offline';
    callback(status);
  }

  onMounted(() => {
    window.addEventListener('online', updateOnlineStatus);
    window.addEventListener('offline', updateOnlineStatus);
  });

  onUnmounted(() => {
    window.removeEventListener('online', updateOnlineStatus);
    window.removeEventListener('offline', updateOnlineStatus);
  })
}


// usage
useNetworkStatus((status) => { 
    console.log(`Your network status is ${status}`);
}

On gists

useStorage

Vue.js

useStorage.js #

// https://javascript.plainenglish.io/10-useful-custom-hooks-with-vue-js-37f0fd42ce0d

import { ref } from 'vue';

const getItem = (key, storage) => {
  let value = storage.getItem(key);
  if (!value) {
    return null;
  }
  try {
    return JSON.parse(value)
  } catch (error) {
    return value;
  }
}

export const useStorage = (key, type = 'session') => {
  let storage = null;
  switch (type) {
    case 'session':
      storage = sessionStorage;
      break;
    case 'local':
      storage = localStorage;
      break;
    default:
      return null;
  }
  const value = ref(getItem(key, storage));
  const setItem = (storage) => {
    return (newValue) => {
      value.value = newValue;
      storage.setItem(key, JSON.stringify(newValue));
    }
  }
  return [
    value,
    setItem(storage)
  ]
}


// usage
const [token, setToken] = useStorage('token');
setToken('new token');

On gists

useWindowResize

Vue.js

useWindowResize.js #

import { ref, onMounted, onUnmounted } from 'vue';

export function useWindowResize() {
  const width = ref(window.innerWidth);
  const height = ref(window.innerHeight);
  const handleResize = () => {
    width.value = window.innerWidth;
    height.value = window.innerHeight;
  }

  onMounted(() => {
    window.addEventListener('resize', handleResize)
  });

  onUnmounted(() => {
    window.removeEventListener('resize', handleResize)
  })

  return {
    width,
    height
  }
}


// usage
setup() {
    const { width, height } = useWindowResize();
}

On gists

Colorpicker + event

JavaScript

ex.html #

<body>
	<input type="color" id="color" value="#c1e0ff" />
</body>


<script>

const color = document.querySelector('#color')
const div = document.body

color.addEventListener('input', () => {
	div.style.backgroundColor = color.value
})

color.dispatchEvent(new Event('input'));

</script>

On gists

Random colors (hexa)

JS oneliners

demo.js #

const generateRandomHexColor = () =>
  `#${Math.floor(Math.random() * 0xffffff).toString(16)}`;

On gists

Scroll top / bottom

JS oneliners

demo.js #

const scrollToTop = (element) =>
  element.scrollIntoView({ behavior: "smooth", block: "start" });
  
  const scrollToBottom = (element) =>
  element.scrollIntoView({ behavior: "smooth", block: "end" });