FloatingBox.vue 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. <template>
  2. <div
  3. ref="box"
  4. :class="{
  5. 'floating-box': true,
  6. column
  7. }"
  8. :id="id"
  9. v-if="shown"
  10. :style="{
  11. width: width + 'px',
  12. height: height + 'px',
  13. top: top + 'px',
  14. left: left + 'px'
  15. }"
  16. @mousedown.left="onResizeBox"
  17. >
  18. <div class="box-header item-draggable" @mousedown.left="onDragBox">
  19. <span class="delete material-icons" @click="toggleBox()"
  20. >highlight_off</span
  21. >
  22. </div>
  23. <div class="box-body">
  24. <slot name="body"></slot>
  25. </div>
  26. </div>
  27. </template>
  28. <script>
  29. export default {
  30. props: {
  31. id: { type: String, default: null },
  32. column: { type: Boolean, default: true }
  33. },
  34. data() {
  35. return {
  36. width: 200,
  37. height: 200,
  38. top: 0,
  39. left: 0,
  40. shown: false,
  41. pos1: 0,
  42. pos2: 0,
  43. pos3: 0,
  44. pos4: 0
  45. };
  46. },
  47. mounted() {
  48. if (this.id !== null && localStorage[`box:${this.id}`]) {
  49. const json = JSON.parse(localStorage.getItem(`box:${this.id}`));
  50. this.height = json.height;
  51. this.width = json.width;
  52. this.top = json.top;
  53. this.left = json.left;
  54. this.shown = json.shown;
  55. }
  56. },
  57. methods: {
  58. onDragBox(e) {
  59. const e1 = e || window.event;
  60. e1.preventDefault();
  61. this.pos3 = e1.clientX;
  62. this.pos4 = e1.clientY;
  63. document.onmousemove = e => {
  64. const e2 = e || window.event;
  65. e2.preventDefault();
  66. // calculate the new cursor position:
  67. this.pos1 = this.pos3 - e.clientX;
  68. this.pos2 = this.pos4 - e.clientY;
  69. this.pos3 = e.clientX;
  70. this.pos4 = e.clientY;
  71. // set the element's new position:
  72. this.top -= this.pos2;
  73. this.left -= this.pos1;
  74. };
  75. document.onmouseup = () => {
  76. document.onmouseup = null;
  77. document.onmousemove = null;
  78. this.saveBox();
  79. };
  80. },
  81. onResizeBox(e) {
  82. if (e.target !== this.$refs.box) return;
  83. document.onmouseup = () => {
  84. document.onmouseup = null;
  85. const { height, width } = e.target.style;
  86. this.height = Number(
  87. height
  88. .split("")
  89. .splice(0, height.length - 2)
  90. .join("")
  91. );
  92. this.width = Number(
  93. width
  94. .split("")
  95. .splice(0, width.length - 2)
  96. .join("")
  97. );
  98. this.saveBox();
  99. };
  100. },
  101. toggleBox() {
  102. this.shown = !this.shown;
  103. this.saveBox();
  104. },
  105. resetBox() {
  106. this.top = 0;
  107. this.left = 0;
  108. this.width = 200;
  109. this.height = 200;
  110. this.saveBox();
  111. },
  112. saveBox() {
  113. if (this.id === null) return;
  114. localStorage.setItem(
  115. `box:${this.id}`,
  116. JSON.stringify({
  117. height: this.height,
  118. width: this.width,
  119. top: this.top,
  120. left: this.left,
  121. shown: this.shown
  122. })
  123. );
  124. }
  125. }
  126. };
  127. </script>
  128. <style lang="scss">
  129. .night-mode .floating-box {
  130. background-color: var(--dark-grey-2) !important;
  131. border: 0 !important;
  132. .box-body b {
  133. color: var(--light-grey-2) !important;
  134. }
  135. }
  136. .floating-box {
  137. display: flex;
  138. background-color: var(--white);
  139. color: var(--black);
  140. position: fixed;
  141. z-index: 10000000;
  142. resize: both;
  143. overflow: auto;
  144. border: 1px solid var(--light-grey-2);
  145. border-radius: 5px;
  146. min-height: 50px !important;
  147. min-width: 50px !important;
  148. padding: 0;
  149. &.column {
  150. flex-direction: column;
  151. }
  152. .box-header {
  153. z-index: 100000001;
  154. background-color: var(--primary-color);
  155. display: block;
  156. height: 24px;
  157. width: 100%;
  158. .delete.material-icons {
  159. position: absolute;
  160. top: 2px;
  161. right: 2px;
  162. font-size: 20px;
  163. color: var(--white);
  164. cursor: pointer;
  165. &:hover,
  166. &:focus {
  167. filter: brightness(90%);
  168. }
  169. }
  170. }
  171. .box-body {
  172. display: flex;
  173. flex-wrap: wrap;
  174. padding: 10px;
  175. height: calc(100% - 24px); /* 24px is the height of the box-header */
  176. overflow: auto;
  177. span {
  178. padding: 3px 6px;
  179. }
  180. }
  181. &.column .box-body {
  182. flex-flow: column;
  183. span {
  184. flex: 1;
  185. display: block;
  186. }
  187. }
  188. }
  189. </style>