0

我整天都在努力寻找一个好的解决方案,在我正在开发的网站上以列表格式显示谷歌日历。我遇到了这段代码,除了一些格式问题外,它运行良好。我对 jQuery 不是很了解,所以我在格式上苦苦挣扎。我已经从 CSS 方面做了尽可能多的工作,但显然其中一些是在脚本方面。也许如果有人可以请帮助我删除脚本中的格式并严格使用 css 会很棒 =) 或另一个更好的解决方案 =P

非常感谢!

我追求的格式是不同 div 中的 3 个部分: date('nov 12, 09:00') event('Student Night') location('Nicci Beach')

JS:

    // Generated by CoffeeScript 1.4.0
(function() {
  var $, gCalFlow, log, methods, pad_zero, _ref;

  $ = jQuery;

  if ((typeof window !== "undefined" && window !== null) && (window._gCalFlow_debug != null) && (typeof console !== "undefined" && console !== null)) {
    log = console;
    if ((_ref = log.debug) == null) {
      log.debug = log.log;
    }
  } else {
    log = {};
    log.error = log.warn = log.log = log.info = log.debug = function() {};
  }

  pad_zero = function(num, size) {
    var i, ret, _i, _ref1;
    if (size == null) {
      size = 2;
    }
    if (10 * (size - 1) <= num) {
      return num;
    }
    ret = "";
    for (i = _i = 1, _ref1 = size - ("" + num).length; 1 <= _ref1 ? _i <= _ref1 : _i >= _ref1; i = 1 <= _ref1 ? ++_i : --_i) {
      ret = ret.concat("0");
    }
    return ret.concat(num);
  };

  gCalFlow = (function() {

    gCalFlow.prototype.target = null;

    gCalFlow.prototype.template = $("<div class=\"gCalFlow\">\n  <div class=\"gcf-header-block\">\n    <div class=\"gcf-title-block\">\n      <span class=\"gcf-title\"></span>\n    </div>\n  </div>\n  <div class=\"gcf-item-container-block\">\n    <div class=\"gcf-item-block\">\n      <div class=\"gcf-item-header-block\">\n        <div class=\"gcf-item-date-block\">\n          [<span class=\"gcf-item-daterange\"></span>]\n        </div>\n        <div class=\"gcf-item-title-block\">\n          <strong class=\"gcf-item-title\"></strong>\n        </div>\n      </div>\n      <div class=\"gcf-item-body-block\">\n        <div class=\"gcf-item-description\">\n        </div>\n        <div class=\"gcf-item-location\">\n        </div>\n      </div>\n    </div>\n  </div>\n  <div class=\"gcf-last-update-block\">\n    LastUpdate: <span class=\"gcf-last-update\"></span>\n  </div>\n</div>");

    gCalFlow.prototype.opts = {
      maxitem: 5,
      calid: null,
      mode: 'upcoming',
      feed_url: null,
      auto_scroll: false,
      scroll_interval: 10 * 1000,
      link_title: true,
      link_item_title: true,
      link_item_description: true,
      link_target: '_blank',
      item_description_in_html: false,
      callback: null,
      no_items_html: '',
      globalize_culture: (typeof navigator !== "undefined" && navigator !== null) && (navigator.browserLanguage || navigator.language || navigator.userLanguage),
      globalize_fmt_datetime: 'f',
      globalize_fmt_date: 'D',
      globalize_fmt_time: 't',
      globalize_fmt_monthday: 'M',
      date_formatter: function(d, allday_p) {
        var fmtstr;
        if ((typeof Globalize !== "undefined" && Globalize !== null) && (Globalize.format != null)) {
          if (allday_p) {
            fmtstr = this.globalize_fmt_date;
          } else {
            fmtstr = this.globalize_fmt_datetime;
          }
          return Globalize.format(d, fmtstr);
        } else {
          if (allday_p) {
            return "" + (d.getFullYear()) + "-" + (pad_zero(d.getMonth() + 1)) + "-" + (pad_zero(d.getDate()));
          } else {
            return "" + (d.getFullYear()) + "-" + (pad_zero(d.getMonth() + 1)) + "-" + (pad_zero(d.getDate())) + " " + (pad_zero(d.getHours())) + ":" + (pad_zero(d.getMinutes()));
          }
        }
      },
      daterange_formatter: function(sd, ed, allday_p) {
        var endstr, ret;
        ret = this.date_formatter(sd, allday_p);
        if (allday_p) {
          ed = new Date(ed.getTime() - 86400 * 1000);
        }
        endstr = '';
        if (sd.getDate() !== ed.getDate() || sd.getMonth() !== ed.getMonth()) {
          if ((typeof Globalize !== "undefined" && Globalize !== null) && (Globalize.format != null)) {
            endstr += Globalize.format(ed, this.globalize_fmt_monthday);
          } else {
            endstr += "" + (pad_zero(ed.getMonth() + 1)) + "-" + (pad_zero(ed.getDate()));
          }
        }
        if (!allday_p && (sd.getHours() !== ed.getHours() || sd.getMinutes() !== ed.getMinutes())) {
          if ((typeof Globalize !== "undefined" && Globalize !== null) && (Globalize.format != null)) {
            endstr += Globalize.format(ed, this.globalize_fmt_time);
          } else {
            endstr += " " + (pad_zero(ed.getHours())) + ":" + (pad_zero(ed.getMinutes()));
          }
        }
        if (endstr) {
          ret += " - " + endstr;
        }
        return ret;
      }
    };

    function gCalFlow(target, opts) {
      this.target = target;
      target.addClass('gCalFlow');
      if (target.children().size() > 0) {
        log.debug("Target node has children, use target element as template.");
        this.template = target;
      }
      this.update_opts(opts);
    }

    gCalFlow.prototype.update_opts = function(new_opts) {
      log.debug("update_opts was called");
      log.debug("old options:", this.opts);
      this.opts = $.extend({}, this.opts, new_opts);
      return log.debug("new options:", this.opts);
    };

    gCalFlow.prototype.gcal_url = function() {
      if (!this.opts.calid && !this.opts.feed_url) {
        log.error("Option calid and feed_url are missing. Abort URL generation");
        this.target.text("Error: You need to set 'calid' or 'feed_url' option.");
        throw "gCalFlow: calid and feed_url missing";
      }
      if (this.opts.feed_url) {
        return this.opts.feed_url;
      } else if (this.opts.mode === 'updates') {
        return "https://www.google.com/calendar/feeds/" + this.opts.calid + "/public/full?alt=json-in-script&max-results=" + this.opts.maxitem + "&orderby=lastmodified&sortorder=descending";
      } else {
        return "https://www.google.com/calendar/feeds/" + this.opts.calid + "/public/full?alt=json-in-script&max-results=" + this.opts.maxitem + "&orderby=starttime&futureevents=true&sortorder=ascending&singleevents=true";
      }
    };

    gCalFlow.prototype.fetch = function() {
      var success_handler,
        _this = this;
      log.debug("Starting ajax call for " + (this.gcal_url()));
      success_handler = function(data) {
        log.debug("Ajax call success. Response data:", data);
        return _this.render_data(data, _this);
      };
      return $.ajax({
        success: success_handler,
        dataType: "jsonp",
        url: this.gcal_url()
      });
    };

    gCalFlow.prototype.parse_date = function(dstr) {
      var day, hour, m, min, mon, offset, ret, sec, year;
      if (m = dstr.match(/^(\d{4})-(\d{2})-(\d{2})$/)) {
        return new Date(parseInt(m[1], 10), parseInt(m[2], 10) - 1, parseInt(m[3], 10), 0, 0, 0);
      }
      offset = (new Date()).getTimezoneOffset() * 60 * 1000;
      year = mon = day = null;
      hour = min = sec = 0;
      if (m = dstr.match(/^(\d{4})-(\d{2})-(\d{2})[T ](\d{2}):(\d{2}):(\d{2}(?:\.\d+)?)(Z|([+-])(\d{2}):(\d{2}))$/)) {
        year = parseInt(m[1], 10);
        mon = parseInt(m[2], 10);
        day = parseInt(m[3], 10);
        hour = parseInt(m[4], 10);
        min = parseInt(m[5], 10);
        sec = parseInt(m[6], 10);
        if (m[7] !== "Z") {
          offset += (m[8] === "+" ? 1 : -1) * (parseInt(m[9], 10) * 60 + parseInt(m[10], 10)) * 1000 * 60;
        }
      } else {
        log.warn("Time parse error! Unknown time pattern: " + dstr);
        return new Date(1970, 1, 1, 0, 0, 0);
      }
      log.debug("time parse (gap to local): " + offset);
      ret = new Date(new Date(year, mon - 1, day, hour, min, sec).getTime() - offset);
      log.debug("time parse: " + dstr + " -> ", ret);
      return ret;
    };

    gCalFlow.prototype.render_data = function(data) {
      var ci, desc_body_method, ed, ent, et, etf, feed, ic, it, items, link, sd, st, stf, t, titlelink, _i, _len, _ref1, _ref2;
      log.debug("start rendering for data:", data);
      feed = data.feed;
      t = this.template.clone();
      titlelink = (_ref1 = this.opts.titlelink) != null ? _ref1 : "http://www.google.com/calendar/embed?src=" + this.opts.calid;
      if (this.opts.link_title) {
        t.find('.gcf-title').html($("<a />").attr({
          target: this.opts.link_target,
          href: titlelink
        }).text(feed.title.$t));
      } else {
        t.find('.gcf-title').text(feed.title.$t);
      }
      t.find('.gcf-link').attr({
        target: this.opts.link_target,
        href: titlelink
      });
      t.find('.gcf-last-update').html(this.opts.date_formatter(this.parse_date(feed.updated.$t)));
      it = t.find('.gcf-item-block');
      it.detach();
      it = $(it[0]);
      log.debug("item block template:", it);
      items = $();
      log.debug("render entries:", feed.entry);
      if (this.opts.item_description_as_html) {
        desc_body_method = 'html';
      } else {
        desc_body_method = 'text';
      }
      if ((feed.entry != null) && feed.entry.length > 0) {
        _ref2 = feed.entry.slice(0, +this.opts.maxitem + 1 || 9e9);
        for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
          ent = _ref2[_i];
          log.debug("formatting entry:", ent);
          ci = it.clone();
          if (ent.gd$when) {
            st = ent.gd$when[0].startTime;
            sd = this.parse_date(st);
            stf = this.opts.date_formatter(sd, st.indexOf(':') < 0);
            ci.find('.gcf-item-date').html(stf);
            ci.find('.gcf-item-start-date').html(stf);
            et = ent.gd$when[0].endTime;
            ed = this.parse_date(et);
            etf = this.opts.date_formatter(ed, et.indexOf(':') < 0);
            ci.find('.gcf-item-end-date').html(etf);
            ci.find('.gcf-item-daterange').html(this.opts.daterange_formatter(sd, ed, st.indexOf(':') < 0));
          }
          ci.find('.gcf-item-update-date').html(this.opts.date_formatter(this.parse_date(ent.updated.$t), false));
          link = $('<a />').attr({
            target: this.opts.link_target,
            href: ent.link[0].href
          });
          if (this.opts.link_item_title) {
            ci.find('.gcf-item-title').html(link.clone().text(ent.title.$t));
          } else {
            ci.find('.gcf-item-title').text(ent.title.$t);
          }
          if (this.opts.link_item_description) {
            ci.find('.gcf-item-description').html(link.clone()[desc_body_method](ent.content.$t));
          } else {
            ci.find('.gcf-item-description')[desc_body_method](ent.content.$t);
          }
          ci.find('.gcf-item-location').text(ent.gd$where[0].valueString);
          ci.find('.gcf-item-link').attr({
            href: ent.link[0].href
          });
          log.debug("formatted item entry:", ci[0]);
          items.push(ci[0]);
        }
      } else {
        items = $('<div class=".gcf-no-items"></div>').html(this.opts.no_items_html);
      }
      log.debug("formatted item entry array:", items);
      ic = t.find('.gcf-item-container-block');
      log.debug("item container element:", ic);
      ic.html(items);
      this.target.html(t.html());
      this.bind_scroll();
      if (this.opts.callback) {
        return this.opts.callback.apply(this.target);
      }
    };

    gCalFlow.prototype.bind_scroll = function() {
      var scroll_children, scroll_container, scroll_timer, scroller, state;
      scroll_container = this.target.find('.gcf-item-container-block');
      scroll_children = scroll_container.find(".gcf-item-block");
      log.debug("scroll container:", scroll_container);
      if (!this.opts.auto_scroll || scroll_container.size() < 1 || scroll_children.size() < 2) {
        return;
      }
      state = {
        idx: 0
      };
      scroller = function() {
        var scroll_to;
        log.debug("current scroll position:", scroll_container.scrollTop());
        log.debug("scroll capacity:", scroll_container[0].scrollHeight - scroll_container[0].clientHeight);
        if (typeof scroll_children[state.idx] === 'undefined' || scroll_container.scrollTop() >= scroll_container[0].scrollHeight - scroll_container[0].clientHeight) {
          log.debug("scroll to top");
          state.idx = 0;
          return scroll_container.animate({
            scrollTop: scroll_children[0].offsetTop
          });
        } else {
          scroll_to = scroll_children[state.idx].offsetTop;
          log.debug("scroll to " + scroll_to + "px");
          scroll_container.animate({
            scrollTop: scroll_to
          });
          return state.idx += 1;
        }
      };
      return scroll_timer = setInterval(scroller, this.opts.scroll_interval);
    };

    return gCalFlow;

  })();

  methods = {
    init: function(opts) {
      var data;
      if (opts == null) {
        opts = {};
      }
      data = this.data('gCalFlow');
      if (!data) {
        return this.data('gCalFlow', {
          target: this,
          obj: new gCalFlow(this, opts)
        });
      }
    },
    destroy: function() {
      var data;
      data = this.data('gCalFlow');
      data.obj.target = null;
      $(window).unbind('.gCalFlow');
      data.gCalFlow.remove();
      return this.removeData('gCalFlow');
    },
    render: function() {
      if ((typeof Globalize !== "undefined" && Globalize !== null) && (Globalize.culture != null)) {
        Globalize.culture(this.data('gCalFlow').obj.opts.globalize_culture);
      }
      return this.data('gCalFlow').obj.fetch();
    }
  };

  $.fn.gCalFlow = function(method) {
    var orig_args;
    orig_args = arguments;
    if (typeof method === 'object' || !method) {
      return this.each(function() {
        methods.init.apply($(this), orig_args);
        return methods.render.apply($(this), orig_args);
      });
    } else if (methods[method]) {
      return this.each(function() {
        return methods[method].apply($(this), Array.prototype.slice.call(orig_args, 1));
      });
    } else if (method === 'version') {
      return "1.2.5";
    } else {
      return $.error("Method " + method + " does not exist on jQuery.gCalFlow");
    }
  };

}).call(this);

