我正在try 创建一个简单的日历应用程序,在其内部本地存储其事件和任务

目前,它使用单个文本框来存储事件数据,并且不允许在事件内进行任务处理.只是一个大的文本可编辑框,仅用于文本输入.

因此,如何更改我的代码,使其在一天内处理多达20个事件,每个事件都有自己的关联任务列表,而不是为一个日期的所有事件使用一个文本框

即:9月22日有四个事件:事件1、事件2、事件3、事件4.目前,如上所述,存储的是完全没有分开的单行事件.我想try 让单项赛事有自己的任务集.

举个例子,我想试着做以下几件事; 点击月份内的日期例如22月22日

Line编辑事件1、复选框任务1、复选框任务2、复选框任务3

Line编辑事件2、复选框任务1、复选框任务2、复选框任务3

Line编辑事件3、复选框任务1、复选框任务2、复选框任务3

Line编辑事件4、复选框任务1、复选框任务2、复选框任务3

有点像这样的东西;

<textarea id="evt-details" rows="5" cols="35"></textarea><br>
<input type="checkbox" value="Task 1"><label>Task2</label><br>
<input type="checkbox" value="Task 2"><label>Task2</label><br>
<input type="checkbox" value="Task 3"><label>Task 3</label><br>

但更干净,允许多个单独的事件,并允许它们被单独编辑、修改和删除,并仍然允许扩展日历方块,以显示当天的所有事件,如果多个,我理想地希望显示任务完成的 colored颜色 代码-或当勾选时,写在事件旁边的"任务1完成"作为一个例子.

等等.

