Javascript 如果元素相互接触,是否将其宽度一分为二?

Javascript 如果元素相互接触,是否将其宽度一分为二?,javascript,jquery,css,Javascript,Jquery,Css,我正在开发一个Javascript/jQuery日历,其中包括一个月视图和一个日视图。单击日期将更改日期,这将更新日期视图中的日期变量 白天的景色从午夜到晚上11:00分为半小时的部分。点击任何半小时的(日视图是一个表格)将在点击时间和未来一小时之间创建一个事件,并在日历顶部附加一个div,跨越时间范围并定位在正确的起点(每个像素为一分钟…) 然而,有一个问题。如果您在某个时间跨度之间创建一个“事件”,而该时间跨度中已有一个“事件”,则它们会重叠。显然,这是默认行为,但我希望发生的是,如果在事件

我正在开发一个Javascript/jQuery日历,其中包括一个月视图和一个日视图。单击日期将更改日期,这将更新日期视图中的日期变量

白天的景色从午夜到晚上11:00分为半小时的部分。点击任何半小时的
(日视图是一个表格)将在点击时间和未来一小时之间创建一个事件,并在日历顶部附加一个
div
,跨越时间范围并定位在正确的起点(每个像素为一分钟…)

然而,有一个问题。如果您在某个时间跨度之间创建一个“事件”,而该时间跨度中已有一个“事件”,则它们会重叠。显然,这是默认行为,但我希望发生的是,如果在事件已占用的日期范围内创建事件,它们将并排排列,以避免重叠

这类似于iCal mac应用程序中的行为:

现在我的第一个想法是使用冲突检测,但是所有用于此的jQuery插件都是臃肿的,或者要求元素是可拖动的

然后我想CSS中可能有一种方法可以做到这一点,如果两个元素重叠,它们会均匀地分割宽度

然后我认为这是荒谬的牵强,所以我想知道如何才能尽可能容易地实现这一点

我将在JSFIDLE中发布完整的代码,但最重要的函数是
insertEvent
,如下所示:

    function insertEvent(start, end){

        var end_minutes = new Date(end).getMinutes();
        var end_border = new Date(new Date(end).setMinutes(end_minutes + 2));

        //$(".day_date").html(start + "<br />" + end);
        var diff = Math.abs(end_border - new Date(start));
        var minutes = Math.floor((diff/1000)/60);

        var start_element = $("td").find("[data-date='" + start + "']");
        var offset = start_element.offset().top - $(".second").offset().top;

        var this_element = $("<div class='event' style='height:" + minutes + "px;margin-top:" + offset + "px;'></div>");

        $(".right").prepend(this_element);

    }
函数插入事件(开始、结束){
var end_minutes=新日期(end).getMinutes();
var end_border=新日期(新日期(end).setMinutes(end_分钟+2));
//$(“.day_date”).html(开始+”
“+end); var diff=Math.abs(结束-新日期(开始)); var分钟=数学楼层((差异/1000)/60); var start_元素=$(“td”).find(“[数据日期='”+start+“]”); var offset=start_element.offset().top-$(“.second”).offset().top; var this_元素=$(“”); $(“.right”).prepend(此元素); }
这采用javascript
new Date()
格式的两个参数,一个用于开始日期,一个用于结束日期


麻烦:

我发现您的方法存在的一个问题是,数据的存储并没有一个结构。我以前用Javascript构建过一个日历,这并不容易。首先,确保对日历事件有某种抽象。比如:

function CalendarEvent(startDateTime, endDateTime) {
  this.startDateTime = startDateTime;
  this.endDateTime = endDateTime;
}

CalendarEvent.prototype.start = function() {
  return this.startDateTime.getTime();
};

CalendarEvent.prototype.end = function() {
  return this.endDateTime.getTime();
};

CalendarEvent.new = function(startDateTime, endDateTime) {
  // This is a little factory method. It prevents calendar events 
  // from having end times that fall before the start time.
  // USE THIS TO INSTANTIATE A NEW CALENDAR EVENT
  if(endDateTime.getTime() < startDateTime.getTime()) {
    throw new Error("End time falls before start time");
  }
  return new CalendarEvent(startDateTime, endDateTime);
};

CalendarEvent.compare = function(eventOne, eventTwo) {
  // this is a class method to compare two events
  // If used with sort it will sort by startDateTime
  return eventOne.start() - eventTwo.start();
};

// ... add any other methods you need
这个特定算法的基本思想是,如果列表上的下一个事件存在,并且该事件与currentEvent相交,那么我们需要拆分currentEvent的宽度。它继续递归,直到不再找到交叉点,然后返回递归调用链。我跳过了实际的DOM操作逻辑,因为真正困难的部分是确定需要拆分多少实际列才能使这些事件适合。希望这一切都有点道理

编辑:

更清楚地说,为了将其添加到现有代码中,我将用类似的东西替换
insertEvent
函数。我没有为你写所有的逻辑,所以你必须自己写一些。但这只是乐趣的一半:-)


我看到您的方法存在的一个问题是,数据存储并没有一个结构。我以前用Javascript构建过一个日历,这并不容易。首先,确保对日历事件有某种抽象。比如:

function CalendarEvent(startDateTime, endDateTime) {
  this.startDateTime = startDateTime;
  this.endDateTime = endDateTime;
}

CalendarEvent.prototype.start = function() {
  return this.startDateTime.getTime();
};

CalendarEvent.prototype.end = function() {
  return this.endDateTime.getTime();
};

CalendarEvent.new = function(startDateTime, endDateTime) {
  // This is a little factory method. It prevents calendar events 
  // from having end times that fall before the start time.
  // USE THIS TO INSTANTIATE A NEW CALENDAR EVENT
  if(endDateTime.getTime() < startDateTime.getTime()) {
    throw new Error("End time falls before start time");
  }
  return new CalendarEvent(startDateTime, endDateTime);
};

CalendarEvent.compare = function(eventOne, eventTwo) {
  // this is a class method to compare two events
  // If used with sort it will sort by startDateTime
  return eventOne.start() - eventTwo.start();
};

// ... add any other methods you need
这个特定算法的基本思想是,如果列表上的下一个事件存在,并且该事件与currentEvent相交,那么我们需要拆分currentEvent的宽度。它继续递归,直到不再找到交叉点,然后返回递归调用链。我跳过了实际的DOM操作逻辑,因为真正困难的部分是确定需要拆分多少实际列才能使这些事件适合。希望这一切都有点道理

编辑:

更清楚地说,为了将其添加到现有代码中,我将用类似的东西替换
insertEvent
函数。我没有为你写所有的逻辑,所以你必须自己写一些。但这只是乐趣的一半:-)