HTML:

<div id="gcf-custom-template">
                      <div class="gcf-item-container-block">
                        <div class="gcf-item-block">
                          <div class="gcf-item-header-block">
                                <div class="gcf-item-title-block">
                                  <div style="float: left; width 250px;"><a class="gcf-item-link"><span class="gcf-item-daterange">2012-02-01 09:00</span>:</a></div>
                                  <div style="float: left; width 250px;"><a class="gcf-item-location">1-877-346-9707 w 55586#</a></div>
                                  <div style="float: left; width 250px;"><strong><a class="gcf-item-title">Item Title of Your event</a></strong></div>
                                </div>
                          </div>
                        </div>
                      </div>
                     </div>

脚本调用:

<script type="text/javascript">
      var $ = jQuery;
      $(function() {
        $('#gcf-custom-template').gCalFlow({
          calid: '4t0m1c.w07f@gmail.com',
          maxitem: 50,
          mode: 'updates',
          date_formatter: function(d, allday_p) { return (d.getMonth()+1) + "/" + d.getDate() + "/" + d.getYear().toString().substr(-2) }
        });
      });
    </script>
4

1 回答 1

0

这是我对类似问题的解决方案,使用moment.js进行日期格式化,使用markupjs进行模板化,使用 jQuery 让生活更轻松。