var cal = {
  // (A) PROPERTIES
  // (A1) COMMON CALENDAR
  sMon : false, // Week start on Monday?
  mName : ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // Month Names

  // (A2) CALENDAR DATA
  data : null, // Events for the selected period
  sDay : 0, sMth : 0, sYear : 0, // Current selected day, month, year

  // (A3) COMMON HTML ELEMENTS
  hMth : null, hYear : null, // month/year selector
  hForm : null, hfHead : null, hfDate : null, hfTxt : null, hfDel : null, // event form

  // (B) INIT CALENDAR
  init : () => {
    // (B1) GET + SET COMMON HTML ELEMENTS
    cal.hMth = document.getElementById("cal-mth");
    cal.hYear = document.getElementById("cal-yr");
    cal.hForm = document.getElementById("cal-event");
    cal.hfHead = document.getElementById("evt-head");
    cal.hfDate = document.getElementById("evt-date");
    cal.hfTxt = document.getElementById("evt-details");
    cal.hfDel = document.getElementById("evt-del");
    document.getElementById("evt-close").onclick = cal.close;
    cal.hfDel.onclick = cal.del;
    cal.hForm.onsubmit = cal.save;

    // (B2) DATE NOW
    let now = new Date(),
        nowMth = now.getMonth(),
        nowYear = parseInt(now.getFullYear());

    // (B3) APPEND MONTHS SELECTOR
    for (let i=0; i<12; i++) {
      let opt = document.createElement("option");
      opt.value = i;
      opt.innerHTML = cal.mName[i];
      if (i==nowMth) { opt.selected = true; }
      cal.hMth.appendChild(opt);
    }
    cal.hMth.onchange = cal.list;

    // (B4) APPEND YEARS SELECTOR
    // Set to 10 years range. Change this as you like.
    for (let i=nowYear-10; i<=nowYear+10; i++) {
      let opt = document.createElement("option");
      opt.value = i;
      opt.innerHTML = i;
      if (i==nowYear) { opt.selected = true; }
      cal.hYear.appendChild(opt);
    }
    cal.hYear.onchange = cal.list;

    // (B5) START - DRAW CALENDAR
    cal.list();
  },

  // (C) DRAW CALENDAR FOR SELECTED MONTH
  list : () => {
    // (C1) BASIC CALCULATIONS - DAYS IN MONTH, START + END DAY
    // Note - Jan is 0 & Dec is 11
    // Note - Sun is 0 & Sat is 6
    cal.sMth = parseInt(cal.hMth.value); // selected month
    cal.sYear = parseInt(cal.hYear.value); // selected year
    let daysInMth = new Date(cal.sYear, cal.sMth+1, 0).getDate(), // number of days in selected month
        startDay = new Date(cal.sYear, cal.sMth, 1).getDay(), // first day of the month
        endDay = new Date(cal.sYear, cal.sMth, daysInMth).getDay(), // last day of the month
        now = new Date(), // current date
        nowMth = now.getMonth(), // current month
        nowYear = parseInt(now.getFullYear()), // current year
        nowDay = cal.sMth==nowMth && cal.sYear==nowYear ? now.getDate() : null ;

    // (C2) LOAD DATA FROM LOCALSTORAGE
    cal.data = localStorage.getItem("cal-" + cal.sMth + "-" + cal.sYear);
    if (cal.data==null) {
      localStorage.setItem("cal-" + cal.sMth + "-" + cal.sYear, "{}");
      cal.data = {};
    } else { cal.data = JSON.parse(cal.data); }

    // (C3) DRAWING CALCULATIONS
    // Blank squares before start of month
    let squares = [];
    if (cal.sMon && startDay != 1) {
      let blanks = startDay==0 ? 7 : startDay ;
      for (let i=1; i<blanks; i++) { squares.push("b"); }
    }
    if (!cal.sMon && startDay != 0) {
      for (let i=0; i<startDay; i++) { squares.push("b"); }
    }

    // Days of the month
    for (let i=1; i<=daysInMth; i++) { squares.push(i); }

    // Blank squares after end of month
    if (cal.sMon && endDay != 0) {
      let blanks = endDay==6 ? 1 : 7-endDay;
      for (let i=0; i<blanks; i++) { squares.push("b"); }
    }
    if (!cal.sMon && endDay != 6) {
      let blanks = endDay==0 ? 6 : 6-endDay;
      for (let i=0; i<blanks; i++) { squares.push("b"); }
    }

    // (C4) DRAW HTML CALENDAR
    // Get container
    let container = document.getElementById("cal-container"),
    cTable = document.createElement("table");
    cTable.id = "calendar";
    container.innerHTML = "";
    container.appendChild(cTable);

    // First row - Day names
    let cRow = document.createElement("tr"),
        days = ["Sun", "Mon", "Tue", "Wed", "Thur", "Fri", "Sat"];
    if (cal.sMon) { days.push(days.shift()); }
    for (let d of days) {
      let cCell = document.createElement("td");
      cCell.innerHTML = d;
      cRow.appendChild(cCell);
    }
    cRow.classList.add("head");
    cTable.appendChild(cRow);

    // Days in Month
    let total = squares.length;
    cRow = document.createElement("tr");
    cRow.classList.add("day");
    for (let i=0; i<total; i++) {
      let cCell = document.createElement("td");
      if (squares[i]=="b") { cCell.classList.add("blank"); }
      else {
        if (nowDay==squares[i]) { cCell.classList.add("today"); }
        cCell.innerHTML = `<div class="dd">${squares[i]}</div>`;
        if (cal.data[squares[i]]) {
          cCell.innerHTML += "<div class='evt'>" + cal.data[squares[i]] + "</div>";
        }
        cCell.onclick = () => { cal.show(cCell); };
      }
      cRow.appendChild(cCell);
      if (i!=0 && (i+1)%7==0) {
        cTable.appendChild(cRow);
        cRow = document.createElement("tr");
        cRow.classList.add("day");
      }
    }

    // (C5) REMOVE ANY PREVIOUS ADD/EDIT EVENT DOCKET
    cal.close();
  },

  // (D) SHOW EDIT EVENT DOCKET FOR SELECTED DAY
  show : (el) => {
    // (D1) FETCH EXISTING DATA
    cal.sDay = el.getElementsByClassName("dd")[0].innerHTML;
    let isEdit = cal.data[cal.sDay] !== undefined ;

    // (D2) UPDATE EVENT FORM
    cal.hfTxt.value = isEdit ? cal.data[cal.sDay] : "" ;
    cal.hfHead.innerHTML = isEdit ? "EDIT EVENT" : "ADD EVENT" ;
    cal.hfDate.innerHTML = `${cal.sDay} ${cal.mName[cal.sMth]} ${cal.sYear}`;
    if (isEdit) { cal.hfDel.classList.remove("ninja"); }
    else { cal.hfDel.classList.add("ninja"); }
    cal.hForm.classList.remove("ninja");
  },

  // (E) CLOSE EVENT DOCKET
  close : () => {
    cal.hForm.classList.add("ninja");
  },

  // (F) SAVE EVENT
  save : () => {
    cal.data[cal.sDay] = cal.hfTxt.value;
    localStorage.setItem(`cal-${cal.sMth}-${cal.sYear}`, JSON.stringify(cal.data));
    cal.list();
    return false;
  },

  // (G) DELETE EVENT FOR SELECTED DATE
  del : () => { if (confirm("Delete event?")) {
    delete cal.data[cal.sDay];
    localStorage.setItem(`cal-${cal.sMth}-${cal.sYear}`, JSON.stringify(cal.data));
    cal.list();
  }}
};
window.addEventListener("load", cal.init);
/* (A) ENTIRE PAGE */
#cal-wrap * { font-family: arial, sans-serif; }
.ninja { display: none !important; }

