X-Git-Url: http://git.roojs.org/?a=blobdiff_plain;f=roojs-bootstrap-debug.js;h=9e39fb86ca80ef3682e6b2aaa6f9e8c2b526ddf2;hb=5a09638750d76b5c2f42753ab924401909761f61;hp=d571ae007d3b5394337f4bdd7dc5c251fea9da8a;hpb=46cc346126636f08ed5012230381afd7aa6c703b;p=roojs1 diff --git a/roojs-bootstrap-debug.js b/roojs-bootstrap-debug.js index d571ae007d..9e39fb86ca 100644 --- a/roojs-bootstrap-debug.js +++ b/roojs-bootstrap-debug.js @@ -330,11 +330,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){ @@ -362,6 +362,11 @@ Roo.extend(Roo.bootstrap.Component, Roo.BoxComponent, { { 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 @@ -650,6 +655,8 @@ Roo.extend(Roo.bootstrap.Component, Roo.BoxComponent, { * @cfg {String} cls class of the element * @cfg {Boolean} preventDefault (true|false) default false * @cfg {Boolean} clickable (true|false) default false + * @cfg {String} role default blank - set to button to force cursor pointer + * * @constructor * Create a new Element @@ -667,7 +674,9 @@ Roo.bootstrap.Element = function(config){ * @param {Roo.bootstrap.Element} this * @param {Roo.EventObject} e */ - "click" : true + "click" : true + + }); }; @@ -678,6 +687,8 @@ Roo.extend(Roo.bootstrap.Element, Roo.bootstrap.Component, { html: '', preventDefault: false, clickable: false, + tapedTwice : false, + role : false, getAutoCreate : function(){ @@ -686,6 +697,9 @@ Roo.extend(Roo.bootstrap.Element, Roo.bootstrap.Component, { // cls: this.cls, double assign in parent class Component.js :: onRender html: this.html }; + if (this.role !== false) { + cfg.role = this.role; + } return cfg; }, @@ -698,6 +712,7 @@ Roo.extend(Roo.bootstrap.Element, Roo.bootstrap.Component, { this.el.on('click', this.onClick, this); } + }, onClick : function(e) @@ -706,9 +721,14 @@ Roo.extend(Roo.bootstrap.Element, Roo.bootstrap.Component, { e.preventDefault(); } - this.fireEvent('click', this, e); + this.fireEvent('click', this, e); // why was this double click before? }, + + + + + getValue : function() { return this.el.dom.innerHTML; @@ -1354,6 +1374,7 @@ Roo.extend(Roo.bootstrap.Button, Roo.bootstrap.Component, { { this.disabled = false; this.el.removeClass('disabled'); + this.el.dom.removeAttribute("disabled"); }, /** @@ -1363,6 +1384,7 @@ Roo.extend(Roo.bootstrap.Button, Roo.bootstrap.Component, { { this.disabled = true; this.el.addClass('disabled'); + this.el.attr("disabled", "disabled") }, /** * sets the active state on/off, @@ -2015,12 +2037,19 @@ Roo.bootstrap.Card = function(config){ /** * @event rotate * When a element a card is rotate - * @param {Roo.bootstrap.Element} this + * @param {Roo.bootstrap.Card} this * @param {Roo.Element} n the node being dropped? * @param {Boolean} rotate status */ - 'rotate' : true - + 'rotate' : true, + /** + * @event cardover + * When a card element is dragged over ready to drop (return false to block dropable) + * @param {Roo.bootstrap.Card} this + * @param {Object} data from dragdrop + */ + 'cardover' : true + }); }; @@ -2075,6 +2104,8 @@ Roo.extend(Roo.bootstrap.Card, Roo.bootstrap.Component, { bodyEl: false, // card-body headerContainerEl : false, // headerEl : false, + header_imageEl : false, + layoutCls : function() { @@ -2285,7 +2316,7 @@ Roo.extend(Roo.bootstrap.Card, Roo.bootstrap.Component, { }, getCardImageTop : function() { - var ret = this.el.select('.card-img-top',true).first(); + var ret = this.header_imageEl; if (ret.hasClass('d-none')) { ret.removeClass('d-none'); } @@ -2331,17 +2362,19 @@ Roo.extend(Roo.bootstrap.Card, Roo.bootstrap.Component, { if (this.rotateable) { this.el.select('.card-header',true).on('click', this.onToggleRotate, this); } - this.collapsableEl = this.el.select('.roo-collapsable').first(); + this.collapsableEl = this.el.select('.roo-collapsable',true).first(); - this.footerEl = this.el.select('.card-footer').first(); - this.collapsableToggleEl = this.el.select('.roo-collapse-toggle'); - this.headerContainerEl = this.el.select('.roo-card-header-ctr').first(); + this.footerEl = this.el.select('.card-footer',true).first(); + this.collapsableToggleEl = this.el.select('.roo-collapse-toggle',true).first(); + this.headerContainerEl = this.el.select('.roo-card-header-ctr',true).first(); this.headerEl = this.el.select('.card-header',true).first(); if (this.rotated) { this.el.addClass('roo-card-rotated'); this.fireEvent('rotate', this, true); } + this.header_imageEl = this.el.select('.card-img-top',true).first(); + this.header_imageEl.on('load', this.onHeaderImageLoad, this ); }, getDragData : function(e) @@ -2369,6 +2402,17 @@ Roo.extend(Roo.bootstrap.Card, Roo.bootstrap.Component, { /** * Part of the Roo.dd.DropZone interface. If no target node is found, the * whole Element becomes the target, and this causes the drop gesture to append. + * + * Returns an object: + * { + + position : 'below' or 'above' + card : relateive to card OBJECT (or true for no cards listed) + items_n : relative to nth item in list + card_n : relative to nth card in list + } + * + * */ getTargetFromEvent : function(e, dragged_card_el) { @@ -2462,7 +2506,11 @@ Roo.extend(Roo.bootstrap.Card, Roo.bootstrap.Component, { } Roo.log(['getTargetFromEvent', target_info ]); - + + if (this.fireEvent('cardover', this, [ data ]) === false) { + return false; + } + this.dropPlaceHolder('show', target_info,data); return false; @@ -2487,9 +2535,7 @@ Roo.extend(Roo.bootstrap.Card, Roo.bootstrap.Component, { } this.dropPlaceHolder('hide'); - - - + this.acceptCard(data.source, info.position, info.card, info.items_n); return true; @@ -2679,7 +2725,31 @@ Roo.extend(Roo.bootstrap.Card, Roo.bootstrap.Component, { }, setHeaderText: function(html) { - this.headerContainerEl.dom.innerHTML = html; + this.header = html; + if (this.headerContainerEl) { + this.headerContainerEl.dom.innerHTML = html; + } + }, + onHeaderImageLoad : function(ev, he) + { + if (!this.header_image_fit_square) { + return; + } + + var hw = he.naturalHeight / he.naturalWidth; + // wide image = < 0 + // tall image = > 1 + //var w = he.dom.naturalWidth; + var ww = he.width; + he.style.left = 0; + he.style.position = 'relative'; + if (hw > 1) { + var nw = (ww * (1/hw)); + Roo.get(he).setSize( ww * (1/hw), ww); + he.style.left = ((ww - nw)/ 2) + 'px'; + he.style.position = 'relative'; + } + } @@ -2783,6 +2853,174 @@ Roo.extend(Roo.bootstrap.CardImageTop, Roo.bootstrap.Element, { + +/* +* Licence: LGPL +*/ + +/** + * @class Roo.bootstrap.ButtonUploader + * @extends Roo.bootstrap.Button + * Bootstrap Button Uploader class - it's a button which when you add files to it + * + * + * @cfg {Number} errorTimeout default 3000 + * @cfg {Array} images an array of ?? Img objects ??? when loading existing files.. + * @cfg {Array} html The button text. + * @cfg {Boolean} multiple (default true) Should the upload allow multiple files to be uploaded. + * + * @constructor + * Create a new CardUploader + * @param {Object} config The config object + */ + +Roo.bootstrap.ButtonUploader = function(config){ + + + + Roo.bootstrap.ButtonUploader.superclass.constructor.call(this, config); + + + this.addEvents({ + // raw events + /** + * @event beforeselect + * When button is pressed, before show upload files dialog is shown + * @param {Roo.bootstrap.UploaderButton} this + * + */ + 'beforeselect' : true, + /** + * @event fired when files have been selected, + * When a the download link is clicked + * @param {Roo.bootstrap.UploaderButton} this + * @param {Array} Array of files that have been uploaded + */ + 'uploaded' : true + + }); +}; + +Roo.extend(Roo.bootstrap.ButtonUploader, Roo.bootstrap.Button, { + + + errorTimeout : 3000, + + images : false, + + fileCollection : false, + allowBlank : true, + + multiple : true, + + getAutoCreate : function() + { + var im = { + tag: 'input', + type : 'file', + cls : 'd-none roo-card-upload-selector' + + }; + if (this.multiple) { + im.multiple = 'multiple'; + } + + return { + cls :'div' , + cn : [ + Roo.bootstrap.Button.prototype.getAutoCreate.call(this), + im + + ] + }; + + + }, + + + initEvents : function() + { + + Roo.bootstrap.Button.prototype.initEvents.call(this); + + + + + + this.urlAPI = (window.createObjectURL && window) || + (window.URL && URL.revokeObjectURL && URL) || + (window.webkitURL && webkitURL); + + + + + this.selectorEl = this.el.select('.roo-card-upload-selector', true).first(); + + this.selectorEl.on('change', this.onFileSelected, this); + + + + }, + + + onClick : function(e) + { + e.preventDefault(); + + if ( this.fireEvent('beforeselect', this) === false) { + return; + } + + this.selectorEl.dom.click(); + + }, + + onFileSelected : function(e) + { + e.preventDefault(); + + if(typeof(this.selectorEl.dom.files) == 'undefined' || !this.selectorEl.dom.files.length){ + return; + } + var files = Array.prototype.slice.call(this.selectorEl.dom.files); + this.selectorEl.dom.value = '';// hopefully reset.. + + this.fireEvent('uploaded', this, files ); + + }, + + + + + /** + * addCard - add an Attachment to the uploader + * @param data - the data about the image to upload + * + * { + id : 123 + title : "Title of file", + is_uploaded : false, + src : "http://.....", + srcfile : { the File upload object }, + mimetype : file.type, + preview : false, + is_deleted : 0 + .. any other data... + } + * + * + */ + + reset: function() + { + + this.selectorEl + } + + + + +}); /* * - LGPL * @@ -2805,6 +3043,7 @@ Roo.extend(Roo.bootstrap.CardImageTop, Roo.bootstrap.Element, { * @cfg {String} smUrl sm image source * @cfg {String} mdUrl md image source * @cfg {String} lgUrl lg image source + * @cfg {Boolean} backgroundContain (use style background and contain image in content) * * @constructor * Create a new Input @@ -2821,7 +3060,13 @@ Roo.bootstrap.Img = function(config){ * The img click event for the img. * @param {Roo.EventObject} e */ - "click" : true + "click" : true, + /** + * @event load + * The when any image loads + * @param {Roo.EventObject} e + */ + "load" : true }); }; @@ -2836,6 +3081,7 @@ Roo.extend(Roo.bootstrap.Img, Roo.bootstrap.Component, { smUrl: '', mdUrl: '', lgUrl: '', + backgroundContain : false, getAutoCreate : function() { @@ -2908,12 +3154,20 @@ Roo.extend(Roo.bootstrap.Img, Roo.bootstrap.Component, { tag: 'img', cls: (this.imgResponsive) ? 'img-responsive' : '', html : null, - src : 'about:blank' // just incase src get's set to undefined?!? + src : Roo.BLANK_IMAGE_URL // just incase src get's set to undefined?!? }; + if (this.backgroundContain) { + cfg.cls += ' background-contain'; + } + cfg.html = this.html || cfg.html; - cfg.src = this.src || cfg.src; + if (this.backgroundContain) { + cfg.style="background-image: url(" + this.src + ')'; + } else { + cfg.src = this.src || cfg.src; + } if (['rounded','circle','thumbnail'].indexOf(this.border)>-1) { cfg.cls += ' img-' + this.border; @@ -2946,6 +3200,12 @@ Roo.extend(Roo.bootstrap.Img, Roo.bootstrap.Component, { if(!this.href){ this.el.on('click', this.onClick, this); } + if(this.src || (!this.xsUrl && !this.smUrl && !this.mdUrl && !this.lgUrl)){ + this.el.on('load', this.onImageLoad, this); + } else { + // not sure if this works.. not tested + this.el.select('img', true).on('load', this.onImageLoad, this); + } }, @@ -2954,6 +3214,12 @@ Roo.extend(Roo.bootstrap.Img, Roo.bootstrap.Component, { Roo.log('img onclick'); this.fireEvent('click', this, e); }, + onImageLoad: function(e) + { + Roo.log('img load'); + this.fireEvent('load', this, e); + }, + /** * Sets the url of the image - used to update it * @param {String} url the url of the image @@ -2964,7 +3230,11 @@ Roo.extend(Roo.bootstrap.Img, Roo.bootstrap.Component, { this.src = url; if(this.src || (!this.xsUrl && !this.smUrl && !this.mdUrl && !this.lgUrl)){ - this.el.dom.src = url; + if (this.backgroundContain) { + this.el.dom.style.backgroundImage = 'url(' + url + ')'; + } else { + this.el.dom.src = url; + } return; } @@ -3341,7 +3611,9 @@ Roo.bootstrap.MenuMgr = function(){ * @cfg {bool} hidden if the menu should be hidden when rendered. * @cfg {bool} stopEvent (true|false) Stop event after trigger press (default true) * @cfg {bool} isLink (true|false) the menu has link disable auto expand and collaspe (default false) - * + * @cfg {bool} hideTrigger (true|false) default false - hide the carret for trigger. + * @cfg {String} align default tl-bl? == below - how the menu should be aligned. + * @constructor * Create a new Menu * @param {Object} config The config object @@ -3349,6 +3621,13 @@ Roo.bootstrap.MenuMgr = function(){ Roo.bootstrap.Menu = function(config){ + + if (config.type == 'treeview') { + // normally menu's are drawn attached to the document to handle layering etc.. + // however treeview (used by the docs menu is drawn into the parent element) + this.container_method = 'getChildContainer'; + } + Roo.bootstrap.Menu.superclass.constructor.call(this, config); if (this.registerMenu && this.type != 'treeview') { Roo.bootstrap.MenuMgr.register(this); @@ -3418,7 +3697,7 @@ Roo.bootstrap.Menu = function(config){ Roo.extend(Roo.bootstrap.Menu, Roo.bootstrap.Component, { /// html : false, - //align : '', + triggerEl : false, // is this set by component builder? -- it should really be fetched from parent()??? type: false, /** @@ -3436,6 +3715,13 @@ Roo.extend(Roo.bootstrap.Menu, Roo.bootstrap.Component, { isLink : false, + container_method : 'getDocumentBody', // so the menu is rendered on the body and zIndex works. + + hideTrigger : false, + + align : 'tl-bl?', + + getChildContainer : function() { return this.el; }, @@ -3445,11 +3731,10 @@ Roo.extend(Roo.bootstrap.Menu, Roo.bootstrap.Component, { //if (['right'].indexOf(this.align)!==-1) { // cfg.cn[1].cls += ' pull-right' //} - - + var cfg = { tag : 'ul', - cls : 'dropdown-menu' , + cls : 'dropdown-menu shadow' , style : 'z-index:1000' }; @@ -3467,18 +3752,22 @@ Roo.extend(Roo.bootstrap.Menu, Roo.bootstrap.Component, { // Roo.log("ADD event"); // Roo.log(this.triggerEl.dom); + if (this.triggerEl) { + + this.triggerEl.on('click', this.onTriggerClick, this); + + this.triggerEl.on(Roo.isTouch ? 'touchstart' : 'mouseup', this.onTriggerPress, this); + + if (!this.hideTrigger) { + if (this.triggerEl.hasClass('nav-item') && this.triggerEl.select('.nav-link',true).length) { + // dropdown toggle on the 'a' in BS4? + this.triggerEl.select('.nav-link',true).first().addClass('dropdown-toggle'); + } else { + this.triggerEl.addClass('dropdown-toggle'); + } + } + } - this.triggerEl.on('click', this.onTriggerClick, this); - - this.triggerEl.on(Roo.isTouch ? 'touchstart' : 'mouseup', this.onTriggerPress, this); - - - if (this.triggerEl.hasClass('nav-item')) { - // dropdown toggle on the 'a' in BS4? - this.triggerEl.select('.nav-link',true).first().addClass('dropdown-toggle'); - } else { - this.triggerEl.addClass('dropdown-toggle'); - } if (Roo.isTouch) { this.el.on('touchstart' , this.onTouch, this); } @@ -3596,8 +3885,31 @@ Roo.extend(Roo.bootstrap.Menu, Roo.bootstrap.Component, { if(!this.el){ this.render(); } + this.el.addClass('show'); // show otherwise we do not know how big we are.. + + var xy = this.el.getAlignToXY(el, pos); + + // bl-tl << left align below + // tl-bl << left align + + if(this.el.getWidth() + xy[0] >= Roo.lib.Dom.getViewWidth()){ + // if it goes to far to the right.. -> align left. + xy = this.el.getAlignToXY(el, this.align.replace('/l/g', 'r')) + } + if(xy[0] < 0){ + // was left align - go right? + xy = this.el.getAlignToXY(el, this.align.replace('/r/g', 'l')) + } + + // goes down the bottom + if(this.el.getHeight() + xy[1] >= Roo.lib.Dom.getViewHeight() || + xy[1] < 0 ){ + var a = this.align.replace('?', '').split('-'); + xy = this.el.getAlignToXY(el, a[1] + '-' + a[0] + '?') + + } - this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign), parentMenu, false); + this.showAt( xy , parentMenu, false); }, /** * Displays this menu at a specific xy position @@ -3617,18 +3929,17 @@ Roo.extend(Roo.bootstrap.Menu, Roo.bootstrap.Component, { //this.el.show(); this.hideMenuItems(); this.hidden = false; - this.triggerEl.addClass('open'); + if (this.triggerEl) { + this.triggerEl.addClass('open'); + } + this.el.addClass('show'); + + // reassign x when hitting right - if(this.el.getWidth() + xy[0] >= Roo.lib.Dom.getViewWidth()){ - xy[0] = xy[0] - this.el.getWidth() + this.triggerEl.getWidth(); - } // reassign y when hitting bottom - if(this.el.getHeight() + xy[1] >= Roo.lib.Dom.getViewHeight()){ - xy[1] = xy[1] - this.el.getHeight() - this.triggerEl.getHeight(); - } // but the list may align on trigger left or trigger top... should it be a properity? @@ -3660,9 +3971,9 @@ Roo.extend(Roo.bootstrap.Menu, Roo.bootstrap.Component, { hide : function(deep) { if (false === this.fireEvent("beforehide", this)) { - Roo.log("hide canceled"); - return; - } + Roo.log("hide canceled"); + return; + } this.hideMenuItems(); if(this.el && this.isVisible()){ @@ -3670,8 +3981,11 @@ Roo.extend(Roo.bootstrap.Menu, Roo.bootstrap.Component, { this.activeItem.deactivate(); this.activeItem = null; } - this.triggerEl.removeClass('open');; - this.el.removeClass('show'); + if (this.triggerEl) { + this.triggerEl.removeClass('open'); + } + + this.el.removeClass('show'); this.hidden = true; this.fireEvent("hide", this); } @@ -3716,7 +4030,8 @@ Roo.extend(Roo.bootstrap.Menu, Roo.bootstrap.Component, { this.hide(); } else { Roo.log('show'); - this.show(this.triggerEl, '?', false); + + this.show(this.triggerEl, this.align, false); } if(this.stopEvent || e.getTarget().nodeName.toLowerCase() === 'i'){ @@ -6125,8 +6440,10 @@ Roo.extend(Roo.bootstrap.NavItem, Roo.bootstrap.Component, { cfg.href = this.href; } if (this.fa) { - cfg.html = ' ' + this.html + ''; - } + cfg.html = ' ' + this.html + ''; + } else { + cfg.cls += " nav-html"; + } // menu .. should add dropdown-menu class - so no need for carat.. @@ -6142,7 +6459,8 @@ Roo.extend(Roo.bootstrap.NavItem, Roo.bootstrap.Component, { { tag: this.tagtype, href : this.href || "#", - html: this.html || '' + html: this.html || '', + cls : '' } ]; if (this.tagtype == 'a') { @@ -6150,23 +6468,21 @@ Roo.extend(Roo.bootstrap.NavItem, Roo.bootstrap.Component, { } if (this.icon) { - cfg.cn[0].html = ' ' + cfg.cn[0].html + ''; - } - if (this.fa) { - cfg.cn[0].html = ' ' + cfg.cn[0].html + ''; - } - if(this.glyphicon) { + cfg.cn[0].html = ' ' + cfg.cn[0].html + ''; + } else if (this.fa) { + cfg.cn[0].html = ' ' + cfg.cn[0].html + ''; + } else if(this.glyphicon) { cfg.cn[0].html = ' ' + cfg.cn[0].html; - } + } else { + cfg.cn[0].cls += " nav-html"; + } if (this.menu) { - cfg.cn[0].html += " "; } if (this.badge !== '') { - cfg.cn[0].html += ' ' + this.badge + ''; } } @@ -6184,6 +6500,7 @@ Roo.extend(Roo.bootstrap.NavItem, Roo.bootstrap.Component, { var ret = Roo.bootstrap.NavItem.superclass.onRender.call(this, ct, position); this.navLink = this.el.select('.nav-link',true).first(); + this.htmlEl = this.el.hasClass('nav-html') ? this.el : this.el.select('.nav-html',true).first(); return ret; }, @@ -6381,7 +6698,17 @@ Roo.extend(Roo.bootstrap.NavItem, Roo.bootstrap.Component, { Roo.get(c).scrollTo('top', options.value, true); return; - } + }, + /** + * Set the HTML (text content) of the item + * @param {string} html content for the nav item + */ + setHtml : function(html) + { + this.html = html; + this.htmlEl.dom.innerHTML = html; + + } }); @@ -7010,30 +7337,15 @@ Roo.grid.ColumnModel = function(config){ /** * The config passed into the constructor */ - this.config = config; + this.config = []; //config; this.lookup = {}; // if no id, create one // if the column does not have a dataIndex mapping, // map it to the order it is in the config for(var i = 0, len = config.length; i < len; i++){ - var c = config[i]; - if(typeof c.dataIndex == "undefined"){ - c.dataIndex = i; - } - if(typeof c.renderer == "string"){ - c.renderer = Roo.util.Format[c.renderer]; - } - if(typeof c.id == "undefined"){ - c.id = Roo.id(); - } - if(c.editor && c.editor.xtype){ - c.editor = Roo.factory(c.editor, Roo.grid); - } - if(c.editor && c.editor.isFormField){ - c.editor = new Roo.grid.GridEditor(c.editor); - } - this.lookup[c.id] = c; + this.addColumn(config[i]); + } /** @@ -7175,7 +7487,7 @@ Roo.extend(Roo.grid.ColumnModel, Roo.util.Observable, { /** - * Returns the column for a specified dataIndex. + * Returns the column Object for a specified dataIndex. * @param {String} dataIndex The column dataIndex * @return {Object|Boolean} the column or false if not found */ @@ -7501,7 +7813,35 @@ Roo.extend(Roo.grid.ColumnModel, Roo.util.Observable, { */ setEditor : function(col, editor){ this.config[col].editor = editor; + }, + /** + * Add a column (experimental...) - defaults to adding to the end.. + * @param {Object} config + */ + addColumn : function(c) + { + + var i = this.config.length; + this.config[i] = c; + + if(typeof c.dataIndex == "undefined"){ + c.dataIndex = i; + } + if(typeof c.renderer == "string"){ + c.renderer = Roo.util.Format[c.renderer]; + } + if(typeof c.id == "undefined"){ + c.id = Roo.id(); + } + if(c.editor && c.editor.xtype){ + c.editor = Roo.factory(c.editor, Roo.grid); + } + if(c.editor && c.editor.isFormField){ + c.editor = new Roo.grid.GridEditor(c.editor); + } + this.lookup[c.id] = c; } + }); Roo.grid.ColumnModel.defaultRenderer = function(value) @@ -7962,11 +8302,10 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { - var _this = this; Roo.each(this.el.select('thead th.sortable', true).elements, function(e){ - e.on('click', _this.sort, _this); - }); + e.on('click', this.sort, this); + }, this); this.mainBody.on("click", this.onClick, this); this.mainBody.on("dblclick", this.onDblClick, this); @@ -8137,15 +8476,14 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { var rowIndex = this.getRowIndex(row); // why??? - should these not be based on SelectionModel? - if(this.cellSelection){ + //if(this.cellSelection){ this.fireEvent('cellclick', this, cell, rowIndex, cellIndex, e); - } + //} - if(this.rowSelection){ + //if(this.rowSelection){ this.fireEvent('rowclick', this, row, rowIndex, e); - } - - + //} + }, onDblClick : function(e,el) @@ -8193,7 +8531,7 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { var sort = col.attr('sort'); var dir = 'ASC'; - if(col.select('i', true).first().hasClass('glyphicon-arrow-up')){ + if(col.select('i', true).first().hasClass('fa-arrow-up')){ dir = 'DESC'; } @@ -8226,14 +8564,21 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { tag: 'th', cls : 'x-hcol-' + i, style : '', + html: cm.getColumnHeader(i) }; + var tooltip = cm.getColumnTooltip(i); + if (tooltip) { + c.tooltip = tooltip; + } + + var hh = ''; if(typeof(config.sortable) != 'undefined' && config.sortable){ c.cls = 'sortable'; - c.html = '' + c.html; + c.html = '' + c.html; } // could use BS4 hidden-..-down @@ -8368,15 +8713,15 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { var ds = this.store; Roo.each(this.el.select('thead th.sortable', true).elements, function(e){ - e.select('i', true).removeClass(['glyphicon-arrow-up', 'glyphicon-arrow-down']); + e.select('i', true).removeClass(['fa-arrow-up', 'fa-arrow-down']); if (_this.store.sortInfo) { if(e.hasClass('sortable') && e.attr('sort') == _this.store.sortInfo.field && _this.store.sortInfo.direction.toUpperCase() == 'ASC'){ - e.select('i', true).addClass(['glyphicon-arrow-up']); + e.select('i', true).addClass(['fa-arrow-up']); } if(e.hasClass('sortable') && e.attr('sort') == _this.store.sortInfo.field && _this.store.sortInfo.direction.toUpperCase() == 'DESC'){ - e.select('i', true).addClass(['glyphicon-arrow-down']); + e.select('i', true).addClass(['fa-arrow-down']); } } }); @@ -8574,6 +8919,9 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { var td = { tag: 'td', + // this might end up displaying HTML? + // this is too messy... - better to only do it on columsn you know are going to be too long + //tooltip : (typeof(value) === 'object') ? '' : value, cls : rowcfg.rowClass + ' x-col-' + i, style: '', html: (typeof(value) === 'object') ? '' : value @@ -8800,6 +9148,12 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { this.mainHead.remove(); this.mainHead = table.createChild(header, this.mainBody, false); + + Roo.each(this.el.select('thead th.sortable', true).elements, function(e){ + e.on('click', this.sort, this); + }, this); + + }, onHiddenChange : function(colModel, colIndex, hidden) @@ -10493,7 +10847,14 @@ Roo.bootstrap.Input = function(config){ * @param {Roo.form.Field} this * @param {Roo.EventObject} e The event Object */ - keyup : true + keyup : true, + /** + * @event paste + * Fires after the user pastes into input + * @param {Roo.form.Field} this + * @param {Roo.EventObject} e The event Object + */ + paste : true }); }; @@ -10857,7 +11218,7 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component, { } if(this.labelWidth < 13 && this.labelmd == 0){ - this.labelmd = this.labelWidth; + this.labellg = this.labellg > 0 ? this.labellg : this.labelWidth; } if(this.labellg > 0){ @@ -10996,6 +11357,7 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component, { this.inputEl().on("blur", this.onBlur, this); this.inputEl().relayEvent('keyup', this); + this.inputEl().relayEvent('paste', this); this.indicator = this.indicatorEl(); @@ -12496,11 +12858,29 @@ Roo.bootstrap.CardUploader = function(config){ this.fileCollection = new Roo.util.MixedCollection(false,function(r) { return r.data.id - }); - + }); + this.addEvents({ + // raw events + /** + * @event preview + * When a image is clicked on - and needs to display a slideshow or similar.. + * @param {Roo.bootstrap.Card} this + * @param {Object} The image information data + * + */ + 'preview' : true, + /** + * @event download + * When a the download link is clicked + * @param {Roo.bootstrap.Card} this + * @param {Object} The image information data contains + */ + 'download' : true + + }); }; - + Roo.extend(Roo.bootstrap.CardUploader, Roo.bootstrap.Input, { @@ -12528,6 +12908,7 @@ Roo.extend(Roo.bootstrap.CardUploader, Roo.bootstrap.Input, { { tag: 'input', type : 'hidden', + name : this.name, value : this.value, cls : 'd-none form-control' }, @@ -12659,14 +13040,34 @@ Roo.extend(Roo.bootstrap.CardUploader, Roo.bootstrap.Input, { id : Roo.bootstrap.CardUploader.ID--, is_uploaded : false, src : url, + srcfile : file, title : file.name, mimetype : file.type, preview : false, is_deleted : 0 - }) + }); }, + /** + * addCard - add an Attachment to the uploader + * @param data - the data about the image to upload + * + * { + id : 123 + title : "Title of file", + is_uploaded : false, + src : "http://.....", + srcfile : { the File upload object }, + mimetype : file.type, + preview : false, + is_deleted : 0 + .. any other data... + } + * + * + */ + addCard : function (data) { // hidden input element? @@ -12678,7 +13079,7 @@ Roo.extend(Roo.bootstrap.CardUploader, Roo.bootstrap.Input, { { xns : Roo.bootstrap, xtype : 'CardFooter', - items: [ + items: [ { xns : Roo.bootstrap, xtype : 'Element', @@ -12689,13 +13090,14 @@ Roo.extend(Roo.bootstrap.CardUploader, Roo.bootstrap.Input, { xns : Roo.bootstrap, xtype : 'Button', html : String.format("{0}", data.title), - cls : 'col-11 text-left', + cls : 'col-10 text-left', size: 'sm', weight: 'link', fa : 'download', listeners : { click : function() { - this.downloadCard(data.id) + + t.fireEvent( "download", t, data ); } } }, @@ -12703,10 +13105,10 @@ Roo.extend(Roo.bootstrap.CardUploader, Roo.bootstrap.Input, { { xns : Roo.bootstrap, xtype : 'Button', - + style: 'max-height: 28px; ', size : 'sm', weight: 'danger', - cls : 'col-1', + cls : 'col-2', fa : 'times', listeners : { click : function() { @@ -12721,7 +13123,7 @@ Roo.extend(Roo.bootstrap.CardUploader, Roo.bootstrap.Input, { } ]; - + var cn = this.addxtype( { @@ -12737,12 +13139,14 @@ Roo.extend(Roo.bootstrap.CardUploader, Roo.bootstrap.Input, { items : footer, initEvents : function() { Roo.bootstrap.Card.prototype.initEvents.call(this); + var card = this; this.imgEl = this.el.select('.card-img-top').first(); if (this.imgEl) { - this.imgEl.on('click', function() { t.previewCard( data.id); }, this); + this.imgEl.on('click', function() { t.fireEvent( "preview", t, data ); }, this); this.imgEl.set({ 'pointer' : 'cursor' }); } + this.getCardFooter().addClass('p-1'); } @@ -12752,7 +13156,21 @@ Roo.extend(Roo.bootstrap.CardUploader, Roo.bootstrap.Input, { // dont' really need ot update items. // this.items.push(cn); this.fileCollection.add(cn); - this.updateInput(); + + if (!data.srcfile) { + this.updateInput(); + return; + } + + var _t = this; + var reader = new FileReader(); + reader.addEventListener("load", function() { + data.srcdata = reader.result; + _t.updateInput(); + }); + reader.readAsDataURL(data.srcfile); + + }, removeCard : function(id) @@ -12761,16 +13179,20 @@ Roo.extend(Roo.bootstrap.CardUploader, Roo.bootstrap.Input, { var card = this.fileCollection.get(id); card.data.is_deleted = 1; card.data.src = ''; /// delete the source - so it reduces size of not uploaded images etc. - this.fileCollection.remove(card); + //this.fileCollection.remove(card); //this.items = this.items.filter(function(e) { return e != card }); // dont' really need ot update items. card.el.dom.parentNode.removeChild(card.el.dom); + this.updateInput(); + }, reset: function() { this.fileCollection.each(function(card) { - card.el.dom.parentNode.removeChild(card.el.dom); + if (card.el.dom && card.el.dom.parentNode) { + card.el.dom.parentNode.removeChild(card.el.dom); + } }); this.fileCollection.clear(); this.updateInput(); @@ -12778,12 +13200,15 @@ Roo.extend(Roo.bootstrap.CardUploader, Roo.bootstrap.Input, { updateInput : function() { - var data = []; + var data = []; this.fileCollection.each(function(e) { data.push(e.data); + }); - this.inputEl().dom.value = JSON.stringify(data); + + + } @@ -14854,35 +15279,35 @@ Roo.extend(Roo.data.ArrayReader, Roo.data.JsonReader, { readRecords : function(o) { var sid = this.meta ? this.meta.id : null; - var recordType = this.recordType, fields = recordType.prototype.fields; - var records = []; - var root = o; - for(var i = 0; i < root.length; i++){ - var n = root[i]; - var values = {}; - var id = ((sid || sid === 0) && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null); - for(var j = 0, jlen = fields.length; j < jlen; j++){ - var f = fields.items[j]; - var k = f.mapping !== undefined && f.mapping !== null ? f.mapping : j; - var v = n[k] !== undefined ? n[k] : f.defaultValue; - v = f.convert(v); - values[f.name] = v; - } - var record = new recordType(values, id); - record.json = n; - records[records.length] = record; - } - return { - records : records, - totalRecords : records.length - }; + var recordType = this.recordType, fields = recordType.prototype.fields; + var records = []; + var root = o; + for(var i = 0; i < root.length; i++){ + var n = root[i]; + var values = {}; + var id = ((sid || sid === 0) && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null); + for(var j = 0, jlen = fields.length; j < jlen; j++){ + var f = fields.items[j]; + var k = f.mapping !== undefined && f.mapping !== null ? f.mapping : j; + var v = n[k] !== undefined ? n[k] : f.defaultValue; + v = f.convert(v); + values[f.name] = v; + } + var record = new recordType(values, id); + record.json = n; + records[records.length] = record; + } + return { + records : records, + totalRecords : records.length + }; }, // used when loading children.. @see loadDataFromChildren toLoadData: function(rec) { - // expect rec just to be an array.. eg [a,b,c, [...] << cn ] - return typeof(rec.data.cn) == 'undefined' ? [] : rec.data.cn; - + // expect rec just to be an array.. eg [a,b,c, [...] << cn ] + return typeof(rec.data.cn) == 'undefined' ? [] : rec.data.cn; + } @@ -16017,7 +16442,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, { this.inputEl().on('mousedown', this.onTriggerClick, this); this.inputEl().addClass('x-combo-noedit'); }else{ - this.inputEl().dom.setAttribute('readOnly', false); + this.inputEl().dom.removeAttribute('readOnly'); this.inputEl().un('mousedown', this.onTriggerClick, this); this.inputEl().removeClass('x-combo-noedit'); } @@ -17215,16 +17640,21 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, { combobox.cls += ' roo-select2-container-multi'; } + var required = this.allowBlank ? { + tag : 'i', + style: 'display: none' + } : { + tag : 'i', + cls : 'roo-required-indicator left-indicator text-danger fa fa-lg fa-star', + tooltip : 'This field is required' + }; + var align = this.labelAlign || this.parentLabelAlign(); if (align ==='left' && this.fieldLabel.length) { cfg.cn = [ - { - tag : 'i', - cls : 'roo-required-indicator left-indicator text-danger fa fa-lg fa-star', - tooltip : 'This field is required' - }, + required, { tag: 'label', cls : 'control-label col-form-label', @@ -17254,11 +17684,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, { tag : 'span', html : this.fieldLabel }, - { - tag : 'i', - cls : 'roo-required-indicator right-indicator text-danger fa fa-lg fa-star', - tooltip : 'This field is required' - } + required ] }, { @@ -17307,11 +17733,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, { } else if ( this.fieldLabel.length) { cfg.cn = [ - { - tag : 'i', - cls : 'roo-required-indicator left-indicator text-danger fa fa-lg fa-star', - tooltip : 'This field is required' - }, + required, { tag: 'label', cls : 'control-label', @@ -17333,11 +17755,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, { cls : 'control-label', html : this.fieldLabel, cn : [ - { - tag : 'i', - cls : 'roo-required-indicator right-indicator text-danger fa fa-lg fa-star', - tooltip : 'This field is required' - } + required ] }, { @@ -19872,7 +20290,7 @@ Roo.extend(Roo.bootstrap.Popover, Roo.bootstrap.Component, { if (this.parent() && (this.over == 'parent' || (this.over === false))) { on_el = this.parent().el; } else if (this.over) { - Roo.get(this.over); + on_el = Roo.get(this.over); } } @@ -20040,15 +20458,18 @@ Roo.apply(Roo.bootstrap.Popover, { clickHander : false, + onMouseDown : function(e) { - if (!e.getTarget(".roo-popover")) { + if (this.popups.length && !e.getTarget(".roo-popover")) { + /// what is nothing is showing.. this.hideAll(); } }, + popups : [], register : function(popup) @@ -20057,15 +20478,23 @@ Roo.apply(Roo.bootstrap.Popover, { Roo.bootstrap.Popover.clickHandler = Roo.get(document).on("mousedown", Roo.bootstrap.Popover.onMouseDown, Roo.bootstrap.Popover); } // hide other popups. - this.hideAll(); - this.popups.push(popup); + popup.on('show', Roo.bootstrap.Popover.onShow, popup); + popup.on('hide', Roo.bootstrap.Popover.onHide, popup); + this.hideAll(); //<< why? + //this.popups.push(popup); }, hideAll : function() { this.popups.forEach(function(p) { p.hide(); }); - } + }, + onShow : function() { + Roo.bootstrap.Popover.popups.push(this); + }, + onHide : function() { + Roo.bootstrap.Popover.popups.remove(this); + } });/* * - LGPL @@ -21556,7 +21985,10 @@ Roo.extend(Roo.bootstrap.DateField, Roo.bootstrap.Input, { break; case 'span': if (className.indexOf('disabled') < 0) { - this.viewDate.setUTCDate(1); + if (!this.viewDate) { + this.viewDate = new Date(); + } + this.viewDate.setUTCDate(1); if (className.indexOf('month') > -1) { this.viewDate.setUTCMonth(Roo.bootstrap.DateField.dates[this.language].monthsShort.indexOf(html)); } else { @@ -21580,8 +22012,8 @@ Roo.extend(Roo.bootstrap.DateField, Roo.bootstrap.Input, { //Roo.log(className); if (className.indexOf('day') > -1 && className.indexOf('disabled') < 0 ){ var day = parseInt(html, 10) || 1; - var year = (new Date(this.viewDate)).getUTCFullYear(), - month = (new Date(this.viewDate)).getUTCMonth(); + var year = (this.viewDate || new Date()).getUTCFullYear(), + month = (this.viewDate || new Date()).getUTCMonth(); if (className.indexOf('old') > -1) { if(month === 0 ){ @@ -25763,8 +26195,8 @@ Roo.HtmlEditorCore.cblack= [ Roo.HtmlEditorCore.swapCodes =[ - [ 8211, "--" ], - [ 8212, "--" ], + [ 8211, "–" ], + [ 8212, "—" ], [ 8216, "'" ], [ 8217, "'" ], [ 8220, '"' ], @@ -28641,7 +29073,7 @@ Roo.extend(Roo.bootstrap.menu.Separator, Roo.bootstrap.Component, { getAutoCreate : function(){ var cfg = { tag : 'li', - cls: 'divider' + cls: 'dropdown-divider divider' }; return cfg; @@ -28730,10 +29162,19 @@ Roo.apply(Roo.bootstrap.Tooltip, { return; } - var bindEl = el; + var bindEl = el; + var pel = false; + if (!el.attr('tooltip')) { + pel = el.findParent("[tooltip]"); + if (pel) { + bindEl = Roo.get(pel); + } + } + + // you can not look for children, as if el is the body.. then everythign is the child.. - if (!el.attr('tooltip')) { // + if (!pel && !el.attr('tooltip')) { // if (!el.select("[tooltip]").elements.length) { return; } @@ -28747,7 +29188,7 @@ Roo.apply(Roo.bootstrap.Tooltip, { //Roo.log("child element over.."); } - this.currentEl = bindEl; + this.currentEl = el; this.currentTip.bind(bindEl); this.currentRegion = Roo.lib.Region.getRegion(dom); this.currentTip.enter(); @@ -28939,6 +29380,22 @@ Roo.extend(Roo.bootstrap.Tooltip, Roo.bootstrap.Component, { } + var elems = document.getElementsByTagName('div'); + var highest = Number.MIN_SAFE_INTEGER || -(Math.pow(2, 53) - 1); + for (var i = 0; i < elems.length; i++) { + var zindex = Number.parseInt( + document.defaultView.getComputedStyle(elems[i], null).getPropertyValue("z-index"), + 10 + ); + if (zindex > highest) { + highest = zindex; + } + } + + + + this.el.dom.style.zIndex = highest; + this.el.alignTo(this.bindEl, align[0],align[1]); //var arrow = this.el.select('.arrow',true).first(); //arrow.set(align[2], @@ -29466,8 +29923,11 @@ Roo.apply(Roo.bootstrap.LocationPicker, { * @licence LGPL * @cfg {String} title The title of alert * @cfg {String} html The content of alert - * @cfg {String} weight ( success | info | warning | danger ) - * @cfg {String} faicon font-awesomeicon + * @cfg {String} weight (success|info|warning|danger) Weight of the message + * @cfg {String} fa font-awesomeicon + * @cfg {Number} seconds default:-1 Number of seconds until it disapears (-1 means never.) + * @cfg {Boolean} close true to show a x closer + * * * @constructor * Create a new alert @@ -29485,7 +29945,10 @@ Roo.extend(Roo.bootstrap.Alert, Roo.bootstrap.Component, { title: '', html: '', weight: false, - faicon: false, + fa: false, + faicon: false, // BC + close : false, + getAutoCreate : function() { @@ -29494,6 +29957,13 @@ Roo.extend(Roo.bootstrap.Alert, Roo.bootstrap.Component, { tag : 'div', cls : 'alert', cn : [ + { + tag: 'button', + type : "button", + cls: "close", + html : '×', + style : this.close ? '' : 'display:none' + }, { tag : 'i', cls : 'roo-alert-icon' @@ -29515,6 +29985,9 @@ Roo.extend(Roo.bootstrap.Alert, Roo.bootstrap.Component, { if(this.faicon){ cfg.cn[0].cls += ' fa ' + this.faicon; } + if(this.fa){ + cfg.cn[0].cls += ' fa ' + this.fa; + } if(this.weight){ cfg.cls += ' alert-' + this.weight; @@ -29526,45 +29999,69 @@ Roo.extend(Roo.bootstrap.Alert, Roo.bootstrap.Component, { initEvents: function() { this.el.setVisibilityMode(Roo.Element.DISPLAY); + this.titleEl = this.el.select('.roo-alert-title',true).first(); + this.iconEl = this.el.select('.roo-alert-icon',true).first(); + this.htmlEl = this.el.select('.roo-alert-text',true).first(); + if (this.seconds > 0) { + this.hide.defer(this.seconds, this); + } }, - + /** + * Set the Title Message HTML + * @param {String} html + */ setTitle : function(str) { - this.el.select('.roo-alert-title',true).first().dom.innerHTML = str; + this.titleEl.dom.innerHTML = str; }, - - setText : function(str) + + /** + * Set the Body Message HTML + * @param {String} html + */ + setHtml : function(str) { - this.el.select('.roo-alert-text',true).first().dom.innerHTML = str; + this.htmlEl.dom.innerHTML = str; }, + /** + * Set the Weight of the alert + * @param {String} (success|info|warning|danger) weight + */ setWeight : function(weight) { if(this.weight){ - this.el.select('.alert',true).first().removeClass('alert-' + this.weight); + this.el.removeClass('alert-' + this.weight); } this.weight = weight; - this.el.select('.alert',true).first().addClass('alert-' + this.weight); + this.el.addClass('alert-' + this.weight); }, - + /** + * Set the Icon of the alert + * @param {String} see fontawsome names (name without the 'fa-' bit) + */ setIcon : function(icon) { if(this.faicon){ - this.el.select('.roo-alert-icon',true).first().removeClass(['fa', 'fa-' + this.faicon]); + this.alertEl.removeClass(['fa', 'fa-' + this.faicon]); } this.faicon = icon; - this.el.select('.roo-alert-icon',true).first().addClass(['fa', 'fa-' + this.faicon]); + this.alertEl.addClass(['fa', 'fa-' + this.faicon]); }, - + /** + * Hide the Alert + */ hide: function() { this.el.hide(); }, - + /** + * Show the Alert + */ show: function() { this.el.show(); @@ -39716,7 +40213,15 @@ Roo.bootstrap.panel.Content = function( config){ * Fires when this tab is created * @param {Roo.ContentPanel} this */ - "render" : true + "render" : true, + + /** + * @event scroll + * Fires when this content is scrolled + * @param {Roo.ContentPanel} this + * @param {Event} scrollEvent + */ + "scroll" : true @@ -39727,6 +40232,7 @@ Roo.bootstrap.panel.Content = function( config){ if(this.autoScroll && !this.iframe){ this.resizeEl.setStyle("overflow", "auto"); + this.resizeEl.on('scroll', this.onScroll, this); } else { // fix randome scrolling //this.el.on('scroll', function() { @@ -39766,6 +40272,9 @@ Roo.extend(Roo.bootstrap.panel.Content, Roo.bootstrap.Component, { iframe : false, iframeEl : false, + /* Resize Element - use this to work out scroll etc. */ + resizeEl : false, + setRegion : function(region){ this.region = region; this.setActiveClass(region && !this.background); @@ -40075,6 +40584,12 @@ layout.addxtype({ getChildContainer: function () { return this.getEl(); + }, + + + onScroll : function(e) + { + this.fireEvent('scroll', this, e); }