Browse Source

implement mouse dragging

subDesTagesMitExtraKaese 2 years ago
parent
commit
434fa2f68e

+ 18 - 12
zitap/static/zitap/css/date-picker.css

@@ -2,18 +2,20 @@
     display: grid;
     grid-template-columns: repeat(9, 1fr);
     grid-template-rows: repeat(6, 1fr);
-    grid-gap: 1px;
+    grid-gap: 0.2rem;
     justify-items: center;
     align-items: center;
     user-select: none;
 }
 .date-picker .month {
     font-weight: bold;
-    padding: 3px;
+    justify-self: stretch;
+    align-self: stretch;
 }
 .date-picker .year {
     font-weight: bold;
-    padding: 3px;
+    justify-self: stretch;
+    align-self: stretch;
 }
 .date-picker .day.hidden {
     visibility: hidden;
@@ -27,26 +29,30 @@
     transition: all .5s ease;
     cursor: pointer;
     position: relative;
+    justify-self: stretch;
+    align-self: stretch;
+    display: grid;
 }
 .date-picker .day input[type=checkbox] {
     visibility: hidden;
     position: absolute;
 }
 .date-picker .day-number {
-    font-size: 10pt;
-    width: 20pt;
-    height: 20pt;
-    z-index: 10;
+    font-size: 1em;
+    width: 100%;
+    height: 100%;
     transition: background-color .2s ease;
     display: grid;
-    align-items: center;
     justify-items: center;
+    align-items: center;
     cursor: pointer;
 }
-.date-picker .day:hover {
-    background-color: rgb(255, 255, 255);
-    cursor: pointer;
+.date-picker .day label:hover {
+    background-color: #d65d5d;
+}
+.date-picker .day input[type=checkbox]:checked + label:hover {
+    background-color: rgb(185, 165, 52);
 }
-.date-picker input[type=checkbox]:checked + label {
+.date-picker .day input[type=checkbox]:checked + label {
     background-color: rgb(52, 185, 52);
 }

+ 0 - 0
zitap/static/zitap/js/date-picker.js


+ 98 - 0
zitap/static/zitap/js/mouse-drag.js

@@ -0,0 +1,98 @@
+window.onload = function()
+{
+  let dragStart = null
+  let currentTargetChecked = null
+  let originalStates = []
+
+  const checkables = []
+  for (const element of document.getElementsByClassName("checkable"))
+  {
+    element.onmousedown = mouseDownHandler
+    element.onclick = function(e) { e.preventDefault() }
+    if(element.tagName == "INPUT")
+      checkables.push(element)
+  }
+
+  document.onmousemove = mouseMoveHandler
+  document.onmouseup = mouseUpHandler
+
+  function mouseDownHandler(e)
+  {
+    dragStart = {x: e.clientX, y: e.clientY}
+    let currentTarget
+    if (e.target.tagName == "INPUT")
+    {
+      currentTarget = e.target
+    }
+    else
+    {
+      currentTarget = e.target.parentNode.getElementsByTagName("input")[0]
+    }
+    currentTargetChecked = !currentTarget.checked
+    currentTarget.checked = currentTargetChecked
+
+    // save current state of all checkables
+    originalStates = []
+    for (let checkable of checkables)
+      originalStates.push(checkable.checked)
+  }
+  function mouseUpHandler(e)
+  {
+    if (!dragStart)
+      return
+    dragStart = null
+    let rectElement = document.getElementById("rect")
+    if (rectElement)
+      rectElement.parentNode.removeChild(rectElement)
+  }
+  function mouseMoveHandler(e)
+  {
+    if (!dragStart)
+      return
+    
+    // get rectangle of dragged area
+    let rect = {
+      left: Math.min(dragStart.x, e.clientX),
+      top: Math.min(dragStart.y, e.clientY),
+      right: Math.max(dragStart.x, e.clientX),
+      bottom: Math.max(dragStart.y, e.clientY)
+    }
+    // draw rectangle
+    let rectElement = document.getElementById("rect")
+    if (!rectElement)
+    {
+      rectElement = document.createElement("div")
+      rectElement.id = "rect"
+      rectElement.style.position = "absolute"
+      rectElement.style.border = "1px solid black"
+      rectElement.style.zIndex = "100"
+      document.body.appendChild(rectElement)
+    }
+    rectElement.style.left = rect.left + "px"
+    rectElement.style.top = rect.top + "px"
+    rectElement.style.width = (rect.right - rect.left) + "px"
+    rectElement.style.height = (rect.bottom - rect.top) + "px"
+
+    // get all checkables in dragged area
+    for(let i = 0; i < checkables.length; i++)
+    {
+      let checkable = checkables[i]
+
+      let checkableRect = checkable.parentNode.getBoundingClientRect()
+      // check if checkable intersects the dragged area
+      if (checkableRect.left < rect.right &&
+          checkableRect.right > rect.left &&
+          checkableRect.top < rect.bottom &&
+          checkableRect.bottom > rect.top)
+      {
+        checkable.checked = currentTargetChecked
+      }
+      else
+      {
+        checkable.checked = originalStates[i]
+      }
+    }
+    
+  }
+}
+

+ 2 - 2
zitap/templates/widgets/date-picker.html

@@ -10,8 +10,8 @@
         <div class="month">{{ week.month }}</div>
         {% for day in week.days %}
             <div class="day{% if day.date == widget.today %} today{% endif %}{% if day.date < widget.today %} hidden{% endif %}">
-                <input type="checkbox" id="date_{{ day.date|date:"Y-m-d" }}" name="date_{{ day.date|date:"Y-m-d" }}" />
-                <label class="day-number" for="date_{{ day.date|date:"Y-m-d" }}">{{ day.day }}</label>
+                <input class="checkable" type="checkbox" id="date_{{ day.date|date:"Y-m-d" }}" name="date_{{ day.date|date:"Y-m-d" }}" />
+                <label class="checkable day-number" for="date_{{ day.date|date:"Y-m-d" }}">{{ day.day }}</label>
             </div>
         {% endfor %}
         <div class="year">{{ week.year }}</div>

+ 1 - 0
zitap/templates/zitap/create-event.html

@@ -14,4 +14,5 @@
     {{ form.non_field_errors }}
     <input type="submit" value="Create Event">
 </form>
+<script type="text/javascript" src="{% static 'zitap/js/mouse-drag.js' %}"></script>
 {% endblock %}