X-Git-Url: http://git.roojs.org/?p=roojs1;a=blobdiff_plain;f=roojs-calendar-debug.js;h=2854206bacd5a1b8d8370706093a94acd3d55cd5;hp=82e30ea6f961333a166988288545a71c45fbd9f1;hb=fc32d3336ffe6a4ac93549dab21fd04b7d7056d3;hpb=fbb4ca0089561cae5daea8a2576e777e8fa51397 diff --git a/roojs-calendar-debug.js b/roojs-calendar-debug.js index 82e30ea6f9..2854206bac 100644 --- a/roojs-calendar-debug.js +++ b/roojs-calendar-debug.js @@ -9,6 +9,8 @@ Roo.bootstrap = Roo.bootstrap || {}; /** * @class Roo.bootstrap.Component * @extends Roo.Component + * @abstract + * @children Roo.bootstrap.Component * Bootstrap Component base class * @cfg {String} cls css class * @cfg {String} style any extra css @@ -16,7 +18,10 @@ Roo.bootstrap = Roo.bootstrap || {}; * @cfg {Boolean} can_build_overlaid True if element can be rebuild from a HTML page * @cfg {string} dataId cutomer id * @cfg {string} name Specifies name attribute - * + * @cfg {string} tooltip Text for the tooltip + * @cfg {string} container_method method to fetch parents container element (used by NavHeaderbar - getHeaderChildContainer) + * @cfg {string|object} visibilityEl (el|parent) What element to use for visibility (@see getVisibilityEl()) + * @constructor * Do not use directly - it does not do anything.. * @param {Object} config The config object @@ -26,6 +31,20 @@ Roo.bootstrap = Roo.bootstrap || {}; Roo.bootstrap.Component = function(config){ Roo.bootstrap.Component.superclass.constructor.call(this, config); + + this.addEvents({ + /** + * @event childrenrendered + * Fires when the children have been rendered.. + * @param {Roo.bootstrap.Component} this + */ + "childrenrendered" : true + + + + }); + + }; Roo.extend(Roo.bootstrap.Component, Roo.BoxComponent, { @@ -39,7 +58,11 @@ Roo.extend(Roo.bootstrap.Component, Roo.BoxComponent, { autoCreate : false, - initEvents : function() { }, + tooltip : null, + /** + * Initialize Events for the element + */ + initEvents : function() { }, xattr : false, @@ -47,6 +70,8 @@ Roo.extend(Roo.bootstrap.Component, Roo.BoxComponent, { can_build_overlaid : true, + container_method : false, + dataId : false, name : false, @@ -79,7 +104,8 @@ Roo.extend(Roo.bootstrap.Component, Roo.BoxComponent, { var cfg = Roo.apply({}, this.getAutoCreate()); - cfg.id = Roo.id(); + + cfg.id = this.id || Roo.id(); // fill in the extra attributes if (this.xattr && typeof(this.xattr) =='object') { @@ -93,11 +119,11 @@ Roo.extend(Roo.bootstrap.Component, Roo.BoxComponent, { } if (this.cls) { - cfg.cls = (typeof(cfg.cls) == 'undefined') ? this.cls : cfg.cls + ' ' + this.cls; + cfg.cls = (typeof(cfg.cls) == 'undefined' ? this.cls : cfg.cls) + ' ' + this.cls; } if (this.style) { // fixme needs to support more complex style data. - cfg.style = this.style; + cfg.style = (typeof(cfg.style) == 'undefined' ? this.style : cfg.style) + '; ' + this.style; } if(this.name){ @@ -106,30 +132,54 @@ Roo.extend(Roo.bootstrap.Component, Roo.BoxComponent, { this.el = ct.createChild(cfg, position); + if (this.tooltip) { + this.tooltipEl().attr('tooltip', this.tooltip); + } + if(this.tabIndex !== undefined){ this.el.dom.setAttribute('tabIndex', this.tabIndex); } + this.initEvents(); - }, - + /** + * Fetch the element to add children to + * @return {Roo.Element} defaults to this.el + */ getChildContainer : function() { return this.el; }, + getDocumentBody : function() // used by menus - as they are attached to the body so zIndexes work + { + return Roo.get(document.body); + }, - + /** + * Fetch the element to display the tooltip on. + * @return {Roo.Element} defaults to this.el + */ + tooltipEl : function() + { + return this.el; + }, + addxtype : function(tree,cntr) { var cn = this; cn = Roo.factory(tree); + //Roo.log(['addxtype', cn]); cn.parentType = this.xtype; //?? cn.parentId = this.id; - cntr = typeof(cntr == 'undefined' ) ? 'getChildContainer' : cntr; + cntr = (typeof(cntr) == 'undefined' ) ? 'getChildContainer' : cntr; + if (typeof(cn.container_method) == 'string') { + cntr = cn.container_method; + } + var has_flexy_each = (typeof(tree['flexy:foreach']) != 'undefined'); @@ -141,11 +191,16 @@ Roo.extend(Roo.bootstrap.Component, Roo.BoxComponent, { var page_has_body = (Roo.get(document.body).attr('xtype') == 'Roo.bootstrap.Body'); - var self_cntr_el = Roo.get(this[cntr]()); + var self_cntr_el = Roo.get(this[cntr](false)); + + // do not try and build conditional elements + if ((has_flexy_each || has_flexy_if || this.can_build_overlaid == false ) && build_from_html) { + return false; + } if (!has_flexy_each || !build_from_html || is_body || !page_has_body) { if(!has_flexy_if || typeof(tree.name) == 'undefined' || !build_from_html || is_body || !page_has_body){ - return this.addxtypeChild(tree,cntr); + return this.addxtypeChild(tree,cntr, is_body); } var echild =self_cntr_el ? self_cntr_el.child('>*[name=' + tree.name + ']') : false; @@ -160,7 +215,12 @@ Roo.extend(Roo.bootstrap.Component, Roo.BoxComponent, { } var ret = false; + if (!build_from_html) { + return false; + } + // this i think handles overlaying multiple children of the same type + // with the sam eelement.. - which might be buggy.. while (true) { var echild =self_cntr_el ? self_cntr_el.child('>*[xtype]') : false; @@ -174,24 +234,33 @@ Roo.extend(Roo.bootstrap.Component, Roo.BoxComponent, { ret = this.addxtypeChild(Roo.apply({}, tree),cntr); } + return ret; }, - addxtypeChild : function (tree, cntr) + + addxtypeChild : function (tree, cntr, is_body) { + Roo.debug && Roo.log('addxtypeChild:' + cntr); var cn = this; - cntr = typeof(cntr == 'undefined' ) ? 'getChildContainer' : cntr; + cntr = (typeof(cntr) == 'undefined' ) ? 'getChildContainer' : cntr; var has_flexy = (typeof(tree['flexy:if']) != 'undefined') || (typeof(tree['flexy:foreach']) != 'undefined'); + - - + skip_children = false; // render the element if it's not BODY. - if (tree.xtype != 'Body') { - var test = Roo.factory(tree); + if (!is_body) { + + // if parent was disabled, then do not try and create the children.. + if(!this[cntr](true)){ + tree.items = []; + return tree; + } + cn = Roo.factory(tree); cn.parentType = this.xtype; //?? @@ -204,10 +273,19 @@ Roo.extend(Roo.bootstrap.Component, Roo.BoxComponent, { // that match this xtype.. // note - when we render we create these as well.. // so we should check to see if body has xtype set. - if (Roo.get(document.body).attr('xtype') == 'Roo.bootstrap.Body') { + if (build_from_html && Roo.get(document.body).attr('xtype') == 'Roo.bootstrap.Body') { - var self_cntr_el = Roo.get(this[cntr]()); + var self_cntr_el = Roo.get(this[cntr](false)); var echild =self_cntr_el ? self_cntr_el.child('>*[xtype]') : false; + if (echild) { + //Roo.log(Roo.XComponent.build_from_html); + //Roo.log("got echild:"); + //Roo.log(echild); + } + // there is a scenario where some of the child elements are flexy:if (and all of the same type) + // and are not displayed -this causes this to use up the wrong element when matching. + // at present the only work around for this is to nest flexy:if elements in another element that is always rendered. + if (echild && echild.attr('xtype').split('.').pop() == cn.xtype) { // Roo.log("found child for " + this.xtype +": " + echild.attr('xtype') ); @@ -218,59 +296,136 @@ Roo.extend(Roo.bootstrap.Component, Roo.BoxComponent, { // Roo.log("GOT"); //echild.dom.removeAttribute('xtype'); } else { - Roo.log("MISSING " + cn.xtype + " on child of " + (this.el ? this.el.attr('xbuilderid') : 'no parent')); - + Roo.debug && Roo.log("MISSING " + cn.xtype + " on child of " + (this.el ? this.el.attr('xbuilderid') : 'no parent')); + Roo.debug && Roo.log(self_cntr_el); + Roo.debug && Roo.log(echild); + Roo.debug && Roo.log(cn); } } - + // if object has flexy:if - then it may or may not be rendered. if (build_from_html && has_flexy && !cn.el && cn.can_build_overlaid) { // skip a flexy if element. - Roo.log('skipping render'); + Roo.debug && Roo.log('skipping render'); + Roo.debug && Roo.log(tree); + if (!cn.el) { + Roo.debug && Roo.log('skipping all children'); + skip_children = true; + } + } else { // actually if flexy:foreach is found, we really want to create // multiple copies here... + //Roo.log('render'); + //Roo.log(this[cntr]()); + // some elements do not have render methods.. like the layouts... + /* + if(this[cntr](true) === false){ + cn.items = []; + return cn; + } + */ + cn.render && cn.render(this[cntr](true)); - cn.render(this[cntr]()); } // then add the element.. } - - + // handle the kids.. var nitems = []; + /* if (typeof (tree.menu) != 'undefined') { tree.menu.parentType = cn.xtype; tree.menu.triggerEl = cn.el; nitems.push(cn.addxtype(Roo.apply({}, tree.menu))); } - + */ if (!tree.items || !tree.items.length) { cn.items = nitems; + //Roo.log(["no children", this]); + return cn; } + var items = tree.items; delete tree.items; //Roo.log(items.length); // add the items.. - for(var i =0;i < items.length;i++) { - nitems.push(cn.addxtype(Roo.apply({}, items[i]))); + if (!skip_children) { + for(var i =0;i < items.length;i++) { + // Roo.log(['add child', items[i]]); + nitems.push(cn.addxtype(Roo.apply({}, items[i]))); + } } - + cn.items = nitems; - + + //Roo.log("fire childrenrendered"); + + cn.fireEvent('childrenrendered', this); + return cn; - } - + }, + /** + * Set the element that will be used to show or hide + */ + setVisibilityEl : function(el) + { + this.visibilityEl = el; + }, + /** + * Get the element that will be used to show or hide + */ + getVisibilityEl : function() + { + if (typeof(this.visibilityEl) == 'object') { + return this.visibilityEl; + } + + if (typeof(this.visibilityEl) == 'string') { + return this.visibilityEl == 'parent' ? this.parent().getEl() : this.getEl(); + } + + return this.getEl(); + }, + /** + * Show a component - removes 'hidden' class + */ + show : function() + { + if(!this.getVisibilityEl()){ + return; + } + + this.getVisibilityEl().removeClass(['hidden','d-none']); + + this.fireEvent('show', this); + + + }, + /** + * Hide a component - adds 'hidden' class + */ + hide: function() + { + if(!this.getVisibilityEl()){ + return; + } + + this.getVisibilityEl().addClass(['hidden','d-none']); + + this.fireEvent('hide', this); + + } }); /* @@ -285,7 +440,9 @@ Roo.bootstrap = Roo.bootstrap || {}; * @class Roo.bootstrap.Calendar * @extends Roo.bootstrap.Component * Bootstrap Calendar class - + * @cfg {Boolean} loadMask (true|false) default false + * @cfg {Object} header generate the user specific header of the calendar, default false + * @constructor * Create a new Container * @param {Object} config The config object @@ -338,11 +495,20 @@ Roo.bootstrap.Calendar = function(config){ Roo.extend(Roo.bootstrap.Calendar, Roo.bootstrap.Component, { + /** + * @cfg {Roo.data.Store} store + * The data source for the calendar + */ + store : false, /** * @cfg {Number} startDay * Day index at which the week should begin, 0-based (defaults to 0, which is Sunday) */ startDay : 0, + + loadMask : false, + + header : false, getAutoCreate : function(){ @@ -360,58 +526,64 @@ Roo.extend(Roo.bootstrap.Calendar, Roo.bootstrap.Component, { }); }; - var header = { - tag : 'table', - cls : 'fc-header', - style : 'width:100%', - cn : [ - { - tag: 'tr', - cn : [ - { - tag : 'td', - cls : 'fc-header-left', - cn : [ - fc_button('prev', 'left', 'arrow', '‹' ), - fc_button('next', 'right', 'arrow', '›' ), - { tag: 'span', cls: 'fc-header-space' }, - fc_button('today', 'left right', '', 'today' ) // neds state disabled.. - - - ] - }, - - { - tag : 'td', - cls : 'fc-header-center', - cn : [ - { - tag: 'span', - cls: 'fc-header-title', - cn : { - tag: 'H2', - html : 'month / year' + var header = {}; + + if(!this.header){ + header = { + tag : 'table', + cls : 'fc-header', + style : 'width:100%', + cn : [ + { + tag: 'tr', + cn : [ + { + tag : 'td', + cls : 'fc-header-left', + cn : [ + fc_button('prev', 'left', 'arrow', '‹' ), + fc_button('next', 'right', 'arrow', '›' ), + { tag: 'span', cls: 'fc-header-space' }, + fc_button('today', 'left right', '', 'today' ) // neds state disabled.. + + + ] + }, + + { + tag : 'td', + cls : 'fc-header-center', + cn : [ + { + tag: 'span', + cls: 'fc-header-title', + cn : { + tag: 'H2', + html : 'month / year' + } } - } - - ] - }, - { - tag : 'td', - cls : 'fc-header-right', - cn : [ - /* fc_button('month', 'left', '', 'month' ), - fc_button('week', '', '', 'week' ), - fc_button('day', 'right', '', 'day' ) - */ - - ] - } - - ] - } - ] - }; + + ] + }, + { + tag : 'td', + cls : 'fc-header-right', + cn : [ + /* fc_button('month', 'left', '', 'month' ), + fc_button('week', '', '', 'week' ), + fc_button('day', 'right', '', 'day' ) + */ + + ] + } + + ] + } + ] + }; + } + + header = this.header; var cal_heads = function() { @@ -461,7 +633,7 @@ Roo.extend(Roo.bootstrap.Calendar, Roo.bootstrap.Component, { }; var cal_rows = function() { - var ret = [] + var ret = []; for (var r = 0; r < 6; r++) { var row= { tag : 'tr', @@ -550,8 +722,40 @@ Roo.extend(Roo.bootstrap.Calendar, Roo.bootstrap.Component, { throw "can not find store for calendar"; } + var mark = { + tag: "div", + cls:"x-dlg-mask", + style: "text-align:center", + cn: [ + { + tag: "div", + style: "background-color:white;width:50%;margin:250 auto", + cn: [ + { + tag: "img", + src: Roo.rootURL + '/images/ux/lightbox/loading.gif' + }, + { + tag: "span", + html: "Loading" + } + + ] + } + ] + }; + this.maskEl = Roo.DomHelper.append(this.el.select('.fc-content', true).first(), mark, true); + + var size = this.el.select('.fc-content', true).first().getSize(); + this.maskEl.setSize(size.width, size.height); + this.maskEl.enableDisplayMode("block"); + if(!this.loadMask){ + this.maskEl.hide(); + } + this.store = Roo.factory(this.store, Roo.data); this.store.on('load', this.onLoad, this); + this.store.on('beforeload', this.onBeforeLoad, this); this.resize(); @@ -671,7 +875,9 @@ Roo.extend(Roo.bootstrap.Calendar, Roo.bootstrap.Component, { var format = this.format; var setCellClass = function(cal, cell){ - + cell.row = 0; + cell.events = []; + cell.more = []; //Roo.log('set Cell Class'); cell.title = ""; var t = d.getTime(); @@ -822,16 +1028,16 @@ Roo.extend(Roo.bootstrap.Calendar, Roo.bootstrap.Component, { return ret; }, - findBestRow: function(cells) - { - var ret = 0; - - for (var i =0 ; i < cells.length;i++) { - ret = Math.max(cells[i].rows || 0,ret); - } - return ret; - - }, +// findBestRow: function(cells) +// { +// var ret = 0; +// +// for (var i =0 ; i < cells.length;i++) { +// ret = Math.max(cells[i].rows || 0,ret); +// } +// return ret; +// +// }, addItem : function(ev) @@ -839,13 +1045,20 @@ Roo.extend(Roo.bootstrap.Calendar, Roo.bootstrap.Component, { // look for vertical location slot in var cells = this.findCells(ev); - ev.row = this.findBestRow(cells); +// ev.row = this.findBestRow(cells); // work out the location. var crow = false; var rows = []; for(var i =0; i < cells.length; i++) { + + cells[i].row = cells[0].row; + + if(i == 0){ + cells[i].row = cells[i].row + 1; + } + if (!crow) { crow = { start : cells[i], @@ -871,10 +1084,8 @@ Roo.extend(Roo.bootstrap.Calendar, Roo.bootstrap.Component, { ev.els = []; ev.rows = rows; ev.cells = cells; - for (var i = 0; i < cells.length;i++) { - cells[i].rows = Math.max(cells[i].rows || 0 , ev.row + 1 ); - - } + + cells[0].events.push(ev); this.calevents.push(ev); }, @@ -886,7 +1097,9 @@ Roo.extend(Roo.bootstrap.Calendar, Roo.bootstrap.Component, { } Roo.each(this.cells.elements, function(c){ - c.rows = 0; + c.row = 0; + c.events = []; + c.more = []; }); Roo.each(this.calevents, function(e) { @@ -897,82 +1110,154 @@ Roo.extend(Roo.bootstrap.Calendar, Roo.bootstrap.Component, { },this); },this); + Roo.each(Roo.select('.fc-more-event', true).elements, function(e){ + e.remove(); + }); + }, renderEvents: function() { - // first make sure there is enough space.. + var _this = this; this.cells.each(function(c) { - - c.select('.fc-day-content div',true).first().setHeight(Math.max(34, c.rows * 20)); + + if(c.row < 5){ + return; + } + + var ev = c.events; + + var r = 4; + if(c.row != c.events.length){ + r = 4 - (4 - (c.row - c.events.length)); + } + + c.events = ev.slice(0, r); + c.more = ev.slice(r); + + if(c.more.length && c.more.length == 1){ + c.events.push(c.more.pop()); + } + + c.row = (c.row - ev.length) + c.events.length + ((c.more.length) ? 1 : 0); + }); - - for (var e = 0; e < this.calevents.length; e++) { - var ev = this.calevents[e]; - var cells = ev.cells; - var rows = ev.rows; - for(var i =0; i < rows.length; i++) { + this.cells.each(function(c) { + + c.select('.fc-day-content div',true).first().setHeight(Math.max(34, c.row * 20)); + + + for (var e = 0; e < c.events.length; e++){ + var ev = c.events[e]; + var rows = ev.rows; - - // how many rows should it span.. + for(var i = 0; i < rows.length; i++) { - var cfg = { - cls : 'roo-dynamic fc-event fc-event-hori fc-event-draggable ui-draggable', - style : 'position: absolute', // left: 387px; width: 121px; top: 359px; + // how many rows should it span.. + + var cfg = { + cls : 'roo-dynamic fc-event fc-event-hori fc-event-draggable ui-draggable', + style : 'position: absolute', // left: 387px; width: 121px; top: 359px; + + unselectable : "on", + cn : [ + { + cls: 'fc-event-inner', + cn : [ + // { + // tag:'span', + // cls: 'fc-event-time', + // html : cells.length > 1 ? '' : ev.time + // }, + { + tag:'span', + cls: 'fc-event-title', + html : String.format('{0}', ev.title) + } + + + ] + }, + { + cls: 'ui-resizable-handle ui-resizable-e', + html : '   ' + } + + ] + }; + + if (i == 0) { + cfg.cls += ' fc-event-start'; + } + if ((i+1) == rows.length) { + cfg.cls += ' fc-event-end'; + } + + var ctr = _this.el.select('.fc-event-container',true).first(); + var cg = ctr.createChild(cfg); + + var sbox = rows[i].start.select('.fc-day-content',true).first().getBox(); + var ebox = rows[i].end.select('.fc-day-content',true).first().getBox(); + + var r = (c.more.length) ? 1 : 0; + cg.setXY([sbox.x +2, sbox.y + ((c.row - c.events.length - r + e) * 20)]); + cg.setWidth(ebox.right - sbox.x -2); + + cg.on('mouseenter' ,_this.onEventEnter, _this, ev); + cg.on('mouseleave' ,_this.onEventLeave, _this, ev); + cg.on('click', _this.onEventClick, _this, ev); + + ev.els.push(cg); + } + + } + + + if(c.more.length){ + var cfg = { + cls : 'fc-more-event roo-dynamic fc-event fc-event-hori fc-event-draggable ui-draggable fc-event-start fc-event-end', + style : 'position: absolute', unselectable : "on", cn : [ { cls: 'fc-event-inner', cn : [ - { - tag:'span', - cls: 'fc-event-time', - html : cells.length > 1 ? '' : ev.time - }, { tag:'span', cls: 'fc-event-title', - html : String.format('{0}', ev.title) + html : 'More' } - - + + ] }, { cls: 'ui-resizable-handle ui-resizable-e', html : '   ' } - + ] }; - if (i == 0) { - cfg.cls += ' fc-event-start'; - } - if ((i+1) == rows.length) { - cfg.cls += ' fc-event-end'; - } - - var ctr = this.el.select('.fc-event-container',true).first(); + + var ctr = _this.el.select('.fc-event-container',true).first(); var cg = ctr.createChild(cfg); - - cg.on('mouseenter' ,this.onEventEnter, this, ev); - cg.on('mouseleave' ,this.onEventLeave, this, ev); - cg.on('click', this.onEventClick, this, ev); - - ev.els.push(cg); - - var sbox = rows[i].start.select('.fc-day-content',true).first().getBox(); - var ebox = rows[i].end.select('.fc-day-content',true).first().getBox(); + + var sbox = c.select('.fc-day-content',true).first().getBox(); + var ebox = c.select('.fc-day-content',true).first().getBox(); //Roo.log(cg); - cg.setXY([sbox.x +2, sbox.y +(ev.row * 20)]); + cg.setXY([sbox.x +2, sbox.y +((c.row - 1) * 20)]); cg.setWidth(ebox.right - sbox.x -2); + + cg.on('click', _this.onMoreEventClick, _this, c.more); + } - - } + }); + + }, @@ -992,19 +1277,43 @@ Roo.extend(Roo.bootstrap.Calendar, Roo.bootstrap.Component, { this.store.load(); }, - onLoad: function () { + onMoreEventClick: function(e, el, more) + { + var _this = this; - this.clearEvents(); - //Roo.log('calendar onload'); -// + this.calpopover.placement = 'right'; + this.calpopover.setTitle('More'); + + this.calpopover.setContent(''); + + var ctr = this.calpopover.el.select('.popover-content', true).first(); + + Roo.each(more, function(m){ + var cfg = { + cls : 'fc-event-hori fc-event-draggable', + html : m.title + }; + var cg = ctr.createChild(cfg); + + cg.on('click', _this.onEventClick, _this, m); + }); + + this.calpopover.show(el); + + + }, + + onLoad: function () + { this.calevents = []; var cal = this; + if(this.store.getCount() > 0){ this.store.data.each(function(d){ cal.addItem({ id : d.data.id, - start: new Date(d.data.start_dt), - end : new Date(d.data.end_dt), + start: (typeof(d.data.start_dt) === 'string') ? new Date.parseDate(d.data.start_dt, 'Y-m-d H:i:s') : d.data.start_dt, + end : (typeof(d.data.end_dt) === 'string') ? new Date.parseDate(d.data.end_dt, 'Y-m-d H:i:s') : d.data.end_dt, time : d.data.start_time, title : d.data.title, description : d.data.description, @@ -1014,6 +1323,18 @@ Roo.extend(Roo.bootstrap.Calendar, Roo.bootstrap.Component, { } this.renderEvents(); + + if(this.calevents.length && this.loadMask){ + this.maskEl.hide(); + } + }, + + onBeforeLoad: function() + { + this.clearEvents(); + if(this.loadMask){ + this.maskEl.show(); + } } });