123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166 |
- /**
- * jQuery Gantt Chart
- *
- * @see http://taitems.github.io/jQuery.Gantt/
- * @license MIT
- */
- /*jshint camelcase:true, freeze:true, jquery:true */
- ;(function($, undefined) {
- 'use strict'
- var UTC_DAY_IN_MS = 24 * 60 * 60 * 1000
- var total = 0
- // 计划年份
- var planYear
- // 记录原始top值
- var curItemId = null
- var historyTop = null
- var hiddenBar = []
- var isHidden = true
- // custom selector `:findday` used to match on specified day in ms.
- //
- // The selector is passed a date in ms and elements are added to the
- // selection filter if the element date matches, as determined by the
- // id attribute containing a parsable date in ms.
- // 打开链接方法
- function openProjectUrl(url) {
- if (url) {
- window.oepn(url)
- } else {
- alert(123)
- }
- }
- function findDay(elt, text) {
- var cd = new Date(parseInt(text, 10))
- cd.setHours(0, 0, 0, 0)
- var id = $(elt).attr('id') || ''
- var si = id.indexOf('-') + 1
- var ed = new Date(parseInt(id.substring(si, id.length), 10))
- ed.setHours(0, 0, 0, 0)
- return cd.getTime() === ed.getTime()
- }
- $.expr.pseudos.findday = !$.expr.createPseudo
- ? function(elt, i, match) {
- return findDay(elt, match[3])
- }
- : $.expr.createPseudo(function(text) {
- return function(elt) {
- return findDay(elt, text)
- }
- })
- // custom selector `:findweek` used to match on specified week in ms.
- function findWeek(elt, text) {
- var cd = new Date(parseInt(text, 10))
- var y = cd.getFullYear()
- var w = cd.getWeekOfYear()
- var m = cd.getMonth()
- if (m === 11 && w === 1) {
- y++
- } else if (!m && w > 51) {
- y--
- }
- cd = y + '-' + w
- var id = $(elt).attr('id') || ''
- var si = id.indexOf('-') + 1
- var ed = id.substring(si, id.length)
- return cd === ed
- }
- $.expr.pseudos.findweek = $.expr.createPseudo
- ? $.expr.createPseudo(function(text) {
- return function(elt) {
- return findWeek(elt, text)
- }
- })
- : function(elt, i, match) {
- return findWeek(elt, match[3])
- }
- // custom selector `:findmonth` used to match on specified month in ms.
- function findMonth(elt, text) {
- var cd = new Date(parseInt(text, 10))
- cd = cd.getFullYear() + '-' + cd.getMonth()
- var id = $(elt).attr('id') || ''
- var si = id.indexOf('-') + 1
- var ed = id.substring(si, id.length)
- return cd === ed
- }
- $.expr[':'].findmonth = $.expr.createPseudo
- ? $.expr.createPseudo(function(text) {
- return function(elt) {
- return findMonth(elt, text)
- }
- })
- : function(elt, i, match) {
- return findMonth(elt, match[3])
- }
- // Date prototype helpers
- // ======================
- // `getWeekId` returns a string in the form of 'dh-YYYY-WW', where WW is
- // the week # for the year.
- // It is used to add an id to the week divs
- Date.prototype.getWeekId = function() {
- var y = this.getFullYear()
- var w = this.getWeekOfYear()
- var m = this.getMonth()
- if (m === 11 && w === 1) {
- y++
- } else if (!m && w > 51) {
- y--
- }
- return 'dh-' + y + '-' + w
- }
- // `getRepDate` returns the milliseconds since the epoch for a given date
- // depending on the active scale
- Date.prototype.getRepDate = function(scale) {
- switch (scale) {
- case 'hours':
- return this.getTime()
- case 'weeks':
- return this.getDayForWeek().getTime()
- case 'months':
- return new Date(this.getFullYear(), this.getMonth(), 1).getTime()
- case 'days':
- /* falls through */
- default:
- return this.getTime()
- }
- }
- // `getDayOfYear` returns the day number for the year
- Date.prototype.getDayOfYear = function() {
- var year = this.getFullYear()
- return (Date.UTC(year, this.getMonth(), this.getDate()) - Date.UTC(year, 0, 0)) / UTC_DAY_IN_MS
- }
- // Use ISO week by default
- //TODO: make these options.
- var firstDay = 1 // ISO week starts with Monday (1); use Sunday (0) for, e.g., North America
- var weekOneDate = 4 // ISO week one always contains 4 Jan; use 1 Jan for, e.g., North America
- // `getWeekOfYear` returns the week number for the year
- //TODO: fix bug when firstDay=6/weekOneDate=1 : https://github.com/moment/moment/issues/2115
- Date.prototype.getWeekOfYear = function() {
- var year = this.getFullYear(),
- month = this.getMonth(),
- date = this.getDate(),
- day = this.getDay()
- //var diff = weekOneDate - day + 7 * (day < firstDay ? -1 : 1);
- var diff = weekOneDate - day
- if (day < firstDay) {
- diff -= 7
- }
- if (diff + 7 < weekOneDate - firstDay) {
- diff += 7
- }
- return Math.ceil(new Date(year, month, date + diff).getDayOfYear() / 7)
- }
- // `getDayForWeek` returns the first day of this Date's week
- Date.prototype.getDayForWeek = function() {
- var day = this.getDay()
- var diff = (day < firstDay ? -7 : 0) + firstDay - day
- return new Date(this.getFullYear(), this.getMonth(), this.getDate() + diff)
- }
- // fixes https://github.com/taitems/jQuery.Gantt/issues/62
- function ktkGetNextDate(currentDate, scaleStep) {
- for (var minIncrements = 1; ; minIncrements++) {
- var nextDate = new Date(currentDate)
- nextDate.setHours(currentDate.getHours() + scaleStep * minIncrements)
- if (nextDate.getTime() !== currentDate.getTime()) {
- return nextDate
- }
- // If code reaches here, it's because current didn't really increment (invalid local time) because of daylight-saving adjustments
- // => retry adding 2, 3, 4 hours, and so on (until nextDate > current)
- }
- }
- $.fn.gantt = function(options) {
- planYear = options.planYear
- total = options.source.length
- var scales = ['hours', 'days', 'weeks', 'months']
- //Default settings
- var settings = {
- source: [],
- holidays: [],
- // paging
- itemsPerPage: 7,
- // localisation
- dow: ['7', '1', '2', '3', '4', '5', '6'],
- months: [
- '一月',
- '二月',
- '三月',
- '四月',
- '五月',
- '六月',
- '七月',
- '八月',
- '九月',
- '十月',
- '十一月',
- '十二月',
- ],
- waitText: '加载中...',
- // navigation
- navigate: 'buttons',
- scrollToToday: true,
- // cookie options
- useCookie: false,
- cookieKey: 'jquery.fn.gantt',
- // scale parameters
- scale: 'days',
- maxScale: 'months',
- minScale: 'hours',
- // callbacks
- onItemClick: function(data) {
- return
- },
- onAddClick: function(dt, rowId) {
- return
- },
- onRender: $.noop,
- }
- // read options
- $.extend(settings, options)
- // can't use cookie if don't have `$.cookie`
- settings.useCookie = settings.useCookie && $.isFunction($.cookie)
- // Grid management
- // ===============
- // Core object is responsible for navigation and rendering
- var core = {
- // Return the element whose topmost point lies under the given point
- // Normalizes for old browsers (NOTE: doesn't work when element is outside viewport)
- //TODO: https://github.com/taitems/jQuery.Gantt/issues/137
- elementFromPoint: (function() {
- // IIFE
- // version for normal browsers
- if (document.compatMode === 'CSS1Compat') {
- return function(x, y) {
- x -= window.pageXOffset
- y -= window.pageYOffset
- return document.elementFromPoint(x, y)
- }
- }
- // version for older browsers
- return function(x, y) {
- x -= $(document).scrollLeft()
- y -= $(document).scrollTop()
- return document.elementFromPoint(x, y)
- }
- })(),
- // **Create the chart**
- create: function(element) {
- // Initialize data with a json object or fetch via an xhr
- // request depending on `settings.source`
- if (typeof settings.source !== 'string') {
- element.data = settings.source
- core.init(element)
- } else {
- $.getJSON(settings.source, function(jsData) {
- element.data = jsData
- core.init(element)
- })
- }
- },
- // **Setup the initial view**
- // Here we calculate the number of rows, pages and visible start
- // and end dates once the data are ready
- init: function(element) {
- element.rowsNum = element.data.length
- element.pageCount = Math.ceil(element.rowsNum / settings.itemsPerPage)
- element.rowsOnLastPage =
- element.rowsNum -
- Math.floor(element.rowsNum / settings.itemsPerPage) * settings.itemsPerPage
- // element.dateStart = tools.getMinDate(element)
- // element.dateEnd = tools.getMaxDate(element)
- element.dateStart = new Date(planYear - 1 + '/10/1 00:00:00')
- element.dateEnd = new Date(planYear + 1 + '/3/31 23:59:59')
- /* core.render(element); */
- core.waitToggle(element, function() {
- core.render(element)
- })
- },
- // **Render the grid**
- render: function(element) {
- var content = $('<div class="fn-content"/>')
- var maindiv = $('<div class="main-div-custom"></div>')
- var $leftPanel = core.leftPanel(element)
- maindiv.append($leftPanel)
- var $rightPanel = core.rightPanel(element, $leftPanel)
- var pLeft, hPos
- maindiv.append($rightPanel)
- content.append(core.navigation(element))
- var $dataPanel = $rightPanel.find('.dataPanel')
- element.gantt = $('<div class="fn-gantt" />')
- .append(maindiv)
- .append(content)
- $(element)
- .empty()
- .append(element.gantt)
- element.scrollNavigation.panelMargin = parseInt(
- $dataPanel.css('left').replace('px', ''),
- 10
- )
- element.scrollNavigation.panelMaxPos = $dataPanel.width() - $rightPanel.width()
- element.scrollNavigation.canScroll = $dataPanel.width() > $rightPanel.width()
- core.markNow(element)
- core.fillData(element, $dataPanel, $leftPanel)
- // Set a cookie to record current position in the view
- if (settings.useCookie) {
- var sc = $.cookie(settings.cookieKey + 'ScrollPos')
- if (sc) {
- element.hPosition = sc
- }
- }
- // Scroll the grid to today's date
- if (settings.scrollToToday) {
- core.navigateTo(element, 'now')
- core.scrollPanel(element, 0)
- // or, scroll the grid to the left most date in the panel
- } else {
- if (element.hPosition !== 0) {
- if (element.scaleOldWidth) {
- pLeft = $dataPanel.width() - $rightPanel.width()
- hPos = (pLeft * element.hPosition) / element.scaleOldWidth
- element.hPosition = hPos > 0 ? 0 : hPos
- element.scaleOldWidth = null
- }
- $dataPanel.css({ left: element.hPosition })
- element.scrollNavigation.panelMargin = element.hPosition
- }
- core.repositionLabel(element)
- }
- $dataPanel.css({ height: $leftPanel.height() })
- core.waitToggle(element)
- settings.onRender()
- },
- // Create and return the left panel with labels
- leftPanel: function(element) {
- /* Left panel */
- var ganttLeftPanel = $('<div class="leftPanel"/>').append(
- $(
- '<div class="row spacer"><div class="pindex" style="line-height:' +
- tools.getCellSize() * element.headerRows +
- 'px">序号</div><div class="pname" style="line-height:' +
- tools.getCellSize() * element.headerRows +
- 'px">项目名称</div><div class="pstatus" style="line-height:' +
- tools.getCellSize() * element.headerRows +
- 'px">项目状态</div></div>'
- ).css('height', tools.getCellSize() * element.headerRows)
- )
- var entries = []
- var k = 1
- $.each(element.data, function(i, entry) {
- if (
- i >= element.pageNum * settings.itemsPerPage &&
- i < element.pageNum * settings.itemsPerPage + settings.itemsPerPage
- ) {
- var dataId = 'id' in entry ? '" data-id="' + entry.id : ''
- entries.push(
- '<div class="row name row' +
- i +
- (entry.desc ? '' : ' fn-wide ' + dataId) +
- '" id="rowheader' +
- i +
- '" data-offset="' +
- (i % settings.itemsPerPage) * tools.getCellSize() +
- '" >' +
- '<span class="indexspan">' +
- (i + 1) +
- '</span><span class="fn-label' +
- (entry.cssClass ? ' ' + entry.cssClass : '') +
- '" title="' +
- (entry.name || '') +
- '">' +
- '<a rel="opener" target="_blank" href="' +
- entry.url +
- '" >' +
- (entry.name || '') +
- '</a>' +
- '</span>' +
- '</div>'
- )
- k++
- if (entry.desc) {
- entries.push(
- '<div class="row desc row' +
- i +
- ' " id="RowdId_' +
- i +
- dataId +
- '">' +
- '<span class="fn-label' +
- (entry.cssClass ? ' ' + entry.cssClass : '') +
- '">' +
- entry.desc +
- '</span>' +
- '</div>'
- )
- }
- }
- })
- return ganttLeftPanel.append(entries.join(''))
- },
- // Create and return the data panel element
- dataPanel: function(element, width) {
- var dataPanel = $('<div class="dataPanel" style="width: ' + width + 'px;"/>')
- // Handle mousewheel events for scrolling the data panel
- var wheel =
- 'onwheel' in element
- ? 'wheel'
- : document.onmousewheel !== undefined
- ? 'mousewheel'
- : 'DOMMouseScroll'
- $(element).on(wheel, function(e) {
- core.wheelScroll(element, e)
- })
- // Handle click events and dispatch to registered `onAddClick` function
- dataPanel.click(function(e) {
- e.stopPropagation()
- var corrX /* <- never used? */, corrY
- var leftpanel = $(element).find('.fn-gantt .leftPanel')
- var datapanel = $(element).find('.fn-gantt .dataPanel')
- switch (settings.scale) {
- case 'months':
- corrY = tools.getCellSize()
- break
- case 'hours':
- corrY = tools.getCellSize() * 4
- break
- case 'days':
- corrY = tools.getCellSize() * 3
- break
- case 'weeks':
- /* falls through */
- default:
- corrY = tools.getCellSize() * 2
- }
- /* Adjust, so get middle of elm
- corrY -= Math.floor(tools.getCellSize() / 2);
- */
- // Find column where click occurred
- var col = core.elementFromPoint(e.pageX, datapanel.offset().top + corrY)
- // Was the label clicked directly?
- if (col.className === 'fn-label') {
- col = $(col.parentNode)
- } else {
- col = $(col)
- }
- var dt = col.data('repdate')
- // Find row where click occurred
- var row = core.elementFromPoint(leftpanel.offset().left + leftpanel.width() - 10, e.pageY)
- // Was the label clicked directly?
- if (row.className.indexOf('fn-label') === 0) {
- row = $(row.parentNode)
- } else {
- row = $(row)
- }
- var rowId = row.data('id')
- // Dispatch user registered function with the DateTime in ms
- // and the id if the clicked object is a row
- settings.onAddClick(dt, rowId)
- })
- return dataPanel
- },
- // Creates and return the right panel containing the year/week/day header
- rightPanel: function(element, leftPanel /* <- never used? */) {
- var range = null
- // Days of the week have a class of one of
- // `sn` (Sunday), `sa` (Saturday), or `wd` (Weekday)
- var dowClass = ['sn', 'wd', 'wd', 'wd', 'wd', 'wd', 'sa']
- //unused: was someone planning to allow styles to stretch to the bottom of the chart?
- //var gridDowClass = [" sn", "", "", "", "", "", " sa"];
- var yearArr = []
- var scaleUnitsThisYear = 0
- var monthArr = []
- var scaleUnitsThisMonth = 0
- var dayArr = []
- var hoursInDay = 0
- var dowArr = []
- var horArr = []
- var today = new Date()
- today.setHours(0, 0, 0, 0)
- // reused variables
- var $row = $('<div class="row header"></div>')
- var i, len
- var year, month, week, day
- var rday, dayClass
- var dataPanel, dataPanelWidth
- // Setup the headings based on the chosen `settings.scale`
- switch (settings.scale) {
- // **Hours**
- case 'hours':
- range = tools.parseTimeRange(element.dateStart, element.dateEnd, element.scaleStep)
- dataPanelWidth = range.length * tools.getCellSize()
- year = range[0].getFullYear()
- month = range[0].getMonth()
- day = range[0]
- for (i = 0, len = range.length; i < len; i++) {
- rday = range[i]
- // Fill years
- var rfy = rday.getFullYear()
- if (rfy !== year) {
- yearArr.push(
- '<div class="row year" style="width: ' +
- tools.getCellSize() * scaleUnitsThisYear +
- 'px;"><div class="fn-label">' +
- year +
- '</div></div>'
- )
- year = rfy
- scaleUnitsThisYear = 0
- }
- scaleUnitsThisYear++
- // Fill months
- var rm = rday.getMonth()
- if (rm !== month) {
- monthArr.push(
- '<div class="row month" style="width: ' +
- tools.getCellSize() * scaleUnitsThisMonth +
- 'px"><div class="fn-label">' +
- settings.months[month] +
- '</div></div>'
- )
- month = rm
- scaleUnitsThisMonth = 0
- }
- scaleUnitsThisMonth++
- // Fill days & hours
- var rgetDay = rday.getDay()
- var getDay = day.getDay()
- if (rgetDay !== getDay) {
- dayClass =
- today - day === 0
- ? 'today'
- : tools.isHoliday(day.getTime())
- ? 'holiday'
- : dowClass[getDay]
- dayArr.push(
- '<div class="row date ' +
- dayClass +
- '" ' +
- 'style="width: ' +
- tools.getCellSize() * hoursInDay +
- 'px;">' +
- '<div class="fn-label">' +
- day.getDate() +
- '</div></div>'
- )
- dowArr.push(
- '<div class="row day ' +
- dayClass +
- '" ' +
- 'style="width: ' +
- tools.getCellSize() * hoursInDay +
- 'px;">' +
- '<div class="fn-label">' +
- settings.dow[getDay] +
- '</div></div>'
- )
- day = rday
- hoursInDay = 0
- }
- hoursInDay++
- dayClass = dowClass[rgetDay]
- if (tools.isHoliday(rday)) {
- dayClass = 'holiday'
- }
- horArr.push(
- '<div class="row day ' +
- dayClass +
- '" id="dh-' +
- rday.getTime() +
- '" data-offset="' +
- i * tools.getCellSize() +
- '" data-repdate="' +
- rday.getRepDate(settings.scale) +
- '"><div class="fn-label">' +
- rday.getHours() +
- '</div></div>'
- )
- }
- // Last year
- yearArr.push(
- '<div class="row year" style="width: ' +
- tools.getCellSize() * scaleUnitsThisYear +
- 'px;"><div class="fn-label">' +
- year +
- '</div></div>'
- )
- // Last month
- monthArr.push(
- '<div class="row month" style="width: ' +
- tools.getCellSize() * scaleUnitsThisMonth +
- 'px"><div class="fn-label">' +
- settings.months[month] +
- '</div></div>'
- )
- dayClass = dowClass[day.getDay()]
- if (tools.isHoliday(day)) {
- dayClass = 'holiday'
- }
- dayArr.push(
- '<div class="row date ' +
- dayClass +
- '" ' +
- 'style="width: ' +
- tools.getCellSize() * hoursInDay +
- 'px;">' +
- '<div class="fn-label">' +
- day.getDate() +
- '</div></div>'
- )
- dowArr.push(
- '<div class="row day ' +
- dayClass +
- '" ' +
- 'style="width: ' +
- tools.getCellSize() * hoursInDay +
- 'px;">' +
- '<div class="fn-label">' +
- settings.dow[day.getDay()] +
- '</div></div>'
- )
- dataPanel = core.dataPanel(element, dataPanelWidth)
- // Append panel elements
- dataPanel.append(
- $row.clone().html(yearArr.join('')),
- $row.clone().html(monthArr.join('')),
- $row.clone().html(dayArr.join('')),
- $row.clone().html(dowArr.join('')),
- $row.clone().html(horArr.join(''))
- )
- break
- // **Weeks**
- case 'weeks':
- range = tools.parseWeeksRange(element.dateStart, element.dateEnd)
- dataPanelWidth = range.length * tools.getCellSize()
- year = range[0].getFullYear()
- month = range[0].getMonth()
- week = range[0].getWeekOfYear()
- var diff
- for (i = 0, len = range.length; i < len; i++) {
- rday = range[i]
- // Fill years
- if (week > (week = rday.getWeekOfYear())) {
- // partial weeks to subtract from year header
- diff = rday.getDate() - 1
- // offset one month (December) if week starts in last year
- diff -= !rday.getMonth() ? 0 : 31
- diff /= 7
- yearArr.push(
- '<div class="row year" style="width: ' +
- tools.getCellSize() * (scaleUnitsThisYear - diff) +
- 'px;"><div class="fn-label">' +
- year +
- '</div></div>'
- )
- year++
- scaleUnitsThisYear = diff
- }
- scaleUnitsThisYear++
- // Fill months
- if (rday.getMonth() !== month) {
- // partial weeks to subtract from month header
- diff = rday.getDate() - 1
- // offset one week if week starts in last month
- //diff -= (diff <= 6) ? 0 : 7;
- diff /= 7
- monthArr.push(
- '<div class="row month" style="width:' +
- tools.getCellSize() * (scaleUnitsThisMonth - diff) +
- 'px;"><div class="fn-label">' +
- settings.months[month] +
- '</div></div>'
- )
- month = rday.getMonth()
- scaleUnitsThisMonth = diff
- }
- scaleUnitsThisMonth++
- // Fill weeks
- dayArr.push(
- '<div class="row day wd"' +
- ' id="' +
- rday.getWeekId() +
- '" data-offset="' +
- i * tools.getCellSize() +
- '" data-repdate="' +
- rday.getRepDate(settings.scale) +
- '">' +
- '<div class="fn-label">' +
- week +
- '</div></div>'
- )
- }
- // Last year
- yearArr.push(
- '<div class="row year" style="width: ' +
- tools.getCellSize() * scaleUnitsThisYear +
- 'px;"><div class="fn-label">' +
- year +
- '</div></div>'
- )
- // Last month
- monthArr.push(
- '<div class="row month" style="width: ' +
- tools.getCellSize() * scaleUnitsThisMonth +
- 'px"><div class="fn-label">' +
- settings.months[month] +
- '</div></div>'
- )
- dataPanel = core.dataPanel(element, dataPanelWidth)
- // Append panel elements
- dataPanel.append(
- $row.clone().html(yearArr.join('')),
- $row.clone().html(monthArr.join('')),
- $row.clone().html(dayArr.join(''))
- )
- break
- // **Months**
- case 'months':
- range = tools.parseMonthsRange(element.dateStart, element.dateEnd)
- dataPanelWidth = range.length * tools.getCellSize() * 3
- year = range[0].getFullYear()
- month = range[0].getMonth()
- for (i = 0, len = range.length; i < len; i++) {
- rday = range[i]
- // Fill years
- if (rday.getFullYear() !== year) {
- yearArr.push(
- '<div class="row year" style="width: ' +
- tools.getCellSize() * 3 * scaleUnitsThisYear +
- 'px;"><div class="fn-label">' +
- year +
- '</div></div>'
- )
- year = rday.getFullYear()
- scaleUnitsThisYear = 0
- }
- scaleUnitsThisYear++
- monthArr.push(
- '<div class="row day wd" id="dh-' +
- tools.genId(rday) +
- '" data-offset="' +
- i * tools.getCellSize() +
- '" data-repdate="' +
- rday.getRepDate(settings.scale) +
- '" style="width:72px">' +
- (1 + rday.getMonth()) +
- '</div>'
- )
- }
- // Last year
- yearArr.push(
- '<div class="row year" style="width: ' +
- tools.getCellSize() * 3 * scaleUnitsThisYear +
- 'px;"><div class="fn-label">' +
- year +
- '</div></div>'
- )
- dataPanel = core.dataPanel(element, dataPanelWidth)
- // Append panel elements
- dataPanel.append(
- $row.clone().html(yearArr.join('')),
- $row.clone().html(monthArr.join(''))
- )
- break
- // **Days (default)**
- default:
- range = tools.parseDateRange(element.dateStart, element.dateEnd)
- dataPanelWidth = range.length * tools.getCellSize()
- var dateBefore = ktkGetNextDate(range[0], -1)
- year = dateBefore.getFullYear()
- month = dateBefore.getMonth()
- //day = dateBefore; // <- never used?
- for (i = 0, len = range.length; i < len; i++) {
- rday = range[i]
- // Fill years
- if (rday.getFullYear() !== year) {
- yearArr.push(
- '<div class="row year" style="width:' +
- tools.getCellSize() * scaleUnitsThisYear +
- 'px;"><div class="fn-label">' +
- year +
- '</div></div>'
- )
- year = rday.getFullYear()
- scaleUnitsThisYear = 0
- }
- scaleUnitsThisYear++
- // Fill months
- if (rday.getMonth() !== month) {
- monthArr.push(
- '<div class="row month" style="width:' +
- tools.getCellSize() * scaleUnitsThisMonth +
- 'px;"><div class="fn-label">' +
- settings.months[month] +
- '</div></div>'
- )
- month = rday.getMonth()
- scaleUnitsThisMonth = 0
- }
- scaleUnitsThisMonth++
- day = rday.getDay()
- dayClass = dowClass[day]
- if (tools.isHoliday(rday)) {
- dayClass = 'holiday'
- }
- dayArr.push(
- '<div class="row date ' +
- dayClass +
- '"' +
- ' id="dh-' +
- tools.genId(rday) +
- '" data-offset="' +
- i * tools.getCellSize() +
- '" data-repdate="' +
- rday.getRepDate(settings.scale) +
- '">' +
- '<div class="fn-label">' +
- rday.getDate() +
- '</div></div>'
- )
- dowArr.push(
- '<div class="row day ' +
- dayClass +
- '"' +
- ' id="dw-' +
- tools.genId(rday) +
- '" data-repdate="' +
- rday.getRepDate(settings.scale) +
- '">' +
- '<div class="fn-label">' +
- settings.dow[day] +
- '</div></div>'
- )
- } //for
- // Last year
- yearArr.push(
- '<div class="row year" style="width: ' +
- tools.getCellSize() * scaleUnitsThisYear +
- 'px;"><div class="fn-label">' +
- year +
- '</div></div>'
- )
- // Last month
- monthArr.push(
- '<div class="row month" style="width: ' +
- (tools.getCellSize() * scaleUnitsThisMonth - 1) +
- 'px"><div class="fn-label">' +
- settings.months[month] +
- '</div></div>'
- )
- dataPanel = core.dataPanel(element, dataPanelWidth)
- // Append panel elements
- dataPanel.append(
- $row.clone().html(yearArr.join('')),
- $row.clone().html(monthArr.join('')),
- $row.clone().html(dayArr.join('')),
- $row.clone().html(dowArr.join(''))
- )
- }
- return $('<div class="rightPanel"></div>').append(dataPanel)
- },
- // **Navigation**
- navigation: function(element) {
- var ganttNavigate = null
- // Scrolling navigation is provided by setting
- // `settings.navigate='scroll'`
- if (settings.navigate === 'scroll') {
- ganttNavigate = $('<div class="navigate" />')
- .append(
- $('<div class="nav-slider" />')
- .append(
- $('<div class="nav-slider-left" />')
- .append(
- $('<button type="button" title="上一页" class="nav-link nav-page-back"/>')
- .html('↑')
- .click(function() {
- core.navigatePage(element, -1)
- })
- )
- .append(
- $('<div class="page-number"/>').append(
- $('<span/>').html(element.pageNum + 1 + ' / ' + element.pageCount)
- )
- )
- .append(
- $('<button type="button" title="下一页" class="nav-link nav-page-next"/>')
- .html('↓')
- .click(function() {
- core.navigatePage(element, 1)
- })
- )
- .append(
- $('<button type="button" title="定位到当前时间" class="nav-link nav-now"/>')
- .html('●')
- .click(function() {
- core.navigateTo(element, 'now')
- })
- )
- .append(
- $(
- '<button type="button" title="快速左移查看范围" class="nav-link nav-prev-week"/>'
- )
- .html('<<')
- .click(function() {
- if (settings.scale === 'hours') {
- core.navigateTo(element, tools.getCellSize() * 8)
- } else if (settings.scale === 'days') {
- core.navigateTo(element, tools.getCellSize() * 30)
- } else if (settings.scale === 'weeks') {
- core.navigateTo(element, tools.getCellSize() * 12)
- } else if (settings.scale === 'months') {
- core.navigateTo(element, tools.getCellSize() * 6)
- }
- })
- )
- .append(
- $(
- '<button type="button" title="左移查看范围" class="nav-link nav-prev-day"/>'
- )
- .html('<')
- .click(function() {
- if (settings.scale === 'hours') {
- core.navigateTo(element, tools.getCellSize() * 4)
- } else if (settings.scale === 'days') {
- core.navigateTo(element, tools.getCellSize() * 7)
- } else if (settings.scale === 'weeks') {
- core.navigateTo(element, tools.getCellSize() * 4)
- } else if (settings.scale === 'months') {
- core.navigateTo(element, tools.getCellSize() * 3)
- }
- })
- )
- )
- .append(
- $('<div class="nav-slider-content" />').append(
- $('<div class="nav-slider-bar" />')
- .append($('<a class="nav-slider-button" title="拖动切换查看范围"/>'))
- .mousedown(function(e) {
- e.preventDefault()
- element.scrollNavigation.scrollerMouseDown = true
- core.sliderScroll(element, e)
- })
- .mousemove(function(e) {
- if (element.scrollNavigation.scrollerMouseDown) {
- core.sliderScroll(element, e)
- }
- })
- )
- )
- .append(
- $('<div class="nav-slider-right" />')
- .append(
- $(
- '<button type="button" title="右移查看范围" class="nav-link nav-next-day"/>'
- )
- .html('>')
- .click(function() {
- if (settings.scale === 'hours') {
- core.navigateTo(element, tools.getCellSize() * -4)
- } else if (settings.scale === 'days') {
- core.navigateTo(element, tools.getCellSize() * -7)
- } else if (settings.scale === 'weeks') {
- core.navigateTo(element, tools.getCellSize() * -4)
- } else if (settings.scale === 'months') {
- core.navigateTo(element, tools.getCellSize() * -3)
- }
- })
- )
- .append(
- $(
- '<button type="button" title="快速右移查看范围" class="nav-link nav-next-week"/>'
- )
- .html('>>')
- .click(function() {
- if (settings.scale === 'hours') {
- core.navigateTo(element, tools.getCellSize() * -8)
- } else if (settings.scale === 'days') {
- core.navigateTo(element, tools.getCellSize() * -30)
- } else if (settings.scale === 'weeks') {
- core.navigateTo(element, tools.getCellSize() * -12)
- } else if (settings.scale === 'months') {
- core.navigateTo(element, tools.getCellSize() * -6)
- }
- })
- )
- .append(
- $('<button type="button" class="nav-link nav-zoomIn"/>')
- .html('+')
- .click(function() {
- core.zoomInOut(element, -1)
- })
- )
- .append(
- $('<button type="button" class="nav-link nav-zoomOut"/>')
- .html('-')
- .click(function() {
- core.zoomInOut(element, 1)
- })
- )
- )
- )
- .append(
- $('<div style="display: inline-block;margin-left: 20px;"/>').html('共' + total + '条')
- )
- $('#toToday').click(function() {
- core.navigateTo(element, 'now')
- })
- $('#toDays')
- .unbind()
- .click(function() {
- core.zoomInOut(element, 1)
- })
- $('#toWeeks').click(function() {
- core.zoomInOut(element, 2)
- })
- $('#toMonths').click(function() {
- core.zoomInOut(element, 3)
- })
- $('#totalCount').html(element.rowsNum / 2)
- $(document).mouseup(function() {
- element.scrollNavigation.scrollerMouseDown = false
- })
- // Button navigation is provided by setting `settings.navigation='buttons'`
- } else {
- ganttNavigate = $('<div class="navigate" />')
- .append(
- $('<button type="button" class="nav-link nav-page-back"/>')
- .html('↑')
- .click(function() {
- core.navigatePage(element, -1)
- })
- )
- .append(
- $('<div class="page-number"/>').append(
- $('<span/>').html(element.pageNum + 1 + ' / ' + element.pageCount)
- )
- )
- .append(
- $('<button type="button" class="nav-link nav-page-next"/>')
- .html('↓')
- .click(function() {
- core.navigatePage(element, 1)
- })
- )
- .append(
- $('<button type="button" class="nav-link nav-begin"/>')
- .html('|<')
- .click(function() {
- core.navigateTo(element, 'begin')
- })
- )
- .append(
- $('<button type="button" class="nav-link nav-prev-week"/>')
- .html('<<')
- .click(function() {
- core.navigateTo(element, tools.getCellSize() * 7)
- })
- )
- .append(
- $('<button type="button" class="nav-link nav-prev-day"/>')
- .html('<')
- .click(function() {
- core.navigateTo(element, tools.getCellSize())
- })
- )
- .append(
- $('<button type="button" class="nav-link nav-now"/>')
- .html('●')
- .click(function() {
- core.navigateTo(element, 'now')
- })
- )
- .append(
- $('<button type="button" class="nav-link nav-next-day"/>')
- .html('>')
- .click(function() {
- core.navigateTo(element, tools.getCellSize() * -1)
- })
- )
- .append(
- $('<button type="button" class="nav-link nav-next-week"/>')
- .html('>>')
- .click(function() {
- core.navigateTo(element, tools.getCellSize() * -7)
- })
- )
- .append(
- $('<button type="button" class="nav-link nav-end"/>')
- .html('>|')
- .click(function() {
- core.navigateTo(element, 'end')
- })
- )
- .append(
- $('<button type="button" class="nav-link nav-zoomIn"/>')
- .html('+')
- .click(function() {
- core.zoomInOut(element, -1)
- })
- )
- .append(
- $('<button type="button" class="nav-link nav-zoomOut"/>')
- .html('-')
- .click(function() {
- core.zoomInOut(element, 1)
- })
- )
- }
- return $('<div class="bottom"></div>').append(ganttNavigate)
- },
- // **Progress Bar**
- // Return an element representing a progress of position within the entire chart
- createProgressBar: function(label, desc, classNames, dataObj, itemId) {
- label = label || ''
- var bar = $(
- '<div id="' + itemId + '" class="bar"><div class="fn-label">' + label + '</div></div>'
- ).data('dataObj', dataObj)
- if (desc) {
- bar
- .mouseenter(function(e) {
- if (itemId !== curItemId) {
- //如过进入的不是当前组合,则直接展示新的
- hiddenBar.map(function(bar, index) {
- $(bar).css('top', historyTop)
- })
- hiddenBar = []
- historyTop = null
- }
- isHidden = false
- if (classNames != 'ganttRed' && historyTop == null) {
- // 多个bar重叠时,将重叠的展示出来
- var barList = document.querySelectorAll(
- "[id='" +
- itemId +
- "'].ganttOne,[id='" +
- itemId +
- "'].ganttTwo,[id='" +
- itemId +
- "'].ganttThree"
- )
- var curBar = document.querySelector("[id='" + itemId + "']." + classNames)
- barList.forEach(function(bar) {
- if (
- $(bar).css('left') == $(curBar).css('left') &&
- $(bar)
- .prop('className')
- .indexOf(classNames) == -1
- ) {
- hiddenBar.push(bar)
- }
- })
- if (hiddenBar.length > 0) {
- curItemId = itemId
- historyTop = $(hiddenBar[0]).css('top')
- hiddenBar.map(function(bar, index) {
- $(bar).css(
- 'top',
- parseFloat(historyTop.replace('px', '')) - (hiddenBar.length - index) * 15
- )
- })
- }
- }
- var hint = $('<div class="fn-gantt-hint" />').html(desc)
- $('body').append(hint)
- hint.css('left', e.pageX)
- hint.css('top', e.pageY - 300)
- hint.show()
- })
- .mouseleave(function() {
- isHidden = true
- setTimeout(function() {
- if (isHidden) {
- hiddenBar.map(function(bar, index) {
- $(bar).css('top', historyTop)
- })
- hiddenBar = []
- historyTop = null
- }
- }, 2000)
- $('.fn-gantt-hint').remove()
- })
- .mousemove(function(e) {
- $('.fn-gantt-hint').css('left', e.pageX)
- $('.fn-gantt-hint').css('top', e.pageY + 15)
- })
- }
- if (classNames) {
- bar.addClass(classNames)
- }
- bar.click(function(e) {
- e.stopPropagation()
- settings.onItemClick($(this).data('dataObj'))
- })
- return bar
- },
- // Remove the `wd` (weekday) class and add `today` class to the
- // current day/week/month (depending on the current scale)
- markNow: function(element) {
- var cd = new Date().setHours(0, 0, 0, 0)
- switch (settings.scale) {
- case 'weeks':
- $(element)
- .find(':findweek("' + cd + '")')
- .removeClass('wd')
- .addClass('today')
- break
- case 'months':
- $(element)
- .find(':findmonth("' + cd + '")')
- .removeClass('wd')
- .addClass('today')
- break
- case 'days':
- /* falls through */
- case 'hours':
- /* falls through */
- default:
- $(element)
- .find(':findday("' + cd + '")')
- .removeClass('wd')
- .addClass('today')
- }
- },
- // **Fill the Chart**
- // Parse the data and fill the data panel
- fillData: function(element, datapanel, leftpanel /* <- never used? */) {
- var cellWidth = tools.getCellSize()
- var barOffset = (cellWidth - 18) / 2
- var dataPanelWidth = datapanel.width()
- var invertColor = function(colStr) {
- try {
- colStr = colStr.replace('rgb(', '').replace(')', '')
- var rgbArr = colStr.split(',')
- var R = parseInt(rgbArr[0], 10)
- var G = parseInt(rgbArr[1], 10)
- var B = parseInt(rgbArr[2], 10)
- var gray = Math.round((255 - (0.299 * R + 0.587 * G + 0.114 * B)) * 0.9)
- return 'rgb(' + gray + ', ' + gray + ', ' + gray + ')'
- } catch (err) {
- return ''
- }
- }
- // Loop through the values of each data element and set a row
- var indexNum = 0
- $.each(element.data, function(i, entry) {
- if (
- i >= element.pageNum * settings.itemsPerPage &&
- i < element.pageNum * settings.itemsPerPage + settings.itemsPerPage
- ) {
- $.each(entry.values, function(j, day) {
- var _bar
- var from, to, cFrom, cTo, dFrom, dTo, dl, dp
- var topEl, top
- switch (settings.scale) {
- // **Hourly data**
- case 'hours':
- dFrom = tools.genId(tools.dateDeserialize(day.from), element.scaleStep)
- from = $(element).find('#dh-' + dFrom)
- dTo = tools.genId(tools.dateDeserialize(day.to), element.scaleStep)
- to = $(element).find('#dh-' + dTo)
- cFrom = from.data('offset')
- cTo = to.data('offset')
- dl = Math.floor((cTo - cFrom) / cellWidth) + 1
- dp = (100 * (cellWidth * dl - 1)) / dataPanelWidth
- _bar = core.createProgressBar(
- day.label,
- day.desc,
- day.customClass,
- day.dataObj,
- day.itemId
- )
- // find row
- topEl = $(element).find('#rowheader' + i)
- top = cellWidth * 5 + barOffset + topEl.data('offset')
- _bar.css({
- top: top,
- left: Math.floor(cFrom),
- width: dp + '%',
- display: !cFrom && !cTo ? 'none' : '',
- })
- datapanel.append(_bar)
- break
- // **Weekly data**
- case 'weeks':
- dFrom = tools.dateDeserialize(day.from)
- dTo = tools.dateDeserialize(day.to)
- from = $(element).find('#' + dFrom.getWeekId())
- cFrom = from.data('offset')
- to = $(element).find('#' + dTo.getWeekId())
- cTo = to.data('offset')
- dl = Math.round((cTo - cFrom) / cellWidth) + 1
- dp = (100 * (cellWidth * dl - 1)) / dataPanelWidth
- // 如果没有开始或者结束,则不显示
- if (!cTo | !cFrom) dp = 0
- if (dp < 0) dp = 100
- _bar = core.createProgressBar(
- day.label,
- day.desc,
- day.customClass,
- day.dataObj,
- day.itemId
- )
- // find row
- topEl = $(element).find('#rowheader' + i)
- top = cellWidth * (3 + j) + barOffset + topEl.data('offset') + indexNum * 24
- _bar.css({
- top: top,
- left: Math.floor(cFrom),
- width: dp + '%',
- display: !cFrom && !cTo ? 'none' : '',
- })
- datapanel.append(_bar)
- break
- // **Monthly data**
- case 'months':
- dFrom = tools.dateDeserialize(day.from)
- dTo = tools.dateDeserialize(day.to)
- if (dFrom.getDate() <= 3 && dFrom.getMonth() === 0) {
- dFrom.setDate(dFrom.getDate() + 4)
- }
- if (dFrom.getDate() <= 3 && dFrom.getMonth() === 0) {
- dFrom.setDate(dFrom.getDate() + 4)
- }
- if (dTo.getDate() <= 3 && dTo.getMonth() === 0) {
- dTo.setDate(dTo.getDate() + 4)
- }
- from = $(element).find('#dh-' + tools.genId(dFrom))
- cFrom = from.data('offset')
- to = $(element).find('#dh-' + tools.genId(dTo))
- cTo = to.data('offset')
- dl = Math.round((cTo - cFrom) / cellWidth) + 1
- dp = (100 * (cellWidth * dl - 1)) / dataPanelWidth
- // 如果没有开始或者结束,则不显示
- if (!cTo | !cFrom) dp = 0
- if (dp < 0) dp = 100
- _bar = core.createProgressBar(
- day.label,
- day.desc,
- day.customClass,
- day.dataObj,
- day.itemId
- )
- // find row
- topEl = $(element).find('#rowheader' + i)
- top = cellWidth * (2 + j) + barOffset + topEl.data('offset') + indexNum * 24
- _bar.css({
- top: top,
- left: Math.floor(cFrom) * 3,
- width: dp * 3 + '%',
- display: !cFrom && !cTo ? 'none' : '',
- })
- datapanel.append(_bar)
- break
- // **Days**
- case 'days':
- /* falls through */
- default:
- dFrom = tools.genId(tools.dateDeserialize(day.from))
- dTo = tools.genId(tools.dateDeserialize(day.to))
- from = $(element).find('#dh-' + dFrom)
- cFrom = from.data('offset')
- dl = Math.floor((dTo - dFrom) / UTC_DAY_IN_MS) + 1
- dp = (100 * (cellWidth * dl - 1)) / dataPanelWidth
- _bar = core.createProgressBar(
- day.label,
- day.desc,
- day.customClass,
- day.dataObj,
- day.itemId
- )
- // find row
- topEl = $(element).find('#rowheader' + i)
- top = cellWidth * (4 + j) + barOffset + topEl.data('offset') + indexNum * 24
- _bar.css({
- top: top,
- left: Math.floor(cFrom),
- width: dp + '%',
- display: !cFrom && !cTo ? 'none' : '',
- })
- datapanel.append(_bar)
- }
- var $l = _bar.find('.fn-label')
- if ($l.length) {
- var gray = invertColor(_bar.css('backgroundColor'))
- $l.css('color', gray)
- }
- // if (j === 0) {
- // indexNum++
- // }
- })
- indexNum++
- }
- })
- },
- // **Navigation**
- navigateTo: function(element, val) {
- var $rightPanel = $(element).find('.fn-gantt .rightPanel')
- var $dataPanel = $rightPanel.find('.dataPanel')
- var rightPanelWidth = $rightPanel.width()
- var dataPanelWidth = $dataPanel.width()
- var shift = function() {
- core.repositionLabel(element)
- }
- var maxLeft, curLeft
- switch (val) {
- case 'begin':
- $dataPanel.animate({ left: '0' }, 'fast', shift)
- element.scrollNavigation.panelMargin = 0
- break
- case 'end':
- var pLeft = dataPanelWidth - rightPanelWidth
- element.scrollNavigation.panelMargin = pLeft * -1
- $dataPanel.animate({ left: '-' + pLeft }, 'fast', shift)
- break
- case 'now':
- if (!element.scrollNavigation.canScroll || !$dataPanel.find('.today').length) {
- return false
- }
- maxLeft = (dataPanelWidth - rightPanelWidth) * -1
- curLeft = $dataPanel.css('left').replace('px', '')
- val = $dataPanel.find('.today').offset().left - $dataPanel.offset().left
- val *= -1
- if (val > 0) {
- val = 0
- } else if (val < maxLeft) {
- val = maxLeft
- }
- $dataPanel.animate({ left: val }, 'fast', shift)
- element.scrollNavigation.panelMargin = val
- break
- default:
- maxLeft = (dataPanelWidth - rightPanelWidth) * -1
- curLeft = $dataPanel.css('left').replace('px', '')
- val = parseInt(curLeft, 10) + val
- if (val <= 0 && val >= maxLeft) {
- $dataPanel.animate({ left: val }, 'fast', shift)
- }
- element.scrollNavigation.panelMargin = val
- }
- core.synchronizeScroller(element)
- },
- // Navigate to a specific page
- navigatePage: function(element, val) {
- if (
- element.pageNum + val >= 0 &&
- element.pageNum + val < Math.ceil(element.rowsNum / settings.itemsPerPage)
- ) {
- core.waitToggle(element, function() {
- element.pageNum += val
- element.hPosition = $('.fn-gantt .dataPanel')
- .css('left')
- .replace('px', '')
- element.scaleOldWidth = false
- core.init(element)
- })
- }
- },
- // Change zoom level
- zoomInOut: function(element, val) {
- core.waitToggle(element, function() {
- var scale = settings.scale
- var headerRows = element.headerRows
- var scaleSt = element.scaleStep
- if (val == 1) {
- scale = 'days'
- headerRows = 4
- scaleSt = 13
- }
- if (val == 2) {
- scale = 'weeks'
- headerRows = 3
- scaleSt = 13
- }
- if (val == 3) {
- scale = 'months'
- headerRows = 2
- scaleSt = 14
- }
- /* var zoomIn = (val < 0);
- var scaleSt = element.scaleStep + val * 3;
- scaleSt = scaleSt <= 1 ? 1 : scaleSt === 4 ? 3 : scaleSt;
- var scale = settings.scale;
- var headerRows = element.headerRows;
- if (settings.scale === "hours" && scaleSt >= 13) {
- scale = "days";
- headerRows = 4;
- scaleSt = 13;
- } else if (settings.scale === "days" && zoomIn) {
- scale = "hours";
- headerRows = 5;
- scaleSt = 12;
- } else if (settings.scale === "days" && !zoomIn) {
- scale = "weeks";
- headerRows = 3;
- scaleSt = 13;
- } else if (settings.scale === "weeks" && !zoomIn) {
- scale = "months";
- headerRows = 2;
- scaleSt = 14;
- } else if (settings.scale === "weeks" && zoomIn) {
- scale = "days";
- headerRows = 4;
- scaleSt = 13;
- } else if (settings.scale === "months" && zoomIn) {
- scale = "weeks";
- headerRows = 3;
- scaleSt = 13;
- }
- // do nothing if attempting to zoom past max/min
- if ((zoomIn && $.inArray(scale, scales) < $.inArray(settings.minScale, scales)) ||
- (!zoomIn && $.inArray(scale, scales) > $.inArray(settings.maxScale, scales))) {
- core.init(element);
- return;
- }*/
- element.scaleStep = scaleSt
- settings.scale = scale
- element.headerRows = headerRows
- var $rightPanel = $(element).find('.fn-gantt .rightPanel')
- var $dataPanel = $rightPanel.find('.dataPanel')
- element.hPosition = $dataPanel.css('left').replace('px', '')
- element.scaleOldWidth = $dataPanel.width() - $rightPanel.width()
- if (settings.useCookie) {
- $.cookie(settings.cookieKey + 'CurrentScale', settings.scale)
- // reset scrollPos
- $.cookie(settings.cookieKey + 'ScrollPos', null)
- }
- core.init(element)
- })
- },
- // Move chart via mouseclick
- mouseScroll: function(element, e) {
- var $dataPanel = $(element).find('.fn-gantt .dataPanel')
- $dataPanel.css('cursor', 'move')
- var bPos = $dataPanel.offset()
- var mPos =
- element.scrollNavigation.mouseX === null ? e.pageX : element.scrollNavigation.mouseX
- var delta = e.pageX - mPos
- element.scrollNavigation.mouseX = e.pageX
- core.scrollPanel(element, delta)
- clearTimeout(element.scrollNavigation.repositionDelay)
- element.scrollNavigation.repositionDelay = setTimeout(core.repositionLabel, 50, element)
- },
- // Move chart via mousewheel
- wheelScroll: function(element, e) {
- e.preventDefault() // e is a jQuery Event
- // attempts to normalize scroll wheel velocity
- var delta =
- 'detail' in e
- ? e.detail
- : 'wheelDelta' in e.originalEvent
- ? (-1 / 120) * e.originalEvent.wheelDelta
- : e.originalEvent.deltaY
- ? e.originalEvent.deltaY / Math.abs(e.originalEvent.deltaY)
- : e.originalEvent.detail
- // simpler normalization, ignoring per-device/browser/platform acceleration & semantic variations
- //var delta = e.detail || - (e = e.originalEvent).wheelData || e.deltaY /* || e.deltaX */ || e.detail;
- //delta = ( delta / Math.abs(delta) ) || 0;
- core.scrollPanel(element, -50 * delta)
- clearTimeout(element.scrollNavigation.repositionDelay)
- element.scrollNavigation.repositionDelay = setTimeout(core.repositionLabel, 50, element)
- },
- // Move chart via slider control
- sliderScroll: function(element, e) {
- var $sliderBar = $(element).find('.nav-slider-bar')
- var $sliderBarBtn = $sliderBar.find('.nav-slider-button')
- var $rightPanel = $(element).find('.fn-gantt .rightPanel')
- var $dataPanel = $rightPanel.find('.dataPanel')
- var bPos = $sliderBar.offset()
- var bWidth = $sliderBar.width()
- var wButton = $sliderBarBtn.width()
- var pos, pLeft
- if (e.pageX >= bPos.left && e.pageX <= bPos.left + bWidth) {
- pos = e.pageX - bPos.left
- pos = pos - wButton / 2
- $sliderBarBtn.css('left', pos)
- pLeft = $dataPanel.width() - $rightPanel.width()
- var pPos = ((pos * pLeft) / bWidth) * -1
- if (pPos >= 0) {
- $dataPanel.css('left', '0')
- element.scrollNavigation.panelMargin = 0
- } else if (pos >= bWidth - wButton * 1) {
- $dataPanel.css('left', pLeft * -1)
- element.scrollNavigation.panelMargin = pLeft * -1
- } else {
- $dataPanel.css('left', pPos)
- element.scrollNavigation.panelMargin = pPos
- }
- clearTimeout(element.scrollNavigation.repositionDelay)
- element.scrollNavigation.repositionDelay = setTimeout(core.repositionLabel, 5, element)
- }
- },
- // Update scroll panel margins
- scrollPanel: function(element, delta) {
- if (!element.scrollNavigation.canScroll) {
- return false
- }
- var _panelMargin = parseInt(element.scrollNavigation.panelMargin, 10) + delta
- if (_panelMargin > 0) {
- element.scrollNavigation.panelMargin = 0
- $(element)
- .find('.fn-gantt .dataPanel')
- .css('left', element.scrollNavigation.panelMargin)
- } else if (_panelMargin < element.scrollNavigation.panelMaxPos * -1) {
- element.scrollNavigation.panelMargin = element.scrollNavigation.panelMaxPos * -1
- $(element)
- .find('.fn-gantt .dataPanel')
- .css('left', element.scrollNavigation.panelMargin)
- } else {
- element.scrollNavigation.panelMargin = _panelMargin
- $(element)
- .find('.fn-gantt .dataPanel')
- .css('left', element.scrollNavigation.panelMargin)
- }
- core.synchronizeScroller(element)
- },
- // Synchronize scroller
- synchronizeScroller: function(element) {
- if (settings.navigate !== 'scroll') {
- return
- }
- var $rightPanel = $(element).find('.fn-gantt .rightPanel')
- var $dataPanel = $rightPanel.find('.dataPanel')
- var $sliderBar = $(element).find('.nav-slider-bar')
- var $sliderBtn = $sliderBar.find('.nav-slider-button')
- var bWidth = $sliderBar.width()
- var wButton = $sliderBtn.width()
- var pLeft = $dataPanel.width() - $rightPanel.width()
- var hPos = $dataPanel.css('left') || 0
- if (hPos) {
- hPos = hPos.replace('px', '')
- }
- var pos = (hPos * bWidth) / pLeft - $sliderBtn.width() * 0.25
- pos =
- pos > 0 ? 0 : pos * -1 >= bWidth - wButton * 0.75 ? (bWidth - wButton * 1.25) * -1 : pos
- $sliderBtn.css('left', pos * -1)
- },
- // Reposition data labels
- repositionLabel: function(element) {
- setTimeout(function() {
- var $dataPanel
- if (!element) {
- $dataPanel = $('.fn-gantt .rightPanel .dataPanel')
- } else {
- var $rightPanel = $(element).find('.fn-gantt .rightPanel')
- $dataPanel = $rightPanel.find('.dataPanel')
- }
- if (settings.useCookie) {
- $.cookie(settings.cookieKey + 'ScrollPos', $dataPanel.css('left').replace('px', ''))
- }
- }, 500)
- },
- // waitToggle
- waitToggle: function(element, showCallback) {
- if ($.isFunction(showCallback)) {
- var $elt = $(element)
- var eo = $elt.offset()
- var ew = $elt.outerWidth()
- var eh = $elt.outerHeight()
- if (!element.loader) {
- element.loader = $(
- '<div class="fn-gantt-loader">' +
- '<div class="fn-gantt-loader-spinner"><span>' +
- settings.waitText +
- '</span></div></div>'
- )
- }
- $elt.append(element.loader)
- setTimeout(showCallback, 500)
- } else if (element.loader) {
- element.loader.detach()
- }
- },
- }
- // Utility functions
- // =================
- var tools = {
- // Return the maximum available date in data depending on the scale
- getMaxDate: function(element) {
- var maxDate = null
- $.each(element.data, function(i, entry) {
- $.each(entry.values, function(i, date) {
- maxDate =
- maxDate < tools.dateDeserialize(date.to) ? tools.dateDeserialize(date.to) : maxDate
- })
- })
- maxDate = maxDate || new Date()
- var bd
- bd = new Date(maxDate.getTime())
- maxDate = new Date(bd.getFullYear() + 1, 2, 31)
- /*switch (settings.scale) {
- case "hours":
- maxDate.setHours(Math.ceil((maxDate.getHours()) / element.scaleStep) * element.scaleStep);
- maxDate.setHours(maxDate.getHours() + element.scaleStep * 3);
- break;
- case "weeks":
- // wtf is happening here?
- bd = new Date(maxDate.getTime());
- bd = new Date(bd.setDate(bd.getDate() + 3 * 7));
- var md = Math.floor(bd.getDate() / 7) * 7;
- maxDate = new Date(bd.getFullYear(), bd.getMonth(), md === 0 ? 4 : md - 3);
- break;
- case "months":
- bd = new Date(maxDate.getFullYear(), maxDate.getMonth(), 1);
- bd.setMonth(bd.getMonth() + 2);
- maxDate = new Date(bd.getFullYear(), bd.getMonth(), 1);
- break;
- case "days":
- falls through
- default:
- maxDate.setHours(0);
- maxDate.setDate(maxDate.getDate() + 3);
- }*/
- return maxDate
- },
- // Return the minimum available date in data depending on the scale
- getMinDate: function(element) {
- var minDate = null
- $.each(element.data, function(i, entry) {
- $.each(entry.values, function(i, date) {
- minDate =
- minDate > tools.dateDeserialize(date.from) || minDate === null
- ? tools.dateDeserialize(date.from)
- : minDate
- })
- })
- minDate = minDate || new Date()
- var bd = null
- bd = new Date(minDate.getTime())
- minDate = new Date(bd.getFullYear() - 1, 9, 1)
- /* switch (settings.scale) {
- case "hours":
- minDate.setHours(Math.floor((minDate.getHours()) / element.scaleStep) * element.scaleStep);
- minDate.setHours(minDate.getHours() - element.scaleStep * 3);
- break;
- case "weeks":
- // wtf is happening here?
- var bd = new Date(minDate.getTime());
- bd = new Date(bd.setDate(bd.getDate() - 3 * 7));
- var md = Math.floor(bd.getDate() / 7) * 7;
- minDate = new Date(bd.getFullYear(), bd.getMonth(), md === 0 ? 4 : md - 3);
- break;
- case "months":
- minDate.setHours(0, 0, 0, 0);
- minDate.setDate(1);
- minDate.setMonth(minDate.getMonth() - 3);
- break;
- case "days":
- falls through
- default:
- minDate.setHours(0, 0, 0, 0);
- minDate.setDate(minDate.getDate() - 3);
- }*/
- return minDate
- },
- // Return an array of Date objects between `from` and `to`
- parseDateRange: function(from, to) {
- var current = new Date(from.getTime())
- var ret = []
- var i = 0
- do {
- ret[i++] = new Date(current.getTime())
- current.setDate(current.getDate() + 1)
- } while (current <= to)
- return ret
- },
- // Return an array of Date objects between `from` and `to`,
- // scaled hourly
- parseTimeRange: function(from, to, scaleStep) {
- var current = new Date(from)
- var end = new Date(to)
- // GR: Fix begin
- current.setHours(0, 0, 0, 0)
- end.setMilliseconds(0)
- end.setSeconds(0)
- if (end.getMinutes() > 0 || end.getHours() > 0) {
- end.setMinutes(0)
- end.setHours(0)
- end.setTime(end.getTime() + UTC_DAY_IN_MS)
- }
- // GR: Fix end
- var ret = []
- var i = 0
- for (;;) {
- var dayStartTime = new Date(current)
- dayStartTime.setHours(Math.floor(current.getHours() / scaleStep) * scaleStep)
- if (ret[i] && dayStartTime.getDay() !== ret[i].getDay()) {
- // If mark-cursor jumped to next day, make sure it starts at 0 hours
- dayStartTime.setHours(0)
- }
- ret[i] = dayStartTime
- // Note that we use ">" because we want to include the end-time point.
- if (current > to) {
- break
- }
- /* BUG-2: current is moved backwards producing a dead-lock! (crashes chrome/IE/firefox)
- * SEE: https://github.com/taitems/jQuery.Gantt/issues/62
- if (current.getDay() !== ret[i].getDay()) {
- current.setHours(0);
- }
- */
- // GR Fix Begin
- current = ktkGetNextDate(dayStartTime, scaleStep)
- // GR Fix End
- i++
- }
- return ret
- },
- // Return an array of Date objects between a range of weeks
- // between `from` and `to`
- parseWeeksRange: function(from, to) {
- var current = from.getDayForWeek()
- var ret = []
- var i = 0
- do {
- ret[i++] = current.getDayForWeek()
- current.setDate(current.getDate() + 7)
- } while (current <= to)
- return ret
- },
- // Return an array of Date objects between a range of months
- // between `from` and `to`
- parseMonthsRange: function(from, to) {
- var current = new Date(from)
- var end = new Date(to) // <- never used?
- var ret = []
- var i = 0
- do {
- ret[i++] = new Date(current.getFullYear(), current.getMonth(), 1)
- current.setMonth(current.getMonth() + 1)
- } while (current <= to)
- return ret
- },
- // Deserialize a date from a string or integer
- dateDeserialize: function(date) {
- if (typeof date === 'string') {
- date = date.replace(/\/Date\((.*)\)\//, '$1')
- date = $.isNumeric(date) ? parseInt(date, 10) : $.trim(date)
- }
- return new Date(date)
- },
- // Generate an id for a date
- genId: function(t) {
- // varargs
- if ($.isNumeric(t)) {
- t = new Date(t)
- }
- switch (settings.scale) {
- case 'hours':
- var hour = t.getHours()
- if (arguments.length >= 2) {
- hour = Math.floor(t.getHours() / arguments[1]) * arguments[1]
- }
- return new Date(t.getFullYear(), t.getMonth(), t.getDate(), hour).getTime()
- case 'weeks':
- var y = t.getFullYear()
- var w = t.getWeekOfYear()
- var m = t.getMonth()
- if (m === 11 && w === 1) {
- y++
- } else if (!m && w > 51) {
- y--
- }
- return y + '-' + w
- case 'months':
- return t.getFullYear() + '-' + t.getMonth()
- case 'days':
- /* falls through */
- default:
- return new Date(t.getFullYear(), t.getMonth(), t.getDate()).getTime()
- }
- },
- // normalizes an array of dates into a map of start-of-day millisecond values
- _datesToDays: function(dates) {
- var dayMap = {}
- for (var i = 0, len = dates.length, day; i < len; i++) {
- day = tools.dateDeserialize(dates[i])
- dayMap[day.setHours(0, 0, 0, 0)] = true
- }
- return dayMap
- },
- // Returns true when the given date appears in the array of holidays, if provided
- isHoliday: (function() {
- // IIFE
- // short-circuits the function if no holidays option was passed
- if (!settings.holidays || !settings.holidays.length) {
- return function() {
- return false
- }
- }
- var holidays = false
- // returns the function that will be used to check for holidayness of a given date
- return function(date) {
- if (!holidays) {
- holidays = tools._datesToDays(settings.holidays)
- }
- return !!holidays[
- // assumes numeric dates are already normalized to start-of-day
- $.isNumeric(date)
- ? date
- : new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime()
- ]
- }
- })(),
- // Get the current cell height
- getCellSize: function() {
- if (typeof tools._getCellSize === 'undefined') {
- var measure = $(
- '<div style="display: none; position: absolute;" class="fn-gantt"><div class="row"></div></div>'
- )
- $('body').append(measure)
- tools._getCellSize = measure.find('.row').height()
- measure.empty().remove()
- }
- return tools._getCellSize
- },
- // Get the current page height
- getPageHeight: function(element) {
- return element.pageNum + 1 === element.pageCount
- ? element.rowsOnLastPage * tools.getCellSize()
- : settings.itemsPerPage * tools.getCellSize()
- },
- }
- this.each(function() {
- this.data = null // Received data
- this.pageNum = 0 // Current page number
- this.pageCount = 0 // Available pages count
- this.rowsOnLastPage = 0 // How many rows on last page
- this.rowsNum = 0 // Number of total rows
- this.hPosition = 0 // Current position on diagram (Horizontal)
- this.dateStart = null
- this.dateEnd = null
- this.scrollClicked = false
- this.scaleOldWidth = null
- this.headerRows = null
- // Update cookie with current scale
- if (settings.useCookie) {
- var sc = $.cookie(settings.cookieKey + 'CurrentScale')
- if (sc) {
- settings.scale = sc
- } else {
- $.cookie(settings.cookieKey + 'CurrentScale', settings.scale)
- }
- }
- switch (settings.scale) {
- //case "hours":
- // this.headerRows = 5;
- // this.scaleStep = 8;
- // break;
- case 'hours':
- this.headerRows = 5
- this.scaleStep = 1
- break
- case 'weeks':
- this.headerRows = 3
- this.scaleStep = 13
- break
- case 'months':
- this.headerRows = 2
- this.scaleStep = 14
- break
- case 'days':
- /* falls through */
- default:
- this.headerRows = 4
- this.scaleStep = 13
- }
- this.scrollNavigation = {
- panelMouseDown: false,
- scrollerMouseDown: false,
- mouseX: null,
- panelMargin: 0,
- repositionDelay: 0,
- panelMaxPos: 0,
- canScroll: true,
- }
- this.gantt = null
- this.loader = null
- core.create(this)
- })
- }
- })(jQuery)
|