el-dialog dragging implementation and dragging process cannot be dragged in some areas, and the position is incorrect in full-screen mode and its solution (general version)

el-dialog drag and drop implementation and the drag process. Some areas cannot be dragged, and the position is incorrect in full screen mode and the solution (general version)

The project template uses the vue-admin-element version
It has its own drag and drop method.

This is the method copied above dialogDrag.js

import Vue from 'vue'

// v-dialogDrag: Pop-up window drag attribute (Key point!!! Add this attribute to the modal box and the modal box can be dragged)
Vue.directive('dialogDrag', {<!-- --> // Property name dialogDrag, add v- in front of it to use
  bind(el, binding, vnode) {<!-- -->
    const dialogHeaderEl = el.querySelector('.el-dialog__header')
    const dragDom = el.querySelector('.el-dialog')
    dialogHeaderEl.style.cssText + = ';cursor:move;'
    dragDom.style.cssText + = ';top:0px;'

    // Get the original attributes ie dom element.currentStyle Firefox Google window.getComputedStyle(dom element, null);
    const getStyle = (function() {<!-- -->
      if (window.document.currentStyle) {<!-- -->
        return (dom, attr) => dom.currentStyle[attr]
      } else {<!-- -->
        return (dom, attr) => getComputedStyle(dom, false)[attr]
      }
    })()

    dialogHeaderEl.onmousedown = (e) => {<!-- -->
      // When the mouse is pressed, calculate the distance between the current element and the visible area
      const disX = e.clientX - dialogHeaderEl.offsetLeft
      const disY = e.clientY - dialogHeaderEl.offsetTop

      const dragDomWidth = dragDom.offsetWidth
      // const dragDomHeight = dragDom.offsetHeight

      const screenWidth = document.body.clientWidth
      const screenHeight = document.body.clientHeight

      const minDragDomLeft = dragDom.offsetLeft
      const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth

      const minDragDomTop = dragDom.offsetTop
      // const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomHeight
      const maxDragDomTop = screenHeight - dragDom.offsetTop// No need for -dragDomHeight

      //The obtained value has px regular matching and replacement
      let styL = getStyle(dragDom, 'left')
      let styT = getStyle(dragDom, 'top')

      if (styL.includes('%')) {<!-- -->
        styL = + document.body.clientWidth * ( + styL.replace(/\%/g, '') / 100)
        styT = + document.body.clientHeight * ( + styT.replace(/\%/g, '') / 100)
      } else {<!-- -->
        styL = + styL.replace(/\px/g, '')
        styT = + styT.replace(/\px/g, '')
      }

      document.onmousemove = function(e) {<!-- -->
        //Calculate the distance moved through event delegation
        let left = e.clientX - disX
        let top = e.clientY - disY

        // Boundary processing
        if (-(left) > minDragDomLeft) {<!-- -->
          left = -minDragDomLeft
        } else if (left > maxDragDomLeft) {<!-- -->
          left = maxDragDomLeft
        }

        if (-(top) > minDragDomTop) {<!-- -->
          top = -minDragDomTop
        } else if (top > maxDragDomTop) {<!-- -->
          top = maxDragDomTop
        }

        //Move the current element
        dragDom.style.cssText + = `;left:${<!-- -->left + styL}px;top:${<!-- -->top + styT}px;`

        // emit onDrag event
        vnode.child.$emit('dragDialog')
      }

      document.onmouseup = function(e) {<!-- -->
        document.onmousemove = null
        document.onmouseup = null
      }
    }
  }
})

Introduce it into main.js and you can use it. Change the location yourself

import '@/utils/dialogDrag' // Add drag and drop to global dialog

Add v-dialogDrag on el-dialog to achieve the drag effect

<el-dialog v-dialogDrag></el-dialog>

Existing problems

1. When dragging, some areas cannot be dragged, and full-screen dragging is not involved

Solution: I won’t explain it. Just copy it and replace the content of dialogDrag.js

import Vue from 'vue'

// v-dialogDrag: Pop-up window drag attribute (Key point!!! Add this attribute to the modal box and the modal box can be dragged)
Vue.directive('dialogDrag', {<!-- --> // Property name dialogDrag, add v- in front of it to use
  bind(el, binding, vnode) {<!-- -->
    const dialogHeaderEl = el.querySelector('.el-dialog__header')
    const dragDom = el.querySelector('.el-dialog')
    dialogHeaderEl.style.cssText + = ';cursor:move;'
    dragDom.style.cssText + = ';top:0px;'

    // Get the original attributes ie dom element.currentStyle Firefox Google window.getComputedStyle(dom element, null);
    const getStyle = (function() {<!-- -->
      if (window.document.currentStyle) {<!-- -->
        return (dom, attr) => dom.currentStyle[attr]
      } else {<!-- -->
        return (dom, attr) => getComputedStyle(dom, false)[attr]
      }
    })()

    dialogHeaderEl.onmousedown = (e) => {<!-- -->
      // When the mouse is pressed, calculate the distance between the current element and the visible area
      const disX = e.clientX - dialogHeaderEl.offsetLeft
      const disY = e.clientY - dialogHeaderEl.offsetTop

      const dragDomWidth = dragDom.offsetWidth
      // const dragDomHeight = dragDom.offsetHeight

      const screenWidth = document.body.clientWidth
      const screenHeight = document.body.clientHeight

      const minDragDomLeft = dragDom.offsetLeft
      const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth

      const minDragDomTop = dragDom.offsetTop
      // const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomHeight
      const maxDragDomTop = screenHeight - dragDom.offsetTop// No need for -dragDomHeight

      //The obtained value has px regular matching and replacement
      let styL = getStyle(dragDom, 'left')
      let styT = getStyle(dragDom, 'top')

      if (styL.includes('%')) {<!-- -->
        styL = + document.body.clientWidth * ( + styL.replace(/\%/g, '') / 100)
        styT = + document.body.clientHeight * ( + styT.replace(/\%/g, '') / 100)
      } else {<!-- -->
        styL = + styL.replace(/\px/g, '')
        styT = + styT.replace(/\px/g, '')
      }

      document.onmousemove = function(e) {<!-- -->
        //Calculate the distance moved through event delegation
        let left = e.clientX - disX
        let top = e.clientY - disY

        // Boundary processing
        if (-(left) > minDragDomLeft) {<!-- -->
          left = -minDragDomLeft
        } else if (left > maxDragDomLeft) {<!-- -->
          left = maxDragDomLeft
        }

        if (-(top) > minDragDomTop) {<!-- -->
          top = -minDragDomTop
        } else if (top > maxDragDomTop) {<!-- -->
          top = maxDragDomTop
        }

        //Move the current element
        dragDom.style.cssText + = `;left:${<!-- -->left + styL}px;top:${<!-- -->top + styT}px;`

        // emit onDrag event
        vnode.child.$emit('dragDialog')
      }

      document.onmouseup = function(e) {<!-- -->
        document.onmousemove = null
        document.onmouseup = null
      }
    }
  }
})

The problem was solved after replacing

2. The full screen position is wrong after dragging

Solution: It’s very simple. When you click full screen, the setting position can be restored to the default
Add it to the method yourself
Note: Prevent affecting other el-dialog
We try to add id to el-dialog as much as possible
The id given here is dragDialog

 // Prevent dragging from affecting the full screen and restore it to the center position
      this.$nextTick(() => {<!-- -->
        const dialog = document.querySelector('#dragDialog .el-dialog')
        dialog.style.left = '0'
        dialog.style.top = '0'
      })

Notice! ! ! Must be in synchronization situation, nextTick is used here

If it is useful, please give me a like and save it, I will be very happy, thank you