/* (B) CONTAINER */
#cal-wrap { max-width: 900px; }

/* (C) PERIOD SELECTOR */
#cal-date { display: flex; }
#cal-mth, #cal-yr {
  box-sizing: border-box;
  padding: 10px 20px;
  font-size: 1.2em;
  border: 0;
}

/* (D) CALENDAR */
#calendar {
  width: 100%;
  border-collapse: collapse;
}
#calendar tr.head td {
  font-weight: bold;
  text-transform: uppercase;
  color: #000000;
  background: #CCFFFF;
  padding: 15px;
  text-align: center;
}
#calendar tr.day td {
  border: 1px solid #ddd;
  width: 14.28%;
  padding: 15px 5px;
  vertical-align: top;
}
#calendar tr.day td:hover {
  background: #fff9e4;
  cursor: pointer;
}
#calendar tr td.blank {
  background: #f5f5f5;
}
#calendar tr td.today {
  background: #ffdede;
}
#calendar .dd {
  font-size: 1.2em;
  color: #999;
}
#calendar .evt {
  margin-top: 5px;
  font-size: 0.8em;
  font-weight: bold;
  overflow: hidden;
  color: #ff5d5d;
}

/* (E) ADD/EDIT EVENT */
#cal-event {
  padding: 15px;
  margin-top: 20px;
  background: #f5f5f5;
  border: 1px solid #ddd;
}
#cal-event h1 {
  color: #333;
  padding: 0;
  margin: 0;
}
#evt-date {
  color: #555;
  margin: 10px 0;
}
#cal-event textarea {
  display: block;
  box-sizing: border-box;
  width: 100%;
  padding: 10px;
  margin: 10px 0;
  border: 1px solid #ddd;
  min-height: 200px;
}
#cal-event input[type=button], #cal-event input[type=submit] {
  padding: 10px;
  margin: 5px;
  font-size: 1.2em;
  border: 0;
  background: #ea4c4c;
  color: #fff;
}
<!DOCTYPE html>
<html>
  <head>
    <title>Simple Javascript Calendar</title>
    <link href="calendar.css" rel="stylesheet">
    <script async src="calendar.js"></script>
  </head>
  <body>
    <div id="cal-wrap">
      <!-- (A) PERIOD SELECTOR -->
      <div id="cal-date">
        <select id="cal-mth"></select>
        <select id="cal-yr"></select>
      </div>

      <!-- (B) CALENDAR -->
      <div id="cal-container"></div>

      <!-- (C) EVENT FORM -->
      <form id="cal-event">
        <h1 id="evt-head"></h1>
        <div id="evt-date"></div>
        <textarea id="evt-details" required></textarea>
        <input id="evt-close" type="button" value="Close"/>
        <input id="evt-del" type="button" value="Delete"/>
        <input id="evt-save" type="submit" value="Save"/>
      </form>
    </div>
  </body>
