摘要:即之前實(shí)現(xiàn)了一個(gè)月視圖日歷,我們今天來(lái)實(shí)現(xiàn)一個(gè)二維周視圖的日歷。難點(diǎn)實(shí)現(xiàn)內(nèi)容部件插入我們實(shí)現(xiàn)這個(gè)二維周視圖日歷的主要目的就是要支持插入任意的內(nèi)容,上面已經(jīng)準(zhǔn)備好了插入內(nèi)容的元素,這里要做的就是將數(shù)據(jù)繪制成放置在合適的位置。
即之前實(shí)現(xiàn)了一個(gè)月視圖日歷,我們今天來(lái)實(shí)現(xiàn)一個(gè)二維周視圖的日歷。
以下進(jìn)行分析其中的關(guān)鍵部分。
結(jié)構(gòu)準(zhǔn)備不同之處在于其在日歷的基礎(chǔ)上還有一個(gè)分類(lèi)軸,用于展示不同的類(lèi)目,主要用于一周內(nèi)的日程安排、會(huì)議安排等。
二維則和之前多帶帶的有所不同,二維日歷再切換日期時(shí)不用全部重新渲染,分類(lèi)是不用變的,僅僅改變顯示的日期即可。
而且由于是二維的,插入的內(nèi)容必定是同時(shí)屬于一個(gè)分類(lèi)和一個(gè)時(shí)間段的,內(nèi)容肯定是可以跨越時(shí)間(即日期軸)的,因此不能直接將插入的內(nèi)容像開(kāi)始的日歷一樣直接放置在日歷的格子中。而要進(jìn)行多帶帶的處理。
另外,只要分類(lèi)不變,日期和分類(lèi)構(gòu)成的網(wǎng)格是不用重繪的。
考慮到以上情況,插入內(nèi)容的和網(wǎng)格是需要分開(kāi)來(lái)的,我將現(xiàn)成的日歷弄成一下3D效果示意:
即插入內(nèi)容的層是多帶帶放置在時(shí)間和分類(lèi)構(gòu)成的網(wǎng)格上方的。
基于以上分析,先構(gòu)建如下基本結(jié)構(gòu):
2017年12月04日 - 10日車(chē)輛
結(jié)構(gòu)如上,實(shí)現(xiàn)代碼就不用展示了。
繪制實(shí)現(xiàn)初始好了必要的結(jié)構(gòu),我們接著進(jìn)行日歷的繪制工作。
分類(lèi)繪制首先要處理的是分類(lèi),周視圖中,一周的天數(shù)是固定的,確定好分類(lèi)才能繪制出主體部分的網(wǎng)格。
對(duì)于分類(lèi),暫時(shí)考慮如下必要數(shù)據(jù)格式:
{ id: "cate-1", // 分類(lèi)ID name: "法拉利", // 分類(lèi)名稱(chēng) content: "蘇E00000" // 分類(lèi)的具體描述 }
實(shí)現(xiàn)如下:
{ // 設(shè)置分類(lèi)數(shù)據(jù) setCategory: function (data) { if (!(data instanceof Array)) { this.throwError("分類(lèi)數(shù)據(jù)必須是一個(gè)數(shù)組"); return; } this._categoryData = data; // 繪制分類(lèi) this._renderCatagories(); // 繪制其他需要改變的部分 this._renderChanged(); }, // 左側(cè)分類(lèi)渲染 _renderCatagories: function () { this._categoryListEl.innerHTML = ""; var i = 0, data = this._categoryData, node = document.createElement("li"), cataEl; node.className = "ep-weekcalendar-category"; // 用行作為下標(biāo)記錄當(dāng)前分類(lèi)id集合 this._categoryIndexs = []; // id為鍵記錄索引 this._categoryReocrds = {}; while (i < data.length) { this._categoryIndexs.push(data[i].id); this._categoryReocrds[data[i].id] = i; cataEl = node.cloneNode(true); this._rendercategory(data[i], cataEl); i++; } // 分類(lèi)重繪必定重繪網(wǎng)格和內(nèi)容 this._renderGrid(); this._rednerContent(); }, _rendercategory: function (cate, cateEl) { cateEl.setAttribute("data-cateid", cate.id); var titleEl = document.createElement("span"), contentEl = document.createElement("span"); titleEl.className = "title"; contentEl.className = "content"; titleEl.innerHTML = cate.name; contentEl.innerHTML = cate.content; cateEl.appendChild(titleEl); cateEl.appendChild(contentEl); this.fire("categoryRender", { categoryEl: cateEl, titleEl: titleEl, contentEl: contentEl }); this._categoryListEl.appendChild(cateEl); this.fire("agterCategoryRender", { categoryEl: cateEl, titleEl: titleEl, contentEl: contentEl }); } }
上面通過(guò)設(shè)置分類(lèi)數(shù)據(jù) setCategory 作為入口,調(diào)用繪制分類(lèi)方法,其中還調(diào)用了 _renderChanged 此方法用于重新繪制日歷的可變部分,如標(biāo)題、日期和其中的內(nèi)容,會(huì)在之后進(jìn)行介紹。
日期繪制上面已經(jīng)準(zhǔn)備好了分類(lèi)軸,還需要繪制出日期軸,對(duì)于周視圖而言,一周的實(shí)現(xiàn)就非常簡(jiǎn)單了,根據(jù)一周的開(kāi)始日期,依次渲染7天即可。 注意在繪制過(guò)程中提供日期的必要信息給相應(yīng)事件,一遍使用者能夠在事件中進(jìn)行個(gè)性化處理。
{ // 渲染日歷的星期 _renderWeeks: function () { this._weeksEl.innerHTML = ""; var i = 0, currDate = this._startDate.clone(), node = document.createElement("div"), week; node.className = "ep-weekcalendar-week"; // 單元格列作為下標(biāo)記錄日期 this._dateRecords = []; while (i++ < 7) { // 更新記錄日期 this._dateRecords.push(currDate.clone()); week = node.cloneNode(true); this._renderWeek(currDate, week); currDate.add(1, "day"); } // 切換日期 需要重繪內(nèi)容區(qū)域 this._rednerContent(); }, _renderWeek: function (date, node) { var dateText = date.format("YYYY-MM-DD"), day = date.isoWeekday(); if (day > 5) { node.className += " weekend"; } if (date.isSame(this.today, "day")) { node.className += " today"; } node.setAttribute("data-date", dateText); node.setAttribute("date-isoweekday", day); var ev = this.fire("dateRender", { // 當(dāng)前完整日期 date: dateText, // iso星期 isoWeekday: day, // 顯示的文本 dateText: "周" + this._WEEKSNAME[day - 1] + " " + date.format("MM-DD"), // classname dateCls: node.className, // 日歷el el: this.el, // 當(dāng)前el dateEl: node }); // 處理事件的修改 node.innerHTML = ev.dateText; node.className = ev.dateCls; this._weeksEl.appendChild(node); this.fire("afterDateRender", { // 當(dāng)前完整日期 date: dateText, // iso星期 isoWeekday: day, // 顯示的文本 dateText: node.innerHTML, // classname dateCls: node.className, // 日歷el el: this.el, // 當(dāng)前el dateEl: node }); } }網(wǎng)格和內(nèi)容
上面已經(jīng)準(zhǔn)備好了二維視圖中的兩個(gè)軸,接著進(jìn)行網(wǎng)格和內(nèi)容層的繪制即可。
網(wǎng)格
此處以分類(lèi)為Y方向(行),日期為X方向(列)來(lái)進(jìn)行繪制:
{ // 右側(cè)網(wǎng)格 _renderGrid: function () { this._gridEl.innerHTML = ""; var rowNode = document.createElement("div"), itemNode = document.createElement("span"), rowsNum = this._categoryData.length, i = 0, j = 0, row, item; rowNode.className = "ep-weekcalendar-grid-row"; itemNode.className = "ep-weekcalendar-grid-item"; while (i < rowsNum) { row = rowNode.cloneNode(); row.setAttribute("data-i", i); j = 0; while (j < 7) { item = itemNode.cloneNode(); // 周末標(biāo)識(shí) if (this.dayStartFromSunday) { if (j === 0 || j === 6) { item.className += " weekend"; } } else { if (j > 4) { item.className += " weekend"; } } item.setAttribute("data-i", i); item.setAttribute("data-j", j); row.appendChild(item); j++; } this._gridEl.appendChild(row); i++; } rowNode = itemNode = row = item = null; } }
內(nèi)容
理論上來(lái)說(shuō),二維要支持跨行、跨列兩種情況,即內(nèi)容區(qū)域應(yīng)該為一整塊元素。但是結(jié)合到實(shí)際情況,跨時(shí)間的需求普遍存在(一個(gè)東西在一段時(shí)間內(nèi)被連續(xù)使用)。跨分類(lèi)并沒(méi)有多大的實(shí)際意義,本來(lái)就要分開(kāi)以分類(lèi)來(lái)管理,再跨分類(lèi),又變得復(fù)雜了。而且即使一定要實(shí)現(xiàn)一段時(shí)間內(nèi)同時(shí)在使用多個(gè)東西,也是可以直接實(shí)現(xiàn)的(分類(lèi)A在XX時(shí)間段內(nèi)被使用,B在XX時(shí)間段內(nèi)被使用,只是此時(shí)XX正好相同而已)。
因此此處僅處理跨時(shí)間情況,可將內(nèi)容按行即分類(lèi)進(jìn)行繪制,這樣在插入內(nèi)容部件時(shí),可以簡(jiǎn)化很多計(jì)算。
{ // 右側(cè)內(nèi)容 _rednerContent: function () { this._contentEl.innerHTML = ""; var i = 0, node = document.createElement("div"), row; node.className = "ep-weekcalendar-content-row"; while (i < this._categoryData.length) { row = node.cloneNode(); row.setAttribute("data-i", i); this._contentEl.appendChild(row); ++i; } row = node = null; }, // 日期切換時(shí)清空內(nèi)容 _clearContent: function () { var rows = this._contentEl.childNodes, i = 0; while (i < rows.length) { rows[i].innerHTML && (rows[i].innerHTML = ""); ++i; } // 部件數(shù)據(jù)清空 this._widgetData = {}; } }
如果一定要實(shí)現(xiàn)跨行跨列的情況,直接將內(nèi)容繪制成一整塊元素即可,但是在點(diǎn)擊事件和插入內(nèi)容部件時(shí),需要同時(shí)計(jì)算對(duì)應(yīng)的分類(lèi)和日期時(shí)間。
難點(diǎn)實(shí)現(xiàn) 內(nèi)容部件插入我們實(shí)現(xiàn)這個(gè)二維周視圖日歷的主要目的就是要支持插入任意的內(nèi)容,上面已經(jīng)準(zhǔn)備好了插入內(nèi)容的dom元素,這里要做的就是將數(shù)據(jù)繪制成dom放置在合適的位置。
考慮必要的內(nèi)容部件數(shù)據(jù)結(jié)構(gòu)如下:
{ id: "數(shù)據(jù)標(biāo)識(shí)", categoryId: "所屬分類(lèi)標(biāo)識(shí)", title: "名稱(chēng)", content: "內(nèi)容", start: "開(kāi)始日期時(shí)間" end: "結(jié)束日期時(shí)間" bgColor: "展示的背景色" }
由于上面在內(nèi)容區(qū)域是直接按照分類(lèi)作為繪制的,因此拿到數(shù)據(jù)后,對(duì)應(yīng)的分類(lèi)就已經(jīng)存在了。重點(diǎn)要根據(jù)指定的開(kāi)始和結(jié)束時(shí)間計(jì)算出開(kāi)始和結(jié)束位置。
考慮如下:
考慮響應(yīng)式,位置計(jì)算按照百分比計(jì)算
一周的總時(shí)間是固定的,開(kāi)始日期時(shí)間和這周開(kāi)始日期時(shí)間的差額占總時(shí)間的百分比即開(kāi)始位置的百分比
結(jié)束日期時(shí)間和開(kāi)始時(shí)間的差額占總時(shí)間的百分比即為結(jié)束時(shí)間距離最左側(cè)的百分比
注意處理開(kāi)始和結(jié)束時(shí)間溢出本周的情況
因此關(guān)于位置計(jì)算可以用如下代碼處理:
{ // 日期時(shí)間分隔符 默認(rèn)為空 對(duì)應(yīng)格式為 "2017-11-11 20:00" // 對(duì)于"2017-11-11T20:00" 這樣的格式務(wù)必指定正確的日期和時(shí)間之間的分隔符T _dateTimeSplit:" ", // 一周分鐘數(shù) _WEEKMINUTES: 7 * 24 * 60, // 一周秒數(shù) _WEEKSECONDS: 7 * 24 * 3600, // 一天的分鐘數(shù)秒數(shù) _DAYMINUTES: 24 * 60, _DAYSCONDS: 24 * 3600, // 計(jì)算位置的精度 取值second 或 minute posUnit: "second", // 計(jì)算指定日期的分鐘或秒數(shù) _getNumByUnits: function (dateStr) { var temp = dateStr.split(this._dateTimeSplit), date = temp[0]; // 處理左側(cè)溢出 if (this._startDate.isAfter(date, "day")) { // 指定日期在開(kāi)始日期之前 return 0; } // 右側(cè)溢出直接算作第7天即可 var times = (temp[1] || "").split(":"), days = (function (startDate) { var currDate = startDate.clone(), i = 0, d = moment(date, "YYYY-MM-DD"); while (i < 7) { if (currDate.isSame(d, "day")) { return i; } else { currDate.add(1, "day"); ++i; } } console && console.error && console.error("計(jì)算天數(shù)時(shí)出錯(cuò)!"); return i; }(this._startDate)), hours = parseInt(times[0], 10) || 0, minutes = parseInt(times[1], 10) || 0, seconds = parseInt(times[2], 10) || 0, // 對(duì)應(yīng)分鐘數(shù) result = days * this._DAYMINUTES + hours * 60 + minutes; return this.posUnit == "minute" ? result : (result * 60 + seconds); }, // 計(jì)算日期時(shí)間的百分比位置 _getPos: function (dateStr) { var p = this._getNumByUnits(dateStr) / (this.posUnit == "minute" ? this._WEEKMINUTES : this._WEEKSECONDS); return p > 1 ? 1 : p; } }
上面就拿到了一個(gè)數(shù)據(jù)所對(duì)應(yīng)的開(kāi)始位置和結(jié)束位置。基本上是已經(jīng)完成了,但是還需要再處理一個(gè)情況:相同分類(lèi)下的時(shí)間沖突問(wèn)題。
考慮以如下方式進(jìn)行:
沒(méi)添加一個(gè)就記錄下其數(shù)據(jù)
新增的如果和當(dāng)前分類(lèi)下已有的存在時(shí)間重疊,則認(rèn)為沖突。
實(shí)現(xiàn)如下:
{ /** * 檢查是否發(fā)生重疊 * * @param {Object} data 當(dāng)前要加入的數(shù)據(jù) * @returns false 或 和當(dāng)前部件重疊的元素?cái)?shù)組 */ _checkOccupied: function (data) { if (!this._widgetData[data.categoryId]) { return false; } var i = 0, cate = this._widgetData[data.categoryId], len = cate.length, result = false, occupied = []; for (; i < len; ++i) { // 判斷時(shí)間是否存在重疊 if (data.start < cate[i].end && data.end > cate[i].start) { occupied.push(cate[i]); result = true; } } return result ? occupied : false; } }
完成以上兩步就可以往我們的內(nèi)容區(qū)域中插入了
{ // 緩存widget數(shù)據(jù) _cacheWidgetData: function (data) { if (!this._widgetData[data.categoryId]) { this._widgetData[data.categoryId] = []; } // 記錄當(dāng)前的 this._widgetData[data.categoryId].push(data); }, // 新增一個(gè)小部件 addWidget: function (data) { var row = this._contentEl.childNodes[this._categoryReocrds[data.categoryId]]; if (!row) { this.throwError("對(duì)應(yīng)分類(lèi)不存在,添加失敗"); return false; } // 先查找是否含有 var $aim = jQuery(".ep-weekcalendar-content-widget[data-id="" + data.id + ""]", row); if ($aim.length) { // 已經(jīng)存在則不添加 return $aim[0]; } // 創(chuàng)建部件 var widget = document.createElement("div"), title = document.createElement("span"), content = document.createElement("p"), startPos = this._getPos(data.start), endPos = this._getPos(data.end), _data = { categoryId: data.categoryId, id: data.id, start: startPos, end: endPos, el: widget, data: data }; widget.className = "ep-weekcalendar-content-widget"; title.className = "ep-weekcalendar-content-widget-title"; content.className = "ep-weekcalendar-content-widget-content"; widget.appendChild(title); widget.appendChild(content); // 通過(guò)絕對(duì)定位,指定其left和right來(lái)拉開(kāi)寬度的方式來(lái)處理響應(yīng)式 // 可以通過(guò)樣式設(shè)置一個(gè)最小寬度,來(lái)避免時(shí)間段過(guò)小時(shí)其中文本無(wú)法顯示的問(wèn)題 widget.style.left = startPos * 100 + "%"; widget.style.right = (1 - endPos) * 100 + "%"; data.bgColor && (widget.style.backgroundColor = data.bgColor); data.id && widget.setAttribute("data-id", data.id); widget.setAttribute("data-start", data.start); widget.setAttribute("data-end", data.end); title.innerHTML = data.title; data.content && (content.innerHTML = data.content); widget.title = data.title; // 檢查是否發(fā)生重疊 var isoccupied = this._checkOccupied(_data); if (isoccupied) { // 觸發(fā)重疊事件 var occupiedEv = this.fire("widgetoccupied", { occupiedWidgets: (function () { var arr = []; for (var i = 0, l = isoccupied.length; i < l; ++i) { arr.push(isoccupied[i].el); } return arr; })(), currWidget: widget, widgetData: data }); // 取消后續(xù)執(zhí)行 if (occupiedEv.cancel) { return false; } } // 緩存數(shù)據(jù) this._cacheWidgetData(_data); var addEv = this.fire("widgetAdd", { widgetId: data.id, categoryId: data.categoryId, start: data.start, end: data.end, startPos: startPos, endPos: endPos, widgetEl: widget }); if (addEv.cancel) { return false; } row.appendChild(widget); this.fire("afterWidgetAdd", { widgetId: data.id, categoryId: data.categoryId, start: data.start, end: data.end, startPos: startPos, endPos: endPos, widgetEl: widget }); return widget; }, }點(diǎn)擊事件和范圍選擇
此控件不僅用于結(jié)果展示,還要可用于點(diǎn)擊進(jìn)行添加,需要處理其點(diǎn)擊事件,但是由于要展示內(nèi)容,內(nèi)容是覆蓋在分類(lèi)和日期構(gòu)成的網(wǎng)格之上的,用戶的點(diǎn)擊是點(diǎn)擊不到網(wǎng)格元素的,必須要根據(jù)點(diǎn)擊的位置進(jìn)行計(jì)算來(lái)獲取所點(diǎn)擊的日期和所在分類(lèi)。
同時(shí),由于展示的部件都是時(shí)間范圍的,因此點(diǎn)擊返回某天和某個(gè)分類(lèi)是不夠的,還需要能夠支持鼠標(biāo)按下拖動(dòng)再松開(kāi),來(lái)直接選的一段時(shí)間。
考慮到以上需求,點(diǎn)擊事件不能直接使用 click 來(lái)實(shí)現(xiàn),考慮使用 mousedown 和 mouseup 來(lái)處理點(diǎn)擊事件,同時(shí)需要在 mousemove 中實(shí)時(shí)給出用戶響應(yīng)。
{ _initEvent: function () { var me = this; // 點(diǎn)擊的行索引 var row, // 開(kāi)始列索引 columnStart, // 結(jié)束列索引 columnEnd, // 是否在按下、移動(dòng)、松開(kāi)的click中 isDurringClick = false, // 是否移動(dòng)過(guò) 用于處理按下沒(méi)有移動(dòng)直接松開(kāi)的過(guò)程 isMoveing = false, $columns, // 網(wǎng)格左側(cè)寬度 gridLeft, // 每列的寬度 columnWidth jQuery(this.el) // 按下鼠標(biāo) 記錄分類(lèi)和開(kāi)始列 .on("mousedown.weekcalendar", ".ep-weekcalendar-content-row", function (e) { isDurringClick = true; gridLeft = jQuery(me._gridEl).offset().left; columnWidth = jQuery(me._gridEl).width() / 7; jQuery(me._gridEl).find(".ep-weekcalendar-grid-item").removeClass(me._selectedCls); row = this.getAttribute("data-i"); $columns = jQuery(me._gridEl).find(".ep-weekcalendar-grid-row").eq(row).children(); columnStart = (e.pageX - gridLeft) / columnWidth >> 0; }); // 移動(dòng)和松開(kāi) 松開(kāi)鼠標(biāo) 記錄結(jié)束列 觸發(fā)點(diǎn)擊事件 // 不能直接綁定在日期容器上 否則鼠標(biāo)移出日歷后,松開(kāi)鼠標(biāo),實(shí)際點(diǎn)擊已經(jīng)結(jié)束,但是日歷上處理不到。 jQuery("body") // 點(diǎn)擊移動(dòng)過(guò)程中 實(shí)時(shí)響應(yīng)選中狀態(tài) .on("mousemove.weekcalendar", function (e) { if (!isDurringClick) { return; } isMoveing = true; // 當(dāng)前列索引 var currColumn; // mousemoveTimer = setTimeout(function () { currColumn = (e.pageX - gridLeft) / columnWidth >> 0; // 修正溢出 currColumn = currColumn > 6 ? 6 : currColumn; currColumn = currColumn < 0 ? 0 : currColumn; $columns.removeClass(me._selectedCls); // 起止依次選中 var start = Math.min(columnStart, currColumn), end = Math.max(columnStart, currColumn); do { $columns.eq(start).addClass(me._selectedCls); } while (++start <= end); }) // 鼠標(biāo)松開(kāi) .on("mouseup.weekcalendar", function (e) { if (!isDurringClick) { return; } var startIndex = -1, endIndex = -1; columnEnd = (e.pageX - gridLeft) / columnWidth >> 0; columnEnd = columnEnd > 6 ? 6 : columnEnd; // 沒(méi)有移動(dòng)過(guò)時(shí) if (!isMoveing) { startIndex = endIndex = columnEnd; // 直接down up 沒(méi)有move的過(guò)程則只會(huì)有一個(gè)選中的,直接以結(jié)束的作為處理即可 $columns.eq(columnEnd).addClass(me._selectedCls) .siblings().removeClass(me._selectedCls); } else { startIndex = Math.min(columnStart, columnEnd); endIndex = Math.max(columnStart, columnEnd); } // 觸發(fā)點(diǎn)擊事件 me.fire("cellClick", { // 分類(lèi)id categoryId: me._categoryIndexs[row], // 時(shí)間1 startDate: me._dateRecords[startIndex].format("YYYY-MM-DD"), // 日期2 endDate: me._dateRecords[endIndex].format("YYYY-MM-DD"), // 行索引 rowIndex: row, // 列范圍 columnIndexs: (function (i, j) { var arr = []; while (i <= j) { arr.push(i++); } return arr; }(startIndex, endIndex)) }); row = columnStart = columnEnd = isMoveing = isDurringClick = false; }); } }
此過(guò)程要注意的問(wèn)題是:mousedown 必須綁定在日歷上,而 mouseup 和 mousemove 則不能綁定在日歷上,具體原因已經(jīng)寫(xiě)在上面代碼注釋中了。
另外需要注意,由于范圍點(diǎn)擊選擇使用了 mousedown 和 mouseup 來(lái)模擬,那么日歷內(nèi)容區(qū)域中插入的數(shù)據(jù)部件的點(diǎn)擊事件也要用 mousedown 和 mouseup 來(lái)模擬,因?yàn)?mouseup 觸發(fā)比 click 早,如果使用 click ,會(huì)導(dǎo)致先觸發(fā)日歷上的日期點(diǎn)擊或日期范圍點(diǎn)擊。
使用此日歷實(shí)現(xiàn)基于一個(gè)控件基類(lèi)擴(kuò)展而來(lái),其必要功能僅為一套事件機(jī)制,可參考實(shí)現(xiàn)一套自定義事件機(jī)制
實(shí)測(cè)一下效果吧:
github
demo
本文首發(fā)我的博客:https://blog.cdswyda.com/post/2017121022
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/92057.html
摘要:直接使用事件代理機(jī)制,將事件綁定在整個(gè)日歷的上即可,這樣事件只用在創(chuàng)建時(shí)初始化一次即可,簡(jiǎn)單高效省內(nèi)存。 首發(fā)我的博客 - https://blog.cdswyda.com/post/2017121010 日歷控件多的不勝枚舉,為什么我們還要再造一個(gè)輪子呢? 因?yàn)榇蠖鄶?shù)日歷控件都是用于選擇日期的,有種需求是要在日歷上展示各種各樣的內(nèi)容,這樣的日歷控件較少,而且試用下來(lái)并不滿意。 因此就...
摘要:插件的依賴(lài)文件插件的使用頁(yè)面結(jié)構(gòu)設(shè)置日歷頭部信息,如果設(shè)置為,則不顯示頭部信息。設(shè)置日歷的高度,包括日歷頭部,默認(rèn)未設(shè)置,高度根據(jù)值自適應(yīng)。 先說(shuō)一下我的另一博客地址: https://home.cnblogs.com/u/bllx/ FullCalendar的選擇 前段時(shí)間,一直在開(kāi)發(fā)考勤系統(tǒng),當(dāng)時(shí)為滿足設(shè)計(jì)的需求,選了好幾個(gè)插件,最后決定采用Fullcanlendar的插件。感覺(jué)這...
摘要:本節(jié)接上周的文檔學(xué)習(xí)小組博客開(kāi)發(fā)實(shí)戰(zhàn)第一周教程編寫(xiě)博客的首頁(yè)面,我們繼續(xù)給博客添加功能,以及改善前面不合理的部分。返回該視圖要顯示的對(duì)象。目前小組正在完成第一個(gè)項(xiàng)目,本文即是該項(xiàng)目第二周的相關(guān)文檔。 本教程內(nèi)容已過(guò)時(shí),更新版教程請(qǐng)?jiān)L問(wèn): django 博客開(kāi)發(fā)入門(mén)教程。 上周我們完成了博客的 Model 部分,以及 Blog 的首頁(yè)視圖 IndexView。 本節(jié)接上周的文檔 Djan...
摘要:日歷的項(xiàng)目地址示例上的一個(gè)日歷控件,可以定制成自己想要的樣子。跳轉(zhuǎn)到指定日期,默認(rèn)支持動(dòng)畫(huà)切換自定義日歷,支持組合的方式和利用繪制的方式自定義頂部的可以給添加自定義的額外數(shù)據(jù),實(shí)現(xiàn)各種額外的功能。介紹 最近自己寫(xiě)了個(gè)demo,用到了日歷方面的東西,然后實(shí)現(xiàn)來(lái)一下,最后打算封裝一下,以后可以直接拿來(lái)使用。 參考了Android的一個(gè)開(kāi)源日歷庫(kù)github.com/huanghaibin…,實(shí)現(xiàn)...
閱讀 2055·2019-08-30 15:52
閱讀 2446·2019-08-29 18:37
閱讀 799·2019-08-29 12:33
閱讀 2846·2019-08-29 11:04
閱讀 1536·2019-08-27 10:57
閱讀 2101·2019-08-26 13:38
閱讀 2768·2019-08-26 12:25
閱讀 2455·2019-08-26 12:23