草庐IT

javascript - 在自定义日历中自动突出显示 "rest of day"

coder 2025-01-14 原文

我正在使用 vanilla JS 创建一个事件调度程序。我目前正在研究通过将鼠标“拖动”到所需时间来突出显示时间跨度的能力。我已经让它工作得很好,但我希望如果用户从一天(例如星期一)开始拖动到下一天(例如星期二),则当天剩余的时间会自动突出显示。

换句话说,如果您从星期一凌晨 03 点开始突出显示并拖到星期二凌晨 5 点,则突出显示区域应自动为星期一 03-07 和星期二 00-05。

我几乎可以正常工作了,但是所有这些坐标和计算让我头晕目眩。我们非常欢迎任何帮助或指导。


这是我遇到问题的片段:

if((j >= (startCol-1) && j <= (col-1) && i >= (startRow-1) && i < (row-1))) {
  rows[i].children[j].classList.add('selected');
} else if((j > (startCol-1)) && (j <= (col-1)) && (i < (startRow-1))) {
  rows[i].children[j].classList.add('selected');
} else if((j < (col-1) && (j >= (startCol-1)) && (i >= (row-1)))) {
  rows[i].children[j].classList.add('selected');
} else {
  rows[i].children[j].classList.remove('selected');
}

这是一个完整的片段

const table = document.querySelector('.table');
const rows = document.querySelectorAll('.row');
const sqSize = 28;
let selValue = 'p1';
let didMouseMove = false;
let startRow;
let startCol;

const cb = (e) => {
	didMouseMove = true;
	const x = e.clientX - table.offsetLeft;
	const y = e.clientY - table.offsetTop;
  const row = Math.round(y / sqSize);
  const col = Math.round(x / sqSize);

  for(let i=0; i < rows.length; i++) {
  	for(let j=0; j < rows[i].children.length; j++) {
    	if((j >= (startCol-1) && j <= (col-1) && i >= (startRow-1) && i < (row-1))) {
    		rows[i].children[j].classList.add('selected');
      } else if((j > (startCol-1)) && (j <= (col-1)) && (i < (startRow-1))) {
      	rows[i].children[j].classList.add('selected');
      } else if((j < (col-1) && (j >= (startCol-1)) && (i >= (row-1)))) {
      	rows[i].children[j].classList.add('selected');
      } else {
      	rows[i].children[j].classList.remove('selected');
      }
    }
  }
}

table.addEventListener('mousedown', (e) => {
  startRow = Math.round((e.clientY - table.offsetTop) / sqSize);
	startCol = Math.round((e.clientX - table.offsetLeft) / sqSize);
  table.addEventListener('mousemove', cb);
});
table.addEventListener('mouseup', (e) => {
	const x = table.querySelectorAll('.selected');
  for (let i = 0; i < x.length; i++) {
  	x[i].className = selValue;
  }
	if(!didMouseMove && !e.target.classList.contains('row')) {
  	e.target.classList.toggle(selValue);
  }
	didMouseMove = false;
  table.removeEventListener('mousemove', cb);
});
document.getElementById('sel').addEventListener('change', (e) => {
	selValue = e.target.value;
});
body {
  margin: 0;
  padding: 0;
}

.head {
  font-size: 0;
  margin-left: 32px;
}

.head > div {
  font-size: 12px;
  display: inline-block;
  width: 25px;
  margin: 0 2px;
  text-align: center;
}

.pre {
  display: inline-block;
  font-size: 0;
  vertical-align: top;
  width: 32px;
  margin-top: -8px;
}

.pre > div {
  height: 25px;
  margin: 2px 0;
  font-size: 12px;
  display: inline-block;
}

.table {
  display: inline-block;
}

.wrapper {
  display: inline-block;
  position: relative;
}

.row {
  font-size: 0;
}

.row > div {
  display: inline-block;
  border: 1px solid black;
  margin: 1px;
  width: 25px;
  height: 25px;
}

.p1 {
  background: green;
}

.p2 {
  background: blue;
}

.p3 {
  background: orange;
}

.selected {
  background: grey;
}
<div>
  <select id="sel">
     <option value="p1">Profile 1</option>
     <option value="p2">Profile 2</option>
     <option value="p3">Profile 3</option>
   </select>
 </div>
 
 <div class='wrapper'>
   <div class='head'>
     <div>Mon</div>
     <div>Tue</div>
     <div>Wed</div>
     <div>Thu</div>
     <div>Fri</div>
     <div>Sat</div>
     <div>Sun</div>
   </div>
   <div>
     <div class='pre'>
       <div>00:00</div>
       <div>00:30</div>
       <div>01:00</div>
       <div>01:30</div>
       <div>02:00</div>
       <div>02:30</div>
       <div>03:00</div>
       <div>03:30</div>
       <div>04:00</div>
       <div>04:30</div>
       <div>05:00</div>
       <div>05:30</div>
       <div>06:00</div>
       <div>06:30</div>
       <div>07:00</div>
     </div>
     <div class='table'>
       <div class='row'>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
       </div>
       <div class='row'>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
       </div>
       <div class='row'>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
       </div>
       <div class='row'>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
       </div>
       <div class='row'>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
       </div>
       <div class='row'>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
       </div>
       <div class='row'>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
       </div>
       <div class='row'>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
       </div>
       <div class='row'>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
       </div>
       <div class='row'>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
       </div>
       <div class='row'>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
       </div>
       <div class='row'>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
       </div>
       <div class='row'>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
       </div>
       <div class='row'>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
         <div></div>
       </div>
     </div>
   </div>
 </div>