</html>

推荐答案

你现在所拥有的是一个很好的开始.

您只需在本地存储存储中存储更多信息,如

[{
  "text_area" : "Text area for Nov 6",
  "tasks":[
    {
      "label" : "Label 1",
      "value" : "Value 1"
    },
    {
      "label" : "Label 2",
      "value" : "Value 2"
    },
    {
      "label" : "Label 3",
      "value" : "Value 3"
    }
  ]
},{
  "text_area" : "Another text area for Nov 6",
  "tasks":[
    {
      "label" : "Label 1",
      "value" : "Value 1"
    },
    {
      "label" : "Label 2",
      "value" : "Value 2"
    },
    {
      "label" : "Label 3",
      "value" : "Value 3"
    }
  ]
}]

并将您的表单更改为具有容器

<form id="cal-event">
        <h1 id="evt-head"></h1>
        <div id="evt-date"></div>
        <div id="form-container"></div>
        <input id="evt-close" type="button" value="Close"/>
        <input id="evt-del" type="button" value="Delete"/>
        <input id="evt-save" type="submit" value="Save"/>
      </form>

然后在你的show方法中,你会做一些类似的事情

show: (el) => {
    //...
    let HTML  = ''
    cal.data.forEach(taskGroup => {
        // define a new text area
        HTML += `<textarea>${taskGroup.text_area}</textarea>`
        taskGroup.tasks.forEach(task => {
            HTML += `<input type="checkbox" value="${task.value}"><label>${task.label}</label>`
        })
        //...
    })
    document.getElementById('form-container').innerHTML = HTML;
    //...
}

要点是,通过描述更多的JSON,您将允许您的数据决定页面的外观和感觉.

就日历而言,为了最大限度地增加空间,并在可以添加的内容数量上有更大的灵活性,您可能希望不再使用<tables>,而是使用类似于CSS GRID https://learncssgrid.com/的内容

请把这个代码当作伪代码,给你一些 idea .祝你编程愉快.

Javascript相关问答推荐

在具有焦点和上下文的d3多线图表中,如何将上下文的刷新限制在特定日期?

如何在NightWatch.js测试中允许浏览器权限?

如何为GrapesJS模板编辑器创建自定义撤销/重复按钮?

如何才能拥有在jQuery终端中执行命令的链接?

如何将连续的十六进制字符串拆分为以空间分隔的十六进制块,每个十六进制块包含32个二元组?

传递一个大对象以在Express布局中呈现

Javascript,部分重排序数组

类型自定义lazy Promise. all

我不知道为什么setwritten包装promise 不能像我预期的那样工作

用JavaScript复制C#CRC 32生成器

变量的值在Reaction组件中的Try-Catch语句之外丢失

变量在导入到Vite中的另一个js文件时成为常量.

如何在DYGRAPS中更改鼠标事件和键盘输入

Reaction-SWR-无更新组件

从逗号和破折号分隔的给定字符串中查找所有有效的星期几

MongoDB中的嵌套搜索

FireBase FiRestore安全规则-嵌套对象的MapDiff

在将元素追加到DOM之前,createElement()是否会触发回流?混淆abt DocumentFragment行为

用内嵌的含selenium的Java脚本抓取网站

如何在Java脚本中添加一个可以在另一个面板中垂直调整大小的面板?