我很困惑。。你如何看待你试图解决的问题?比如你如何在一个时间里添加事件?我不太确定你在问什么<代码>如如何将事件添加到时间?事件功能尚未完成,如事件名称、持续时间,但我正在尝试设置groundwork@charlie,我想知道如何构造数据并将其保存在内存中。如果将事件附加到特定时间点。这是如何构造的?数据将被发送到数据库并在加载时检索。你是什么意思?这是如何组织的?所有代码都在上面。。。当你创建一个活动时,它会设置一段时间,并在日程安排中插入一个视觉表示,这就是我在这里遇到的问题。我很困惑。。你如何看待你试图解决的问题?比如你如何在一个时间里添加事件?我不太确定你在问什么<代码>如如何将事件添加到时间?事件功能尚未完成,如事件名称、持续时间,但我正在尝试设置groundwork@charlie,我想知道如何构造数据并将其保存在内存中。如果将事件附加到特定时间点。这是如何构造的?数据将被发送到数据库并在加载时检索。你是什么意思?这是如何组织的?所有代码都在上面。。。创建事件时,它会在一定时间范围内对其进行设置,并在其中插入视觉表示
function renderCalendarEvents(calendarEvents) {
  // Sort the calendar events (assuming calendarEvents is an array)
  var sortedEvents = calendarEvents.sort(CalendarEvent.compare);
  var index = 0;
  // renderEvents is an anonymous function that will be called every time 
  // you need to render an event
  // it returns it's columnDivisor.
  var renderEvent = function(position) {
    var currentEvent = sortedEvents[index];
    var nextEvent = sortedEvents[index + 1];
    // The default column divisor is determined by
    // the current x-position + 1
    var columnDivisor = position + 1;
    // Increment before any recursion
    index += 1;
    // Check if nextEvent even exists
    if(nextEvent) {
      // If the nextEvent intersects with the current event
      // then recurse
      if(currentEvent.intersects(nextEvent)) {
        // We need to tell the next event that it starts at the
        // column position that is immediately +1 to the current event
        columnDivisor = renderEvent(position + 1);
      }
    }
    // placeEvent() is some function you can call to actually place 
    // the calendar event element on the page
    // The position is the x-position of the current event
    // The columnDivisor is a count of the amount of events sharing this column
    placeEvent(currentEvent, position, columnDivisor);
    return columnDivisor;
  };
  while(true) {
    // render events until we're done
    renderEvent(0);
    if(index >= sortedEvents.length) {
      break;
    }
  }
}
function insertEvent(start, end) {
  var newEvent = Calendar.new(start, end);
  // you'll have to store the array somewhere.
  // i'm just assuming some kind of global right now
  eventsArray.push(newEvent);
  // You'll want to destroy any event elements
  destroyCurrentEventElements();
  // Now run the rendering function
  renderCalendarEvents(eventsArray);
}