和 jsfiddle 分支:http://jsfiddle.net/a2v9rd50/1/

最佳答案

这是我写的,需要调整和重构,但选择“有效”。

我动态生成了一个丑陋的 一个时尚的日历。每个单元格都有一个像这样构建的 ID:day_halfhourday 是 x 坐标,halfhour 是 y 坐标。星期一 00:00 的单元格的 ID 0_0。星期日 23:30 有 6_47

每个单元格上有 2 个事件监听器。

一个用于选择开始(mousedown),设置起始坐标(天+小时)startPoint并升起标志selecting

另一个用于选择(mouseover)。它仅在标志 selecting 为真时执行。它设置结束坐标(天 + 小时)coor 与当前单元格 ID (x_y)

文档 (mouseup) 上有第三个事件,它在控制台中显示开始和结束坐标。

您可以使用最终事件来设计选定日期和管理数据。

function changeColor(x, y, state)
{
    let cell = document.getElementById(x + '_' + y);
    if (cell)
      cell.className = state;
}

let tbl = document.createElement('table');
let container = document.getElementById('myTable');
let startPoint = null;
let endPoint = null;
let selecting = false;
for (let i = 0; i < 48; ++i)
{
    let tr = document.createElement('tr');
    for (let j = 0; j < 7; ++j)
    {
        let td = document.createElement('td');
        td.setAttribute('id', j + "_" + i);
        td.innerHTML = "A";
        td.addEventListener('mousedown', (e) =>
        {
            let coortemp = e.srcElement.id.split('_');
            startPoint = [coortemp[0], coortemp[1]];
            selecting = true;
            changeColor(coortemp[0], coortemp[1], "selecting");
        });
        td.addEventListener('mouseover', (e) =>
        {
            if (selecting)
            {
                endPoint = e.srcElement.id.split('_');
                for (let x = 0; x < 7; ++x)
                {
                    for (let y = 0; y < 48; ++y)
                    {
                        //We're out of range concerning selection. background is white
                        if (x < startPoint[0]
                            || x > endPoint[0])
                            changeColor(x, y, "deselected");
                        else
                        {
                            //In the case where we're "painting" the first day
                            //of the selection.
                            if (x == startPoint[0])
                            {
                                /*
                                 * This checks if start and end are the same day.
                                 * to avoid "painting" too much hours
                                 * Or if days are differents, so we can "paint" until midnight
                                 */
                                if (y >= startPoint[1]
                                    && ((startPoint[0] == endPoint[0]
                                            && y <= endPoint[1])
                                        || startPoint[0] != endPoint[0]))
                                {
                                    changeColor(x, y, "selecting");
                                }
                                else
                                {
                                    changeColor(x, y, "deselected");
                                }
                            }
                            //last day of selection ...
                            else if (x == endPoint[0])
                            {
                                //... before or at last hour
                                if (y <= endPoint[1])
                                {
                                    changeColor(x, y, "selecting");
                                }                                    
                                else
                                {
                                    changeColor(x, y, "deselected");
                                }
                            }
                            //There, we're definitely in range and we can blindly "paint"
                            else
                            {
                                changeColor(x, y, "selecting");
                            }
                        }
                    }
                }
            }
        });
        tr.appendChild(td);
    }
    tbl.appendChild(tr);
}
container.appendChild(tbl);
document.addEventListener('mouseup', () =>
{
    if (selecting)
    {
        if (!endPoint)
            endPoint = startPoint;
        console.log('final selection : from day ' + startPoint[0] + ' half-hour * ' + startPoint[1] + ' to day ' + endPoint[0] + ' half-hour * ' + endPoint[1]);
        selecting = false;
        let days = document.getElementsByClassName("selecting");
        
        while (days.length)
          days[0].className = "selected";
    }
});
.selecting
{
  background-color: #A9A9A9;
}

.deselected
{
  background-color: #FFFFFF;
}

.selected
{
  background-color: #00FF00;
}
<div id="myTable">
</div>

关于javascript - 在自定义日历中自动突出显示 "rest of day",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52722239/

有关javascript - 在自定义日历中自动突出显示 "rest of day"的更多相关文章

  1. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  2. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  3. ruby-on-rails - rails : "missing partial" when calling 'render' in RSpec test - 2

    我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou

  4. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  5. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  6. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  7. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  8. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

  9. ruby-on-rails - 使用 Sublime Text 3 突出显示 HTML 背景语法中的 ERB? - 2

    所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择

  10. ruby-on-rails - 迷你测试错误 : "NameError: uninitialized constant" - 2

    我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test

随机推荐