SocialSharingMenu.vue 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. <template lang="pug">
  2. q-menu(
  3. auto-close
  4. anchor='bottom middle'
  5. self='top middle'
  6. @show='menuShown'
  7. @before-hide='menuHidden'
  8. )
  9. q-list(dense, padding)
  10. q-item(clickable, @click='', ref='copyUrlButton')
  11. q-item-section.items-center(avatar)
  12. q-icon(color='grey', name='las la-clipboard', size='sm')
  13. q-item-section.q-pr-md Copy URL
  14. q-item(clickable, tag='a', :href='`mailto:?subject=` + encodeURIComponent(props.title) + `&body=` + encodeURIComponent(urlFormatted) + `%0D%0A%0D%0A` + encodeURIComponent(props.description)', target='_blank')
  15. q-item-section.items-center(avatar)
  16. q-icon(color='grey', name='las la-envelope', size='sm')
  17. q-item-section.q-pr-md Email
  18. </template>
  19. <script setup>
  20. import ClipboardJS from 'clipboard'
  21. import { useQuasar } from 'quasar'
  22. import { computed, onMounted, reactive, ref } from 'vue'
  23. import { useI18n } from 'vue-i18n'
  24. // PROPS
  25. const props = defineProps({
  26. url: {
  27. type: String,
  28. default: null
  29. },
  30. title: {
  31. type: String,
  32. default: 'Untitled Page'
  33. },
  34. description: {
  35. type: String,
  36. default: ''
  37. }
  38. })
  39. // QUASAR
  40. const $q = useQuasar()
  41. // I18N
  42. const { t } = useI18n()
  43. // DATA
  44. const state = reactive({
  45. width: 626,
  46. height: 436,
  47. left: 0,
  48. top: 0,
  49. clip: null
  50. })
  51. let clip = null
  52. const copyUrlButton = ref(null)
  53. // COMPUTED
  54. const urlFormatted = computed(() => {
  55. if (!import.meta.env.SSR) {
  56. return props.url ? props.url : window.location.href
  57. } else {
  58. return ''
  59. }
  60. })
  61. // METHODS
  62. function openSocialPop (url) {
  63. const popupWindow = window.open(
  64. url,
  65. 'sharer',
  66. `status=no,height=${state.height},width=${state.width},resizable=yes,left=${state.left},top=${state.top},screenX=${state.left},screenY=${state.top},toolbar=no,menubar=no,scrollbars=no,location=no,directories=no`
  67. )
  68. popupWindow.focus()
  69. }
  70. function menuShown (ev) {
  71. clip = new ClipboardJS(copyUrlButton.value.$el, {
  72. text: () => { return urlFormatted.value }
  73. })
  74. clip.on('success', () => {
  75. $q.notify({
  76. message: 'URL copied successfully',
  77. icon: 'las la-clipboard'
  78. })
  79. })
  80. clip.on('error', () => {
  81. $q.notify({
  82. type: 'negative',
  83. message: 'Failed to copy to clipboard'
  84. })
  85. })
  86. }
  87. function menuHidden (ev) {
  88. clip.destroy()
  89. }
  90. // MOUNTED
  91. onMounted(() => {
  92. /**
  93. * Center the popup on dual screens
  94. * http://stackoverflow.com/questions/4068373/center-a-popup-window-on-screen/32261263
  95. */
  96. const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left
  97. const dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top
  98. const width = window.innerWidth ? window.innerWidth : (document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width)
  99. const height = window.innerHeight ? window.innerHeight : (document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height)
  100. state.left = ((width / 2) - (state.width / 2)) + dualScreenLeft
  101. state.top = ((height / 2) - (state.height / 2)) + dualScreenTop
  102. })
  103. </script>