// a markup.js pipe which calls on moment.js for formatting
Mark.pipes.moment = function (date, format) {
    return moment(new Date(date)).format(format);
};

// a markup.js pipe that tests if two dates are in the same month (difference between "1st-2nd december" and "30 november - 2 december")
Mark.pipes.diffmonth = function (date1, date2) {
  moment1 = moment(new Date(date1));
  moment2 = moment(new Date(date2));
  var ret= moment1.month()!=moment2.month();
  return ret;
};

// a markup.js pipe to filter an array
Mark.pipes.sift = function (arr, prop, val) {
  return $.grep(arr,function(item) {
    return item[prop] == val;
  });
};

$(document).ready(loadCalendarData);

// this is a google calendar public full json feed (to have complete date and location information) 
calendarURL = "http://www.google.com/calendar/feeds/6vv7tct80gv5tblahm5sg0vsos@group.calendar.google.com/public/full?alt=json-in-script&orderby=starttime&singleevents=true&sortorder=ascending&futureevents=true&callback=?";

function loadCalendarData() {
  $.getJSON( calendarURL, applyTemplate);
}

function applyTemplate(cal_data) {

  // format dates in french
  moment.lang("fr");

  // take cal_data, a google calendar json full feed. and extract VCALENDAR fields. Also extract a type field that distinguishes single day events from multiple day events.
  var events = $.map(cal_data["feed"]["entry"], function (event) {
    var url= $.grep(event["link"], function(link) {
      return link["rel"]=="related";
    });
    return {
      "summary": event["title"]["$t"],
      "dtstart": event["gd$when"][0]["startTime"],
      "dtend": event["gd$when"][0]["endTime"],
      "url": url[0]?url[0]["href"]:"",
      "location": event["gd$where"][0]["valueString"],
      "type": (moment.duration(new Date(event["gd$when"][0]["endTime"])-new Date(event["gd$when"][0]["startTime"])).as("hours")<18)?"single":"multi"
    };

  });

  // summary with url link if exists
  Mark.includes.linked_summary = "{{if url}}<a href='{{url}}'>{{/if}}{{summary}}{{if url}}</a>{{/if}}";
  // location in brackets if exists
  Mark.includes.optional_location = "{{if location}}&nbsp;({{location}}){{/if}}"

  // separate list of evenings and multiple day/weeked events
  var template = 
    "Les soir&eacute;es &agrave; venir :<ul>{{events|sift>type>single}}"+ 
    "<li>{{dtstart|moment>dddd|capcase}} {{dtstart|moment>D/M}}: {{linked_summary}}{{optional_location}}</li>"+
    "{{/events}}</ul>"+
    "<br>"+
    "Les stages et weekends &agrave; venir (2013/2014):<ul>{{events|sift>type>multi}}"+
    "<li>{{dtstart|moment>D}}{{if dtstart|diffmonth>`dtend`}}{{dtstart|moment>/M}}{{/if}}-{{dtend|moment>D/M}}: {{linked_summary}}{{optional_location}}</li>"+
    "{{/events}}</ul>";

  $("#web").html(Mark.up(template, {"events":events}));
}
于 2013-11-05T12:15:40.273 回答