-/**
+Roo.bootstrap = {};/**
* set the version of bootstrap based on the stylesheet...
*
*/
Roo.Element.prototype.visibilityMode = Roo.Element.DISPLAY;
}
return ret;
-})(); /*
+})(); Roo.bootstrap.menu = Roo.bootstrap.menu || {};
+Roo.bootstrap.nav = {};
+
+Roo.bootstrap.form = {};Roo.bootstrap.panel = {};Roo.bootstrap.layout = {};/*
* Based on:
* Ext JS Library 1.1.1
* Copyright(c) 2006-2007, Ext JS, LLC.
* frame: Shadow displays equally on all four sides<br />
* drop: Traditional bottom-right drop shadow (default)
*/
+ mode: false,
/**
* @cfg {String} offset
* The number of pixels to offset the shadow from the element (defaults to 4)
/**
* @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
}
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){
/**
* @class Roo.bootstrap.Element
* @extends Roo.bootstrap.Component
- * Bootstrap Element class
+ * @children Roo.bootstrap.Component
+ * Bootstrap Element class (basically a DIV used to make random stuff )
+ *
* @cfg {String} html contents of the element
* @cfg {String} tag tag of the element
* @cfg {String} cls class of the element
/**
* @class Roo.bootstrap.Body
* @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.Component
+ * @parent none builder
* Bootstrap Body class
*
* @constructor
* @class Roo.bootstrap.ButtonGroup
* @extends Roo.bootstrap.Component
* Bootstrap ButtonGroup class
+ * @children Roo.bootstrap.Button Roo.bootstrap.form.Form
+ *
* @cfg {String} size lg | sm | xs (default empty normal)
* @cfg {String} align vertical | justified (default none)
* @cfg {String} direction up | down (default down)
* @cfg {Boolean} removeClass remove the standard class..
* @cfg {String} target (_self|_blank|_parent|_top|other) target for a href.
* @cfg {Boolean} grpup if parent is a btn group - then it turns it into a toogleGroup.
- *
+ * @cfg {Roo.bootstrap.menu.Menu} menu a Menu
+
* @constructor
* Create a new button
* @param {Object} config The config object
}
Roo.log('button on click ');
- if(this.preventDefault){
+ if(this.href === '' || this.preventDefault){
e.preventDefault();
}
/**
* @class Roo.bootstrap.Column
* @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.Component
* Bootstrap Column class
* @cfg {Number} xs colspan out of 12 for mobile-sized screens or 0 for hidden
* @cfg {Number} sm colspan out of 12 for tablet-sized screens or 0 for hidden
/**
* @class Roo.bootstrap.Container
* @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.Component
+ * @parent builder
* Bootstrap Container class
* @cfg {Boolean} jumbotron is it a jumbotron element
* @cfg {String} html content of element
}
});
- /*
- * - LGPL
- *
- * This is BS4's Card element.. - similar to our containers probably..
- *
- */
-/**
+ /**
* @class Roo.bootstrap.Card
* @extends Roo.bootstrap.Component
- * Bootstrap Card class
+ * @children Roo.bootstrap.Component
+ * @licence LGPL
+ * Bootstrap Card class - note this has children as CardHeader/ImageTop/Footer.. - which should really be listed properties?
*
*
* possible... may not be implemented..
/**
* @class Roo.bootstrap.CardHeader
* @extends Roo.bootstrap.Element
+ * @parent Roo.bootstrap.Card
+ * @children Roo.bootstrap.Component
* Bootstrap CardHeader class
* @constructor
* Create a new Card Header - that you can embed children into
/**
* @class Roo.bootstrap.CardFooter
* @extends Roo.bootstrap.Element
+ * @parent Roo.bootstrap.Card
+ * @children Roo.bootstrap.Component
* Bootstrap CardFooter class
+ *
* @constructor
* Create a new Card Footer - that you can embed children into
* @param {Object} config The config object
/**
* @class Roo.bootstrap.CardImageTop
* @extends Roo.bootstrap.Element
+ * @parent Roo.bootstrap.Card
+ * @children Roo.bootstrap.Component
* Bootstrap CardImageTop class
+ *
* @constructor
* Create a new Card Image Top container
* @param {Object} config The config object
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
-
+ Roo.bootstrap.Button.prototype.getAutoCreate.call(this)
]
};
(window.URL && URL.revokeObjectURL && URL) ||
(window.webkitURL && webkitURL);
-
-
-
- this.selectorEl = this.el.select('.roo-card-upload-selector', true).first();
+ var im = {
+ tag: 'input',
+ type : 'file',
+ cls : 'd-none roo-card-upload-selector'
+
+ };
+ if (this.multiple) {
+ im.multiple = 'multiple';
+ }
+ this.selectorEl = Roo.get(document.body).createChild(im); // so it does not capture click event for navitem.
+
+ //this.selectorEl = this.el.select('.roo-card-upload-selector', true).first();
this.selectorEl.on('change', this.onFileSelected, this);
* @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
* 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
});
};
smUrl: '',
mdUrl: '',
lgUrl: '',
+ backgroundContain : false,
getAutoCreate : function()
{
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;
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);
+ }
},
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
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;
}
/**
* @class Roo.bootstrap.Link
* @extends Roo.bootstrap.Component
- * Bootstrap Link Class
+ * @children Roo.bootstrap.Component
+ * Bootstrap Link Class (eg. '<a href>')
+
* @cfg {String} alt image alternative text
* @cfg {String} href a tag href
* @cfg {String} target (_self|_blank|_parent|_top) target for a href.
/**
* @class Roo.bootstrap.Header
* @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.Component
* Bootstrap Header class
+ *
+ *
* @cfg {String} html content of header
* @cfg {Number} level (1|2|3|4|5|6) default 1
*
- /*
- * Based on:
- * Ext JS Library 1.1.1
- * Copyright(c) 2006-2007, Ext JS, LLC.
- *
- * Originally Released Under LGPL - original licence link has changed is not relivant.
- *
- * Fork - LGPL
- * <script type="text/javascript">
- */
-
-/**
+ /**
* @class Roo.bootstrap.MenuMgr
+ * @licence LGPL
* Provides a common registry of all menu items on a page so that they can be easily accessed by id.
- * @singleton
+ * @static
*/
-Roo.bootstrap.MenuMgr = function(){
+Roo.bootstrap.menu.Manager = function(){
var menus, active, groups = {}, attached = false, lastShow = new Date();
// private - called when first menu is created
}
}
};
-}();/*
- * - LGPL
- *
- * menu
- *
- */
-
+}();
/**
- * @class Roo.bootstrap.Menu
+ * @class Roo.bootstrap.menu.Menu
* @extends Roo.bootstrap.Component
- * Bootstrap Menu class - container for MenuItems
+ * @licence LGPL
+ * @children Roo.bootstrap.menu.Item Roo.bootstrap.menu.Separator
+ * @parent none
+ * Bootstrap Menu class - container for MenuItems - normally has to be added to a object that supports the menu property
+ *
* @cfg {String} type (dropdown|treeview|submenu) type of menu
* @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.
+* @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
+ * @param {Object} config The config objectQ
*/
-Roo.bootstrap.Menu = function(config){
- Roo.bootstrap.Menu.superclass.constructor.call(this, config);
+Roo.bootstrap.menu.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.Menu.superclass.constructor.call(this, config);
if (this.registerMenu && this.type != 'treeview') {
- Roo.bootstrap.MenuMgr.register(this);
+ Roo.bootstrap.menu.Manager.register(this);
}
this.menuitems = new Roo.util.MixedCollection(false, function(o) { return o.el.id; });
};
-Roo.extend(Roo.bootstrap.Menu, Roo.bootstrap.Component, {
+Roo.extend(Roo.bootstrap.menu.Menu, Roo.bootstrap.Component, {
/// html : false,
// 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.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');
- }
- }
if (Roo.isTouch) {
this.el.on('touchstart' , this.onTouch, this);
}
//this.el.show();
this.hideMenuItems();
this.hidden = false;
- this.triggerEl.addClass('open');
+ if (this.triggerEl) {
+ this.triggerEl.addClass('open');
+ }
+
this.el.addClass('show');
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()){
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);
}
this.hide();
} else {
Roo.log('show');
-
+
this.show(this.triggerEl, this.align, false);
}
});
},
addxtypeChild : function (tree, cntr) {
- var comp= Roo.bootstrap.Menu.superclass.addxtypeChild.call(this, tree, cntr);
+ var comp= Roo.bootstrap.menu.Menu.superclass.addxtypeChild.call(this, tree, cntr);
this.menuitems.add(comp);
return comp;
});
- /*
- * - LGPL
- *
- * menu item
- *
- */
-
-
-/**
- * @class Roo.bootstrap.MenuItem
+ /**
+ * @class Roo.bootstrap.menu.Item
* @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.Button Roo.bootstrap.ButtonUploader Roo.bootstrap.Row Roo.bootstrap.Column Roo.bootstrap.Container
+ * @parent Roo.bootstrap.menu.Menu
+ * @licence LGPL
* Bootstrap MenuItem class
+ *
* @cfg {String} html the menu label
* @cfg {String} href the link
* @cfg {Boolean} preventDefault do not trigger A href on clicks (default false).
*/
-Roo.bootstrap.MenuItem = function(config){
- Roo.bootstrap.MenuItem.superclass.constructor.call(this, config);
+Roo.bootstrap.menu.Item = function(config){
+ Roo.bootstrap.menu.Item.superclass.constructor.call(this, config);
this.addEvents({
// raw events
/**
* @event click
* The raw click event for the entire grid.
- * @param {Roo.bootstrap.MenuItem} this
+ * @param {Roo.bootstrap.menu.Item} this
* @param {Roo.EventObject} e
*/
"click" : true
});
};
-Roo.extend(Roo.bootstrap.MenuItem, Roo.bootstrap.Component, {
+Roo.extend(Roo.bootstrap.menu.Item, Roo.bootstrap.Component, {
href : false,
html : false,
},
onClick : function(e)
{
- Roo.log('item on click ');
+ //Roo.log('item on click ');
- if(this.preventDefault){
+ if(this.href === false || this.preventDefault){
e.preventDefault();
}
//this.parent().hideMenuItems();
- /*
- * - LGPL
- *
- * menu separator
- *
- */
-
+
+
/**
- * @class Roo.bootstrap.MenuSeparator
+ * @class Roo.bootstrap.menu.Separator
* @extends Roo.bootstrap.Component
- * Bootstrap MenuSeparator class
+ * @licence LGPL
+ * @parent Roo.bootstrap.menu.Menu
+ * Bootstrap Separator class
*
* @constructor
- * Create a new MenuItem
+ * Create a new Separator
* @param {Object} config The config object
*/
-Roo.bootstrap.MenuSeparator = function(config){
- Roo.bootstrap.MenuSeparator.superclass.constructor.call(this, config);
+Roo.bootstrap.menu.Separator = function(config){
+ Roo.bootstrap.menu.Separator.superclass.constructor.call(this, config);
};
-Roo.extend(Roo.bootstrap.MenuSeparator, Roo.bootstrap.Component, {
+Roo.extend(Roo.bootstrap.menu.Separator, Roo.bootstrap.Component, {
getAutoCreate : function(){
var cfg = {
- cls: 'divider',
- tag : 'li'
+ tag : 'li',
+ cls: 'dropdown-divider divider'
};
return cfg;
/**
* @class Roo.bootstrap.Modal
* @extends Roo.bootstrap.Component
+ * @parent none builder
+ * @children Roo.bootstrap.Component
* Bootstrap Modal class
* @cfg {String} title Title of dialog
* @cfg {String} html - the body of the dialog (for simple ones) - you can also use template..
* @cfg {Roo.Template} tmpl - a template with variables. to use it, add a handler in show:method adn
* @cfg {Boolean} specificTitle default false
- * @cfg {Array} buttons Array of buttons or standard button set..
+ * @cfg {Roo.bootstrap.Button} buttons[] Array of buttons or standard button set..
* @cfg {String} buttonPosition (left|right|center) default right (DEPRICATED) - use mr-auto on buttons to put them on the left
* @cfg {Boolean} animate default true
* @cfg {Boolean} allow_close default true
delete this.items;
for(var i =0;i < items.length;i++) {
+ // we force children not to montor widnow resize - as we do that for them.
+ items[i].monitorWindowResize = false;
nitems.push(this.addxtype(Roo.apply({}, items[i])));
}
}
}
this.resizeTo(w,h);
+ // any layout/border etc.. resize..
+ (function () {
+ this.items.forEach( function(e) {
+ e.layout ? e.layout() : false;
+
+ });
+ }).defer(100,this);
+
},
show : function() {
// set zindex here - otherwise it appears to be ignored...
this.el.setStyle('z-index', Roo.bootstrap.Modal.zIndex++);
-
+
+
+ // this is for children that are... layout.Border
(function () {
this.items.forEach( function(e) {
e.layout ? e.layout() : false;
animEl: 'elId'
});
</code></pre>
- * @singleton
+ * @static
*/
Roo.bootstrap.MessageBox = function(){
var dlg, opt, mask, waitTimer;
*/
/**
- * @class Roo.bootstrap.Navbar
+ * @class Roo.bootstrap.nav.Bar
* @extends Roo.bootstrap.Component
+ * @abstract
* Bootstrap Navbar class
* @constructor
*/
-Roo.bootstrap.Navbar = function(config){
- Roo.bootstrap.Navbar.superclass.constructor.call(this, config);
+Roo.bootstrap.nav.Bar = function(config){
+ Roo.bootstrap.nav.Bar.superclass.constructor.call(this, config);
this.addEvents({
// raw events
/**
});
};
-Roo.extend(Roo.bootstrap.Navbar, Roo.bootstrap.Component, {
+Roo.extend(Roo.bootstrap.nav.Bar, Roo.bootstrap.Component, {
*/
/**
- * @class Roo.bootstrap.NavSimplebar
- * @extends Roo.bootstrap.Navbar
+ * @class Roo.bootstrap.nav.Simplebar
+ * @extends Roo.bootstrap.nav.Bar
+ * @children Roo.bootstrap.nav.Group Roo.bootstrap.Container Roo.bootstrap.form.Form Roo.bootstrap.Row Roo.bootstrap.Column Roo.bootstrap.Link
* Bootstrap Sidebar class
*
* @cfg {Boolean} inverse is inverted color
*/
-Roo.bootstrap.NavSimplebar = function(config){
- Roo.bootstrap.NavSimplebar.superclass.constructor.call(this, config);
+Roo.bootstrap.nav.Simplebar = function(config){
+ Roo.bootstrap.nav.Simplebar.superclass.constructor.call(this, config);
};
-Roo.extend(Roo.bootstrap.NavSimplebar, Roo.bootstrap.Navbar, {
+Roo.extend(Roo.bootstrap.nav.Simplebar, Roo.bootstrap.nav.Bar, {
inverse: false,
*/
/**
- * @class Roo.bootstrap.NavHeaderbar
- * @extends Roo.bootstrap.NavSimplebar
+ * @class Roo.bootstrap.nav.Headerbar
+ * @extends Roo.bootstrap.nav.Simplebar
+ * @children Roo.bootstrap.nav.Group Roo.bootstrap.Container Roo.bootstrap.form.Form Roo.bootstrap.Row Roo.bootstrap.Column Roo.bootstrap.Link
* Bootstrap Sidebar class
*
* @cfg {String} brand what is brand
*/
-Roo.bootstrap.NavHeaderbar = function(config){
- Roo.bootstrap.NavHeaderbar.superclass.constructor.call(this, config);
+Roo.bootstrap.nav.Headerbar = function(config){
+ Roo.bootstrap.nav.Headerbar.superclass.constructor.call(this, config);
};
-Roo.extend(Roo.bootstrap.NavHeaderbar, Roo.bootstrap.NavSimplebar, {
+Roo.extend(Roo.bootstrap.nav.Headerbar, Roo.bootstrap.nav.Simplebar, {
position: '',
brand: '',
initEvents : function()
{
- Roo.bootstrap.NavHeaderbar.superclass.initEvents.call(this);
+ Roo.bootstrap.nav.Headerbar.superclass.initEvents.call(this);
if (this.autohide) {
*/
/**
- * @class Roo.bootstrap.NavSidebar
- * @extends Roo.bootstrap.Navbar
+ * @class Roo.bootstrap.nav.Sidebar
+ * @extends Roo.bootstrap.nav.Bar
+ * @children Roo.bootstrap.nav.Group Roo.bootstrap.Container Roo.bootstrap.form.Form Roo.bootstrap.Row Roo.bootstrap.Column Roo.bootstrap.Link
* Bootstrap Sidebar class
*
* @constructor
*/
-Roo.bootstrap.NavSidebar = function(config){
- Roo.bootstrap.NavSidebar.superclass.constructor.call(this, config);
+Roo.bootstrap.nav.Sidebar = function(config){
+ Roo.bootstrap.nav.Sidebar.superclass.constructor.call(this, config);
};
-Roo.extend(Roo.bootstrap.NavSidebar, Roo.bootstrap.Navbar, {
+Roo.extend(Roo.bootstrap.nav.Sidebar, Roo.bootstrap.nav.Bar, {
sidebar : true, // used by Navbar Item and NavbarGroup at present...
*/
/**
- * @class Roo.bootstrap.NavGroup
+ * @class Roo.bootstrap.nav.Group
* @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.nav.Item
* Bootstrap NavGroup class
* @cfg {String} align (left|right)
* @cfg {Boolean} inverse
* @param {Object} config The config object
*/
-Roo.bootstrap.NavGroup = function(config){
- Roo.bootstrap.NavGroup.superclass.constructor.call(this, config);
+Roo.bootstrap.nav.Group = function(config){
+ Roo.bootstrap.nav.Group.superclass.constructor.call(this, config);
this.navItems = [];
- Roo.bootstrap.NavGroup.register(this);
+ Roo.bootstrap.nav.Group.register(this);
this.addEvents({
/**
* @event changed
* Fires when the active item changes
- * @param {Roo.bootstrap.NavGroup} this
+ * @param {Roo.bootstrap.nav.Group} this
* @param {Roo.bootstrap.Navbar.Item} selected The item selected
* @param {Roo.bootstrap.Navbar.Item} prev The previously selected item
*/
};
-Roo.extend(Roo.bootstrap.NavGroup, Roo.bootstrap.Component, {
+Roo.extend(Roo.bootstrap.nav.Group, Roo.bootstrap.Component, {
align: '',
inverse: false,
getAutoCreate : function()
{
- var cfg = Roo.apply({}, Roo.bootstrap.NavGroup.superclass.getAutoCreate.call(this));
+ var cfg = Roo.apply({}, Roo.bootstrap.nav.Group.superclass.getAutoCreate.call(this));
cfg = {
tag : 'ul',
},
/**
* sets the active Navigation item
- * @param {Roo.bootstrap.NavItem} the new current navitem
+ * @param {Roo.bootstrap.nav.Item} the new current navitem
*/
setActiveItem : function(item)
{
},
/**
* gets the active Navigation item
- * @return {Roo.bootstrap.NavItem} the current navitem
+ * @return {Roo.bootstrap.nav.Item} the current navitem
*/
getActive : function()
{
},
/**
* adds a Navigation item
- * @param {Roo.bootstrap.NavItem} the navitem to add
+ * @param {Roo.bootstrap.nav.Item} the navitem to add
*/
addItem : function(cfg)
{
if (this.form && Roo.bootstrap.version == 4) {
cfg.tag = 'div';
}
- var cn = new Roo.bootstrap.NavItem(cfg);
+ var cn = new Roo.bootstrap.nav.Item(cfg);
this.register(cn);
cn.parentId = this.id;
cn.onRender(this.el, null);
},
/**
* register a Navigation item
- * @param {Roo.bootstrap.NavItem} the navitem to add
+ * @param {Roo.bootstrap.nav.Item} the navitem to add
*/
register : function(item)
{
});
-Roo.apply(Roo.bootstrap.NavGroup, {
+Roo.apply(Roo.bootstrap.nav.Group, {
groups: {},
/**
* register a Navigation Group
- * @param {Roo.bootstrap.NavGroup} the navgroup to add
+ * @param {Roo.bootstrap.nav.Group} the navgroup to add
*/
register : function(navgrp)
{
/**
* fetch a Navigation Group based on the navigation ID
* @param {string} the navgroup to add
- * @returns {Roo.bootstrap.NavGroup} the navgroup
+ * @returns {Roo.bootstrap.nav.Group} the navgroup
*/
get: function(navId) {
if (typeof(this.groups[navId]) == 'undefined') {
return false;
- //this.register(new Roo.bootstrap.NavGroup({ navId : navId }));
+ //this.register(new Roo.bootstrap.nav.Group({ navId : navId }));
}
return this.groups[navId] ;
}
});
- /*
- * - LGPL
- *
- * row
- *
- */
-
-/**
- * @class Roo.bootstrap.NavItem
+ /**
+ * @class Roo.bootstrap.nav.Item
* @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.Container Roo.bootstrap.Button
+ * @parent Roo.bootstrap.nav.Group
+ * @licence LGPL
* Bootstrap Navbar.NavItem class
+ *
* @cfg {String} href link to
* @cfg {String} button_weight (default|primary|secondary|success|info|warning|danger|link|light|dark) default none
* @cfg {Boolean} button_outline show and outlined button
* @cfg {String} tabId the tab that this item activates.
* @cfg {String} tagtype (a|span) render as a href or span?
* @cfg {Boolean} animateRef (true|false) link to element default false
+ * @cfg {Roo.bootstrap.menu.Menu} menu a Menu
* @constructor
* Create a new Navbar Item
* @param {Object} config The config object
*/
-Roo.bootstrap.NavItem = function(config){
- Roo.bootstrap.NavItem.superclass.constructor.call(this, config);
+Roo.bootstrap.nav.Item = function(config){
+ Roo.bootstrap.nav.Item.superclass.constructor.call(this, config);
this.addEvents({
// raw events
/**
/**
* @event changed
* Fires when the active item active state changes
- * @param {Roo.bootstrap.NavItem} this
+ * @param {Roo.bootstrap.nav.Item} this
* @param {boolean} state the new state
*/
/**
* @event scrollto
* Fires when scroll to element
- * @param {Roo.bootstrap.NavItem} this
+ * @param {Roo.bootstrap.nav.Item} this
* @param {Object} options
* @param {Roo.EventObject} e
};
-Roo.extend(Roo.bootstrap.NavItem, Roo.bootstrap.Component, {
+Roo.extend(Roo.bootstrap.nav.Item, Roo.bootstrap.Component, {
href: false,
html: '',
this.tag = 'div';
}
- var ret = Roo.bootstrap.NavItem.superclass.onRender.call(this, ct, position);
+ var ret = Roo.bootstrap.nav.Item.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;
}
if(
- this.preventDefault ||
- this.href == '#'
+ this.preventDefault ||
+ this.href === false ||
+ this.href === '#'
){
- Roo.log("NavItem - prevent Default?");
+ //Roo.log("NavItem - prevent Default?");
e.preventDefault();
}
{
if (this.active && !state && this.navId) {
this.was_active = true;
- var nv = Roo.bootstrap.NavGroup.get(this.navId);
+ var nv = Roo.bootstrap.nav.Group.get(this.navId);
if (nv) {
nv.clearWasActive(this);
}
}
// if we can not flip to new panel - go back to old nav highlight..
if (false == tg.showPanel(pan)) {
- var nv = Roo.bootstrap.NavGroup.get(this.navId);
+ var nv = Roo.bootstrap.nav.Group.get(this.navId);
if (nv) {
var onav = nv.getWasActive();
if (onav) {
*/
/**
- * @class Roo.bootstrap.NavSidebarItem
- * @extends Roo.bootstrap.NavItem
+ * @class Roo.bootstrap.nav.SidebarItem
+ * @extends Roo.bootstrap.nav.Item
* Bootstrap Navbar.NavSidebarItem class
+ *
* {String} badgeWeight (default|primary|success|info|warning|danger)the extra classes for the badge
* {Boolean} open is the menu open
* {Boolean} buttonView use button as the tigger el rather that a (default false)
* Create a new Navbar Button
* @param {Object} config The config object
*/
-Roo.bootstrap.NavSidebarItem = function(config){
- Roo.bootstrap.NavSidebarItem.superclass.constructor.call(this, config);
+Roo.bootstrap.nav.SidebarItem = function(config){
+ Roo.bootstrap.nav.SidebarItem.superclass.constructor.call(this, config);
this.addEvents({
// raw events
/**
/**
* @event changed
* Fires when the active item active state changes
- * @param {Roo.bootstrap.NavSidebarItem} this
+ * @param {Roo.bootstrap.nav.SidebarItem} this
* @param {boolean} state the new state
*/
};
-Roo.extend(Roo.bootstrap.NavSidebarItem, Roo.bootstrap.NavItem, {
+Roo.extend(Roo.bootstrap.nav.SidebarItem, Roo.bootstrap.nav.Item, {
badgeWeight : 'default',
/*
* - LGPL
*
- * Breadcrumb Nav
+ * nav progress bar
*
*/
-Roo.namespace('Roo.bootstrap.breadcrumb');
-
/**
- * @class Roo.bootstrap.breadcrumb.Nav
+ * @class Roo.bootstrap.nav.ProgressBar
* @extends Roo.bootstrap.Component
- * Bootstrap Breadcrumb Nav Class
- *
- * @children Roo.bootstrap.breadcrumb.Item
+ * @children Roo.bootstrap.nav.ProgressBarItem
+ * Bootstrap NavProgressBar class
*
* @constructor
- * Create a new breadcrumb.Nav
+ * Create a new nav progress bar - a bar indicating step along a process
* @param {Object} config The config object
*/
+Roo.bootstrap.nav.ProgressBar = function(config){
+ Roo.bootstrap.nav.ProgressBar.superclass.constructor.call(this, config);
-Roo.bootstrap.breadcrumb.Nav = function(config){
- Roo.bootstrap.breadcrumb.Nav.superclass.constructor.call(this, config);
-
+ this.bullets = this.bullets || [];
+
+// Roo.bootstrap.nav.ProgressBar.register(this);
+ this.addEvents({
+ /**
+ * @event changed
+ * Fires when the active item changes
+ * @param {Roo.bootstrap.nav.ProgressBar} this
+ * @param {Roo.bootstrap.nav.ProgressItem} selected The item selected
+ * @param {Roo.bootstrap.nav.ProgressItem} prev The previously selected item
+ */
+ 'changed': true
+ });
};
-Roo.extend(Roo.bootstrap.breadcrumb.Nav, Roo.bootstrap.Component, {
+Roo.extend(Roo.bootstrap.nav.ProgressBar, Roo.bootstrap.Component, {
+ /**
+ * @cfg {Roo.bootstrap.nav.ProgressItem} NavProgressBar:bullets[]
+ * Bullets for the Nav Progress bar for the toolbar
+ */
+ bullets : [],
+ barItems : [],
getAutoCreate : function()
{
-
- var cfg = {
- tag: 'nav',
+ var cfg = Roo.apply({}, Roo.bootstrap.nav.ProgressBar.superclass.getAutoCreate.call(this));
+
+ cfg = {
+ tag : 'div',
+ cls : 'roo-navigation-bar-group',
cn : [
{
- tag : 'ol',
- cls : 'breadcrumb'
+ tag : 'div',
+ cls : 'roo-navigation-top-bar'
+ },
+ {
+ tag : 'div',
+ cls : 'roo-navigation-bullets-bar',
+ cn : [
+ {
+ tag : 'ul',
+ cls : 'roo-navigation-bar'
+ }
+ ]
+ },
+
+ {
+ tag : 'div',
+ cls : 'roo-navigation-bottom-bar'
}
]
};
-
+
return cfg;
+
},
- initEvents: function()
+ initEvents: function()
{
- this.olEl = this.el.select('ol',true).first();
+
},
- getChildContainer : function()
+
+ onRender : function(ct, position)
{
- return this.olEl;
+ Roo.bootstrap.nav.ProgressBar.superclass.onRender.call(this, ct, position);
+
+ if(this.bullets.length){
+ Roo.each(this.bullets, function(b){
+ this.addItem(b);
+ }, this);
+ }
+
+ this.format();
+
+ },
+
+ addItem : function(cfg)
+ {
+ var item = new Roo.bootstrap.nav.ProgressItem(cfg);
+
+ item.parentId = this.id;
+ item.render(this.el.select('.roo-navigation-bar', true).first(), null);
+
+ if(cfg.html){
+ var top = new Roo.bootstrap.Element({
+ tag : 'div',
+ cls : 'roo-navigation-bar-text'
+ });
+
+ var bottom = new Roo.bootstrap.Element({
+ tag : 'div',
+ cls : 'roo-navigation-bar-text'
+ });
+
+ top.onRender(this.el.select('.roo-navigation-top-bar', true).first(), null);
+ bottom.onRender(this.el.select('.roo-navigation-bottom-bar', true).first(), null);
+
+ var topText = new Roo.bootstrap.Element({
+ tag : 'span',
+ html : (typeof(cfg.position) != 'undefined' && cfg.position == 'top') ? cfg.html : ''
+ });
+
+ var bottomText = new Roo.bootstrap.Element({
+ tag : 'span',
+ html : (typeof(cfg.position) != 'undefined' && cfg.position == 'top') ? '' : cfg.html
+ });
+
+ topText.onRender(top.el, null);
+ bottomText.onRender(bottom.el, null);
+
+ item.topEl = top;
+ item.bottomEl = bottom;
+ }
+
+ this.barItems.push(item);
+
+ return item;
+ },
+
+ getActive : function()
+ {
+ var active = false;
+
+ Roo.each(this.barItems, function(v){
+
+ if (!v.isActive()) {
+ return;
+ }
+
+ active = v;
+ return false;
+
+ });
+
+ return active;
+ },
+
+ setActiveItem : function(item)
+ {
+ var prev = false;
+
+ Roo.each(this.barItems, function(v){
+ if (v.rid == item.rid) {
+ return ;
+ }
+
+ if (v.isActive()) {
+ v.setActive(false);
+ prev = v;
+ }
+ });
+
+ item.setActive(true);
+
+ this.fireEvent('changed', this, item, prev);
+ },
+
+ getBarItem: function(rid)
+ {
+ var ret = false;
+
+ Roo.each(this.barItems, function(e) {
+ if (e.rid != rid) {
+ return;
+ }
+
+ ret = e;
+ return false;
+ });
+
+ return ret;
+ },
+
+ indexOfItem : function(item)
+ {
+ var index = false;
+
+ Roo.each(this.barItems, function(v, i){
+
+ if (v.rid != item.rid) {
+ return;
+ }
+
+ index = i;
+ return false
+ });
+
+ return index;
+ },
+
+ setActiveNext : function()
+ {
+ var i = this.indexOfItem(this.getActive());
+
+ if (i > this.barItems.length) {
+ return;
+ }
+
+ this.setActiveItem(this.barItems[i+1]);
+ },
+
+ setActivePrev : function()
+ {
+ var i = this.indexOfItem(this.getActive());
+
+ if (i < 1) {
+ return;
+ }
+
+ this.setActiveItem(this.barItems[i-1]);
+ },
+
+ format : function()
+ {
+ if(!this.barItems.length){
+ return;
+ }
+
+ var width = 100 / this.barItems.length;
+
+ Roo.each(this.barItems, function(i){
+ i.el.setStyle('width', width + '%');
+ i.topEl.el.setStyle('width', width + '%');
+ i.bottomEl.el.setStyle('width', width + '%');
+ }, this);
+
}
});
-
- /*
+/*
* - LGPL
*
- * Breadcrumb Item
+ * Nav Progress Item
*
*/
-
/**
- * @class Roo.bootstrap.breadcrumb.Nav
+ * @class Roo.bootstrap.nav.ProgressBarItem
* @extends Roo.bootstrap.Component
- * Bootstrap Breadcrumb Nav Class
- *
- * @children Roo.bootstrap.breadcrumb.Component
- * @cfg {String} html the content of the link.
- * @cfg {String} href where it links to if '#' is used the link will be handled by onClick.
- * @cfg {Boolean} active is it active
-
+ * Bootstrap NavProgressBarItem class
+ * @cfg {String} rid the reference id
+ * @cfg {Boolean} active (true|false) Is item active default false
+ * @cfg {Boolean} disabled (true|false) Is item active default false
+ * @cfg {String} html
+ * @cfg {String} position (top|bottom) text position default bottom
+ * @cfg {String} icon show icon instead of number
*
* @constructor
- * Create a new breadcrumb.Nav
+ * Create a new NavProgressBarItem
* @param {Object} config The config object
*/
-
-Roo.bootstrap.breadcrumb.Item = function(config){
- Roo.bootstrap.breadcrumb.Item.superclass.constructor.call(this, config);
+Roo.bootstrap.nav.ProgressBarItem = function(config){
+ Roo.bootstrap.nav.ProgressBarItem.superclass.constructor.call(this, config);
this.addEvents({
- // img events
+ // raw events
/**
* @event click
- * The img click event for the img.
+ * The raw click event for the entire grid.
+ * @param {Roo.bootstrap.nav.ProgressBarItem} this
* @param {Roo.EventObject} e
*/
"click" : true
});
-
+
};
-Roo.extend(Roo.bootstrap.breadcrumb.Item, Roo.bootstrap.Component, {
+Roo.extend(Roo.bootstrap.nav.ProgressBarItem, Roo.bootstrap.Component, {
- href: false,
+ rid : '',
+ active : false,
+ disabled : false,
html : '',
+ position : 'bottom',
+ icon : false,
getAutoCreate : function()
{
-
+ var iconCls = 'roo-navigation-bar-item-icon';
+
+ iconCls += ((this.icon) ? (' ' + this.icon) : (' step-number')) ;
+
var cfg = {
tag: 'li',
- cls : 'breadcrumb-item' + (this.active ? ' active' : '')
+ cls: 'roo-navigation-bar-item',
+ cn : [
+ {
+ tag : 'i',
+ cls : iconCls
+ }
+ ]
};
- if (this.href !== false) {
- cfg.cn = [{
- tag : 'a',
- href : this.href,
- html : this.html
- }];
- } else {
- cfg.html = this.html;
+
+ if(this.active){
+ cfg.cls += ' active';
+ }
+ if(this.disabled){
+ cfg.cls += ' disabled';
}
return cfg;
},
- initEvents: function()
+ disable : function()
{
- if (this.href) {
- this.el.select('a', true).first().on('click',this.onClick, this)
- }
+ this.setDisabled(true);
+ },
+
+ enable : function()
+ {
+ this.setDisabled(false);
+ },
+
+ initEvents: function()
+ {
+ this.iconEl = this.el.select('.roo-navigation-bar-item-icon', true).first();
+ this.iconEl.on('click', this.onClick, this);
},
+
onClick : function(e)
{
e.preventDefault();
- this.fireEvent('click',this, e);
- }
+
+ if(this.disabled){
+ return;
+ }
+
+ if(this.fireEvent('click', this, e) === false){
+ return;
+ };
+
+ this.parent().setActiveItem(this);
+ },
-});
-
- /*
- * - LGPL
- *
- * row
- *
- */
-
-/**
- * @class Roo.bootstrap.Row
- * @extends Roo.bootstrap.Component
- * Bootstrap Row class (contains columns...)
- *
- * @constructor
- * Create a new Row
- * @param {Object} config The config object
- */
-
+ isActive: function ()
+ {
+ return this.active;
+ },
+
+ setActive : function(state)
+ {
+ if(this.active == state){
+ return;
+ }
+
+ this.active = state;
+
+ if (state) {
+ this.el.addClass('active');
+ return;
+ }
+
+ this.el.removeClass('active');
+
+ return;
+ },
+
+ setDisabled : function(state)
+ {
+ if(this.disabled == state){
+ return;
+ }
+
+ this.disabled = state;
+
+ if (state) {
+ this.el.addClass('disabled');
+ return;
+ }
+
+ this.el.removeClass('disabled');
+ },
+
+ tooltipEl : function()
+ {
+ return this.el.select('.roo-navigation-bar-item-icon', true).first();;
+ }
+});
+
+
+ /*
+ * - LGPL
+ *
+ * Breadcrumb Nav
+ *
+ */
+Roo.namespace('Roo.bootstrap.breadcrumb');
+
+
+/**
+ * @class Roo.bootstrap.breadcrumb.Nav
+ * @extends Roo.bootstrap.Component
+ * Bootstrap Breadcrumb Nav Class
+ *
+ * @children Roo.bootstrap.breadcrumb.Item
+ *
+ * @constructor
+ * Create a new breadcrumb.Nav
+ * @param {Object} config The config object
+ */
+
+
+Roo.bootstrap.breadcrumb.Nav = function(config){
+ Roo.bootstrap.breadcrumb.Nav.superclass.constructor.call(this, config);
+
+
+};
+
+Roo.extend(Roo.bootstrap.breadcrumb.Nav, Roo.bootstrap.Component, {
+
+ getAutoCreate : function()
+ {
+
+ var cfg = {
+ tag: 'nav',
+ cn : [
+ {
+ tag : 'ol',
+ cls : 'breadcrumb'
+ }
+ ]
+
+ };
+
+ return cfg;
+ },
+
+ initEvents: function()
+ {
+ this.olEl = this.el.select('ol',true).first();
+ },
+ getChildContainer : function()
+ {
+ return this.olEl;
+ }
+
+});
+
+ /*
+ * - LGPL
+ *
+ * Breadcrumb Item
+ *
+ */
+
+
+/**
+ * @class Roo.bootstrap.breadcrumb.Nav
+ * @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.Component
+ * @parent Roo.bootstrap.breadcrumb.Nav
+ * Bootstrap Breadcrumb Nav Class
+ *
+ *
+ * @cfg {String} html the content of the link.
+ * @cfg {String} href where it links to if '#' is used the link will be handled by onClick.
+ * @cfg {Boolean} active is it active
+
+ *
+ * @constructor
+ * Create a new breadcrumb.Nav
+ * @param {Object} config The config object
+ */
+
+Roo.bootstrap.breadcrumb.Item = function(config){
+ Roo.bootstrap.breadcrumb.Item.superclass.constructor.call(this, config);
+ this.addEvents({
+ // img events
+ /**
+ * @event click
+ * The img click event for the img.
+ * @param {Roo.EventObject} e
+ */
+ "click" : true
+ });
+
+};
+
+Roo.extend(Roo.bootstrap.breadcrumb.Item, Roo.bootstrap.Component, {
+
+ href: false,
+ html : '',
+
+ getAutoCreate : function()
+ {
+
+ var cfg = {
+ tag: 'li',
+ cls : 'breadcrumb-item' + (this.active ? ' active' : '')
+ };
+ if (this.href !== false) {
+ cfg.cn = [{
+ tag : 'a',
+ href : this.href,
+ html : this.html
+ }];
+ } else {
+ cfg.html = this.html;
+ }
+
+ return cfg;
+ },
+
+ initEvents: function()
+ {
+ if (this.href) {
+ this.el.select('a', true).first().on('click',this.onClick, this)
+ }
+
+ },
+ onClick : function(e)
+ {
+ e.preventDefault();
+ this.fireEvent('click',this, e);
+ }
+
+});
+
+ /*
+ * - LGPL
+ *
+ * row
+ *
+ */
+
+/**
+ * @class Roo.bootstrap.Row
+ * @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.Component
+ * Bootstrap Row class (contains columns...)
+ *
+ * @constructor
+ * Create a new Row
+ * @param {Object} config The config object
+ */
+
Roo.bootstrap.Row = function(config){
Roo.bootstrap.Row.superclass.constructor.call(this, config);
};
/**
* @class Roo.bootstrap.Pagination
* @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.Pagination
* Bootstrap Pagination class
- * @cfg {String} size xs | sm | md | lg
- * @cfg {Boolean} inverse false | true
+ *
+ * @cfg {String} size (xs|sm|md|lg|xl)
+ * @cfg {Boolean} inverse
*
* @constructor
* Create a new Pagination
* Fork - LGPL
* <script type="text/javascript">
*/
-
-
-/**
- * @class Roo.grid.ColumnModel
- * @extends Roo.util.Observable
- * This is the default implementation of a ColumnModel used by the Grid. It defines
- * the columns in the grid.
- * <br>Usage:<br>
- <pre><code>
- var colModel = new Roo.grid.ColumnModel([
- {header: "Ticker", width: 60, sortable: true, locked: true},
- {header: "Company Name", width: 150, sortable: true},
- {header: "Market Cap.", width: 100, sortable: true},
- {header: "$ Sales", width: 100, sortable: true, renderer: money},
- {header: "Employees", width: 100, sortable: true, resizable: false}
- ]);
- </code></pre>
- * <p>
-
- * The config options listed for this class are options which may appear in each
- * individual column definition.
- * <br/>RooJS Fix - column id's are not sequential but use Roo.id() - fixes bugs with layouts.
+ /**
+ * @extends Roo.dd.DDProxy
+ * @class Roo.grid.SplitDragZone
+ * Support for Column Header resizing
* @constructor
- * @param {Object} config An Array of column config objects. See this class's
- * config objects for details.
-*/
-Roo.grid.ColumnModel = function(config){
- /**
- * The config passed into the constructor
- */
- this.config = config;
- this.lookup = {};
+ * @param {Object} config
+ */
+// private
+// This is a support class used internally by the Grid components
+Roo.grid.SplitDragZone = function(grid, hd, hd2){
+ this.grid = grid;
+ this.view = grid.getView();
+ this.proxy = this.view.resizeProxy;
+ Roo.grid.SplitDragZone.superclass.constructor.call(
+ this,
+ hd, // ID
+ "gridSplitters" + this.grid.getGridEl().id, // SGROUP
+ { // CONFIG
+ dragElId : Roo.id(this.proxy.dom),
+ resizeFrame:false
+ }
+ );
+
+ this.setHandleElId(Roo.id(hd));
+ if (hd2 !== false) {
+ this.setOuterHandleElId(Roo.id(hd2));
+ }
+
+ this.scroll = false;
+};
+Roo.extend(Roo.grid.SplitDragZone, Roo.dd.DDProxy, {
+ fly: Roo.Element.fly,
- // 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];
+ b4StartDrag : function(x, y){
+ this.view.headersDisabled = true;
+ var h = this.view.mainWrap ? this.view.mainWrap.getHeight() : (
+ this.view.headEl.getHeight() + this.view.bodyEl.getHeight()
+ );
+ this.proxy.setHeight(h);
+
+ // for old system colWidth really stored the actual width?
+ // in bootstrap we tried using xs/ms/etc.. to do % sizing?
+ // which in reality did not work.. - it worked only for fixed sizes
+ // for resizable we need to use actual sizes.
+ var w = this.cm.getColumnWidth(this.cellIndex);
+ if (!this.view.mainWrap) {
+ // bootstrap.
+ w = this.view.getHeaderIndex(this.cellIndex).getWidth();
}
- if(typeof c.id == "undefined"){
- c.id = Roo.id();
+
+
+
+ // this was w-this.grid.minColumnWidth;
+ // doesnt really make sense? - w = thie curren width or the rendered one?
+ var minw = Math.max(w-this.grid.minColumnWidth, 0);
+ this.resetConstraints();
+ this.setXConstraint(minw, 1000);
+ this.setYConstraint(0, 0);
+ this.minX = x - minw;
+ this.maxX = x + 1000;
+ this.startPos = x;
+ if (!this.view.mainWrap) { // this is Bootstrap code..
+ this.getDragEl().style.display='block';
}
- if(c.editor && c.editor.xtype){
- c.editor = Roo.factory(c.editor, Roo.grid);
+
+ Roo.dd.DDProxy.prototype.b4StartDrag.call(this, x, y);
+ },
+
+
+ handleMouseDown : function(e){
+ ev = Roo.EventObject.setEvent(e);
+ var t = this.fly(ev.getTarget());
+ if(t.hasClass("x-grid-split")){
+ this.cellIndex = this.view.getCellIndex(t.dom);
+ this.split = t.dom;
+ this.cm = this.grid.colModel;
+ if(this.cm.isResizable(this.cellIndex) && !this.cm.isFixed(this.cellIndex)){
+ Roo.grid.SplitDragZone.superclass.handleMouseDown.apply(this, arguments);
+ }
}
- if(c.editor && c.editor.isFormField){
- c.editor = new Roo.grid.GridEditor(c.editor);
+ },
+
+ endDrag : function(e){
+ this.view.headersDisabled = false;
+ var endX = Math.max(this.minX, Roo.lib.Event.getPageX(e));
+ var diff = endX - this.startPos;
+ //
+ var w = this.cm.getColumnWidth(this.cellIndex);
+ if (!this.view.mainWrap) {
+ w = 0;
}
- this.lookup[c.id] = c;
+ this.view.onColumnSplitterMoved(this.cellIndex, w+diff);
+ },
+
+ autoOffset : function(){
+ this.setDelta(0,0);
}
+});/*
+ * Based on:
+ * Ext JS Library 1.1.1
+ * Copyright(c) 2006-2007, Ext JS, LLC.
+ *
+ * Originally Released Under LGPL - original licence link has changed is not relivant.
+ *
+ * Fork - LGPL
+ * <script type="text/javascript">
+ */
+
+/**
+ * @class Roo.grid.AbstractSelectionModel
+ * @extends Roo.util.Observable
+ * @abstract
+ * Abstract base class for grid SelectionModels. It provides the interface that should be
+ * implemented by descendant classes. This class should not be directly instantiated.
+ * @constructor
+ */
+Roo.grid.AbstractSelectionModel = function(){
+ this.locked = false;
+ Roo.grid.AbstractSelectionModel.superclass.constructor.call(this);
+};
+
+Roo.extend(Roo.grid.AbstractSelectionModel, Roo.util.Observable, {
+ /** @ignore Called by the grid automatically. Do not call directly. */
+ init : function(grid){
+ this.grid = grid;
+ this.initEvents();
+ },
/**
- * The width of columns which have no width specified (defaults to 100)
- * @type Number
+ * Locks the selections.
*/
- this.defaultWidth = 100;
+ lock : function(){
+ this.locked = true;
+ },
/**
- * Default sortable of columns which have no sortable specified (defaults to false)
- * @type Boolean
+ * Unlocks the selections.
*/
- this.defaultSortable = false;
+ unlock : function(){
+ this.locked = false;
+ },
+
+ /**
+ * Returns true if the selections are locked.
+ * @return {Boolean}
+ */
+ isLocked : function(){
+ return this.locked;
+ }
+});/*
+ * Based on:
+ * Ext JS Library 1.1.1
+ * Copyright(c) 2006-2007, Ext JS, LLC.
+ *
+ * Originally Released Under LGPL - original licence link has changed is not relivant.
+ *
+ * Fork - LGPL
+ * <script type="text/javascript">
+ */
+/**
+ * @extends Roo.grid.AbstractSelectionModel
+ * @class Roo.grid.RowSelectionModel
+ * The default SelectionModel used by {@link Roo.grid.Grid}.
+ * It supports multiple selections and keyboard selection/navigation.
+ * @constructor
+ * @param {Object} config
+ */
+Roo.grid.RowSelectionModel = function(config){
+ Roo.apply(this, config);
+ this.selections = new Roo.util.MixedCollection(false, function(o){
+ return o.id;
+ });
+
+ this.last = false;
+ this.lastActive = false;
this.addEvents({
/**
- * @event widthchange
- * Fires when the width of a column changes.
- * @param {ColumnModel} this
- * @param {Number} columnIndex The column index
- * @param {Number} newWidth The new width
- */
- "widthchange": true,
- /**
- * @event headerchange
- * Fires when the text of a header changes.
- * @param {ColumnModel} this
- * @param {Number} columnIndex The column index
- * @param {Number} newText The new header text
- */
- "headerchange": true,
- /**
- * @event hiddenchange
- * Fires when a column is hidden or "unhidden".
- * @param {ColumnModel} this
- * @param {Number} columnIndex The column index
- * @param {Boolean} hidden true if hidden, false otherwise
- */
- "hiddenchange": true,
- /**
- * @event columnmoved
- * Fires when a column is moved.
- * @param {ColumnModel} this
- * @param {Number} oldIndex
- * @param {Number} newIndex
- */
- "columnmoved" : true,
- /**
- * @event columlockchange
- * Fires when a column's locked state is changed
- * @param {ColumnModel} this
- * @param {Number} colIndex
- * @param {Boolean} locked true if locked
- */
- "columnlockchange" : true
+ * @event selectionchange
+ * Fires when the selection changes
+ * @param {SelectionModel} this
+ */
+ "selectionchange" : true,
+ /**
+ * @event afterselectionchange
+ * Fires after the selection changes (eg. by key press or clicking)
+ * @param {SelectionModel} this
+ */
+ "afterselectionchange" : true,
+ /**
+ * @event beforerowselect
+ * Fires when a row is selected being selected, return false to cancel.
+ * @param {SelectionModel} this
+ * @param {Number} rowIndex The selected index
+ * @param {Boolean} keepExisting False if other selections will be cleared
+ */
+ "beforerowselect" : true,
+ /**
+ * @event rowselect
+ * Fires when a row is selected.
+ * @param {SelectionModel} this
+ * @param {Number} rowIndex The selected index
+ * @param {Roo.data.Record} r The record
+ */
+ "rowselect" : true,
+ /**
+ * @event rowdeselect
+ * Fires when a row is deselected.
+ * @param {SelectionModel} this
+ * @param {Number} rowIndex The selected index
+ */
+ "rowdeselect" : true
});
- Roo.grid.ColumnModel.superclass.constructor.call(this);
+ Roo.grid.RowSelectionModel.superclass.constructor.call(this);
+ this.locked = false;
};
-Roo.extend(Roo.grid.ColumnModel, Roo.util.Observable, {
+
+Roo.extend(Roo.grid.RowSelectionModel, Roo.grid.AbstractSelectionModel, {
/**
- * @cfg {String} header The header text to display in the Grid view.
+ * @cfg {Boolean} singleSelect
+ * True to allow selection of only one row at a time (defaults to false)
*/
+ singleSelect : false,
+
+ // private
+ initEvents : function(){
+
+ if(!this.grid.enableDragDrop && !this.grid.enableDrag){
+ this.grid.on("mousedown", this.handleMouseDown, this);
+ }else{ // allow click to work like normal
+ this.grid.on("rowclick", this.handleDragableRowClick, this);
+ }
+ // bootstrap does not have a view..
+ var view = this.grid.view ? this.grid.view : this.grid;
+ this.rowNav = new Roo.KeyNav(this.grid.getGridEl(), {
+ "up" : function(e){
+ if(!e.shiftKey){
+ this.selectPrevious(e.shiftKey);
+ }else if(this.last !== false && this.lastActive !== false){
+ var last = this.last;
+ this.selectRange(this.last, this.lastActive-1);
+ view.focusRow(this.lastActive);
+ if(last !== false){
+ this.last = last;
+ }
+ }else{
+ this.selectFirstRow();
+ }
+ this.fireEvent("afterselectionchange", this);
+ },
+ "down" : function(e){
+ if(!e.shiftKey){
+ this.selectNext(e.shiftKey);
+ }else if(this.last !== false && this.lastActive !== false){
+ var last = this.last;
+ this.selectRange(this.last, this.lastActive+1);
+ view.focusRow(this.lastActive);
+ if(last !== false){
+ this.last = last;
+ }
+ }else{
+ this.selectFirstRow();
+ }
+ this.fireEvent("afterselectionchange", this);
+ },
+ scope: this
+ });
+
+
+ view.on("refresh", this.onRefresh, this);
+ view.on("rowupdated", this.onRowUpdated, this);
+ view.on("rowremoved", this.onRemove, this);
+ },
+
+ // private
+ onRefresh : function(){
+ var ds = this.grid.ds, i, v = this.grid.view;
+ var s = this.selections;
+ s.each(function(r){
+ if((i = ds.indexOfId(r.id)) != -1){
+ v.onRowSelect(i);
+ s.add(ds.getAt(i)); // updating the selection relate data
+ }else{
+ s.remove(r);
+ }
+ });
+ },
+
+ // private
+ onRemove : function(v, index, r){
+ this.selections.remove(r);
+ },
+
+ // private
+ onRowUpdated : function(v, index, r){
+ if(this.isSelected(r)){
+ v.onRowSelect(index);
+ }
+ },
+
/**
- * @cfg {String} dataIndex (Optional) The name of the field in the grid's {@link Roo.data.Store}'s
- * {@link Roo.data.Record} definition from which to draw the column's value. If not
- * specified, the column's index is used as an index into the Record's data Array.
+ * Select records.
+ * @param {Array} records The records to select
+ * @param {Boolean} keepExisting (optional) True to keep existing selections
*/
+ selectRecords : function(records, keepExisting){
+ if(!keepExisting){
+ this.clearSelections();
+ }
+ var ds = this.grid.ds;
+ for(var i = 0, len = records.length; i < len; i++){
+ this.selectRow(ds.indexOf(records[i]), true);
+ }
+ },
+
/**
- * @cfg {Number} width (Optional) The initial width in pixels of the column. Using this
- * instead of {@link Roo.grid.Grid#autoSizeColumns} is more efficient.
+ * Gets the number of selected rows.
+ * @return {Number}
*/
+ getCount : function(){
+ return this.selections.length;
+ },
+
/**
- * @cfg {Boolean} sortable (Optional) True if sorting is to be allowed on this column.
- * Defaults to the value of the {@link #defaultSortable} property.
- * Whether local/remote sorting is used is specified in {@link Roo.data.Store#remoteSort}.
+ * Selects the first row in the grid.
*/
+ selectFirstRow : function(){
+ this.selectRow(0);
+ },
+
/**
- * @cfg {Boolean} locked (Optional) True to lock the column in place while scrolling the Grid. Defaults to false.
+ * Select the last row.
+ * @param {Boolean} keepExisting (optional) True to keep existing selections
*/
+ selectLastRow : function(keepExisting){
+ this.selectRow(this.grid.ds.getCount() - 1, keepExisting);
+ },
+
/**
- * @cfg {Boolean} fixed (Optional) True if the column width cannot be changed. Defaults to false.
+ * Selects the row immediately following the last selected row.
+ * @param {Boolean} keepExisting (optional) True to keep existing selections
*/
+ selectNext : function(keepExisting){
+ if(this.last !== false && (this.last+1) < this.grid.ds.getCount()){
+ this.selectRow(this.last+1, keepExisting);
+ var view = this.grid.view ? this.grid.view : this.grid;
+ view.focusRow(this.last);
+ }
+ },
+
/**
- * @cfg {Boolean} resizable (Optional) False to disable column resizing. Defaults to true.
+ * Selects the row that precedes the last selected row.
+ * @param {Boolean} keepExisting (optional) True to keep existing selections
*/
+ selectPrevious : function(keepExisting){
+ if(this.last){
+ this.selectRow(this.last-1, keepExisting);
+ var view = this.grid.view ? this.grid.view : this.grid;
+ view.focusRow(this.last);
+ }
+ },
+
/**
- * @cfg {Boolean} hidden (Optional) True to hide the column. Defaults to false.
+ * Returns the selected records
+ * @return {Array} Array of selected records
*/
+ getSelections : function(){
+ return [].concat(this.selections.items);
+ },
+
/**
- * @cfg {Function} renderer (Optional) A function used to generate HTML markup for a cell
- * given the cell's data value. See {@link #setRenderer}. If not specified, the
- * default renderer returns the escaped data value. If an object is returned (bootstrap only)
- * then it is treated as a Roo Component object instance, and it is rendered after the initial row is rendered
+ * Returns the first selected record.
+ * @return {Record}
+ */
+ getSelected : function(){
+ return this.selections.itemAt(0);
+ },
+
+
+ /**
+ * Clears all selections.
+ */
+ clearSelections : function(fast){
+ if(this.locked) {
+ return;
+ }
+ if(fast !== true){
+ var ds = this.grid.ds;
+ var s = this.selections;
+ s.each(function(r){
+ this.deselectRow(ds.indexOfId(r.id));
+ }, this);
+ s.clear();
+ }else{
+ this.selections.clear();
+ }
+ this.last = false;
+ },
+
+
+ /**
+ * Selects all rows.
+ */
+ selectAll : function(){
+ if(this.locked) {
+ return;
+ }
+ this.selections.clear();
+ for(var i = 0, len = this.grid.ds.getCount(); i < len; i++){
+ this.selectRow(i, true);
+ }
+ },
+
+ /**
+ * Returns True if there is a selection.
+ * @return {Boolean}
+ */
+ hasSelection : function(){
+ return this.selections.length > 0;
+ },
+
+ /**
+ * Returns True if the specified row is selected.
+ * @param {Number/Record} record The record or index of the record to check
+ * @return {Boolean}
+ */
+ isSelected : function(index){
+ var r = typeof index == "number" ? this.grid.ds.getAt(index) : index;
+ return (r && this.selections.key(r.id) ? true : false);
+ },
+
+ /**
+ * Returns True if the specified record id is selected.
+ * @param {String} id The id of record to check
+ * @return {Boolean}
+ */
+ isIdSelected : function(id){
+ return (this.selections.key(id) ? true : false);
+ },
+
+ // private
+ handleMouseDown : function(e, t)
+ {
+ var view = this.grid.view ? this.grid.view : this.grid;
+ var rowIndex;
+ if(this.isLocked() || (rowIndex = view.findRowIndex(t)) === false){
+ return;
+ };
+ if(e.shiftKey && this.last !== false){
+ var last = this.last;
+ this.selectRange(last, rowIndex, e.ctrlKey);
+ this.last = last; // reset the last
+ view.focusRow(rowIndex);
+ }else{
+ var isSelected = this.isSelected(rowIndex);
+ if(e.button !== 0 && isSelected){
+ view.focusRow(rowIndex);
+ }else if(e.ctrlKey && isSelected){
+ this.deselectRow(rowIndex);
+ }else if(!isSelected){
+ this.selectRow(rowIndex, e.button === 0 && (e.ctrlKey || e.shiftKey));
+ view.focusRow(rowIndex);
+ }
+ }
+ this.fireEvent("afterselectionchange", this);
+ },
+ // private
+ handleDragableRowClick : function(grid, rowIndex, e)
+ {
+ if(e.button === 0 && !e.shiftKey && !e.ctrlKey) {
+ this.selectRow(rowIndex, false);
+ var view = this.grid.view ? this.grid.view : this.grid;
+ view.focusRow(rowIndex);
+ this.fireEvent("afterselectionchange", this);
+ }
+ },
+
+ /**
+ * Selects multiple rows.
+ * @param {Array} rows Array of the indexes of the row to select
+ * @param {Boolean} keepExisting (optional) True to keep existing selections
+ */
+ selectRows : function(rows, keepExisting){
+ if(!keepExisting){
+ this.clearSelections();
+ }
+ for(var i = 0, len = rows.length; i < len; i++){
+ this.selectRow(rows[i], true);
+ }
+ },
+
+ /**
+ * Selects a range of rows. All rows in between startRow and endRow are also selected.
+ * @param {Number} startRow The index of the first row in the range
+ * @param {Number} endRow The index of the last row in the range
+ * @param {Boolean} keepExisting (optional) True to retain existing selections
+ */
+ selectRange : function(startRow, endRow, keepExisting){
+ if(this.locked) {
+ return;
+ }
+ if(!keepExisting){
+ this.clearSelections();
+ }
+ if(startRow <= endRow){
+ for(var i = startRow; i <= endRow; i++){
+ this.selectRow(i, true);
+ }
+ }else{
+ for(var i = startRow; i >= endRow; i--){
+ this.selectRow(i, true);
+ }
+ }
+ },
+
+ /**
+ * Deselects a range of rows. All rows in between startRow and endRow are also deselected.
+ * @param {Number} startRow The index of the first row in the range
+ * @param {Number} endRow The index of the last row in the range
+ */
+ deselectRange : function(startRow, endRow, preventViewNotify){
+ if(this.locked) {
+ return;
+ }
+ for(var i = startRow; i <= endRow; i++){
+ this.deselectRow(i, preventViewNotify);
+ }
+ },
+
+ /**
+ * Selects a row.
+ * @param {Number} row The index of the row to select
+ * @param {Boolean} keepExisting (optional) True to keep existing selections
+ */
+ selectRow : function(index, keepExisting, preventViewNotify){
+ if(this.locked || (index < 0 || index >= this.grid.ds.getCount())) {
+ return;
+ }
+ if(this.fireEvent("beforerowselect", this, index, keepExisting) !== false){
+ if(!keepExisting || this.singleSelect){
+ this.clearSelections();
+ }
+ var r = this.grid.ds.getAt(index);
+ this.selections.add(r);
+ this.last = this.lastActive = index;
+ if(!preventViewNotify){
+ var view = this.grid.view ? this.grid.view : this.grid;
+ view.onRowSelect(index);
+ }
+ this.fireEvent("rowselect", this, index, r);
+ this.fireEvent("selectionchange", this);
+ }
+ },
+
+ /**
+ * Deselects a row.
+ * @param {Number} row The index of the row to deselect
+ */
+ deselectRow : function(index, preventViewNotify){
+ if(this.locked) {
+ return;
+ }
+ if(this.last == index){
+ this.last = false;
+ }
+ if(this.lastActive == index){
+ this.lastActive = false;
+ }
+ var r = this.grid.ds.getAt(index);
+ this.selections.remove(r);
+ if(!preventViewNotify){
+ var view = this.grid.view ? this.grid.view : this.grid;
+ view.onRowDeselect(index);
+ }
+ this.fireEvent("rowdeselect", this, index);
+ this.fireEvent("selectionchange", this);
+ },
+
+ // private
+ restoreLast : function(){
+ if(this._last){
+ this.last = this._last;
+ }
+ },
+
+ // private
+ acceptsNav : function(row, col, cm){
+ return !cm.isHidden(col) && cm.isCellEditable(col, row);
+ },
+
+ // private
+ onEditorKey : function(field, e){
+ var k = e.getKey(), newCell, g = this.grid, ed = g.activeEditor;
+ if(k == e.TAB){
+ e.stopEvent();
+ ed.completeEdit();
+ if(e.shiftKey){
+ newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);
+ }else{
+ newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
+ }
+ }else if(k == e.ENTER && !e.ctrlKey){
+ e.stopEvent();
+ ed.completeEdit();
+ if(e.shiftKey){
+ newCell = g.walkCells(ed.row-1, ed.col, -1, this.acceptsNav, this);
+ }else{
+ newCell = g.walkCells(ed.row+1, ed.col, 1, this.acceptsNav, this);
+ }
+ }else if(k == e.ESC){
+ ed.cancelEdit();
+ }
+ if(newCell){
+ g.startEditing(newCell[0], newCell[1]);
+ }
+ }
+});/*
+ * Based on:
+ * Ext JS Library 1.1.1
+ * Copyright(c) 2006-2007, Ext JS, LLC.
+ *
+ * Originally Released Under LGPL - original licence link has changed is not relivant.
+ *
+ * Fork - LGPL
+ * <script type="text/javascript">
+ */
+
+
+/**
+ * @class Roo.grid.ColumnModel
+ * @extends Roo.util.Observable
+ * This is the default implementation of a ColumnModel used by the Grid. It defines
+ * the columns in the grid.
+ * <br>Usage:<br>
+ <pre><code>
+ var colModel = new Roo.grid.ColumnModel([
+ {header: "Ticker", width: 60, sortable: true, locked: true},
+ {header: "Company Name", width: 150, sortable: true},
+ {header: "Market Cap.", width: 100, sortable: true},
+ {header: "$ Sales", width: 100, sortable: true, renderer: money},
+ {header: "Employees", width: 100, sortable: true, resizable: false}
+ ]);
+ </code></pre>
+ * <p>
+
+ * The config options listed for this class are options which may appear in each
+ * individual column definition.
+ * <br/>RooJS Fix - column id's are not sequential but use Roo.id() - fixes bugs with layouts.
+ * @constructor
+ * @param {Object} config An Array of column config objects. See this class's
+ * config objects for details.
+*/
+Roo.grid.ColumnModel = function(config){
+ /**
+ * The config passed into the constructor
+ */
+ 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++){
+ this.addColumn(config[i]);
+
+ }
+
+ /**
+ * The width of columns which have no width specified (defaults to 100)
+ * @type Number
+ */
+ this.defaultWidth = 100;
+
+ /**
+ * Default sortable of columns which have no sortable specified (defaults to false)
+ * @type Boolean
+ */
+ this.defaultSortable = false;
+
+ this.addEvents({
+ /**
+ * @event widthchange
+ * Fires when the width of a column changes.
+ * @param {ColumnModel} this
+ * @param {Number} columnIndex The column index
+ * @param {Number} newWidth The new width
+ */
+ "widthchange": true,
+ /**
+ * @event headerchange
+ * Fires when the text of a header changes.
+ * @param {ColumnModel} this
+ * @param {Number} columnIndex The column index
+ * @param {Number} newText The new header text
+ */
+ "headerchange": true,
+ /**
+ * @event hiddenchange
+ * Fires when a column is hidden or "unhidden".
+ * @param {ColumnModel} this
+ * @param {Number} columnIndex The column index
+ * @param {Boolean} hidden true if hidden, false otherwise
+ */
+ "hiddenchange": true,
+ /**
+ * @event columnmoved
+ * Fires when a column is moved.
+ * @param {ColumnModel} this
+ * @param {Number} oldIndex
+ * @param {Number} newIndex
+ */
+ "columnmoved" : true,
+ /**
+ * @event columlockchange
+ * Fires when a column's locked state is changed
+ * @param {ColumnModel} this
+ * @param {Number} colIndex
+ * @param {Boolean} locked true if locked
+ */
+ "columnlockchange" : true
+ });
+ Roo.grid.ColumnModel.superclass.constructor.call(this);
+};
+Roo.extend(Roo.grid.ColumnModel, Roo.util.Observable, {
+ /**
+ * @cfg {String} header [required] The header text to display in the Grid view.
+ */
+ /**
+ * @cfg {String} xsHeader Header at Bootsrap Extra Small width (default for all)
+ */
+ /**
+ * @cfg {String} smHeader Header at Bootsrap Small width
+ */
+ /**
+ * @cfg {String} mdHeader Header at Bootsrap Medium width
+ */
+ /**
+ * @cfg {String} lgHeader Header at Bootsrap Large width
+ */
+ /**
+ * @cfg {String} xlHeader Header at Bootsrap extra Large width
+ */
+ /**
+ * @cfg {String} dataIndex The name of the field in the grid's {@link Roo.data.Store}'s
+ * {@link Roo.data.Record} definition from which to draw the column's value. If not
+ * specified, the column's index is used as an index into the Record's data Array.
+ */
+ /**
+ * @cfg {Number} width The initial width in pixels of the column. Using this
+ * instead of {@link Roo.grid.Grid#autoSizeColumns} is more efficient.
+ */
+ /**
+ * @cfg {Boolean} sortable True if sorting is to be allowed on this column.
+ * Defaults to the value of the {@link #defaultSortable} property.
+ * Whether local/remote sorting is used is specified in {@link Roo.data.Store#remoteSort}.
+ */
+ /**
+ * @cfg {Boolean} locked True to lock the column in place while scrolling the Grid. Defaults to false.
+ */
+ /**
+ * @cfg {Boolean} fixed True if the column width cannot be changed. Defaults to false.
+ */
+ /**
+ * @cfg {Boolean} resizable False to disable column resizing. Defaults to true.
+ */
+ /**
+ * @cfg {Boolean} hidden True to hide the column. Defaults to false.
+ */
+ /**
+ * @cfg {Function} renderer A function used to generate HTML markup for a cell
+ * given the cell's data value. See {@link #setRenderer}. If not specified, the
+ * default renderer returns the escaped data value. If an object is returned (bootstrap only)
+ * then it is treated as a Roo Component object instance, and it is rendered after the initial row is rendered
*/
/**
- * @cfg {Roo.grid.GridEditor} editor (Optional) For grid editors - returns the grid editor
+ * @cfg {Roo.grid.GridEditor} editor For grid editors - returns the grid editor
*/
/**
- * @cfg {String} align (Optional) Set the CSS text-align property of the column. Defaults to undefined.
+ * @cfg {String} align (left|right) Set the CSS text-align property of the column. Defaults to undefined (left).
*/
/**
- * @cfg {String} valign (Optional) Set the CSS vertical-align property of the column (eg. middle, top, bottom etc). Defaults to undefined.
+ * @cfg {String} valign (top|bottom|middle) Set the CSS vertical-align property of the column (eg. middle, top, bottom etc). Defaults to undefined (middle)
*/
/**
- * @cfg {String} cursor (Optional)
+ * @cfg {String} cursor ( auto|default|none|context-menu|help|pointer|progress|wait|cell|crosshair|text|vertical-text|alias|copy|move|no-drop|not-allowed|e-resize|n-resize|ne-resize|nw-resize|s-resize|se-resize|sw-resize|w-resize|ew-resize|ns-resize|nesw-resize|nwse-resize|col-resize|row-resize|all-scroll|zoom-in|zoom-out|grab|grabbing)
*/
/**
- * @cfg {String} tooltip (Optional)
+ * @cfg {String} tooltip mouse over tooltip text
*/
/**
- * @cfg {Number} xs (Optional)
+ * @cfg {Number} xs can be '0' for hidden at this size (number less than 12)
*/
/**
- * @cfg {Number} sm (Optional)
+ * @cfg {Number} sm can be '0' for hidden at this size (number less than 12)
*/
/**
- * @cfg {Number} md (Optional)
+ * @cfg {Number} md can be '0' for hidden at this size (number less than 12)
*/
/**
- * @cfg {Number} lg (Optional)
+ * @cfg {Number} lg can be '0' for hidden at this size (number less than 12)
+ */
+ /**
+ * @cfg {Number} xl can be '0' for hidden at this size (number less than 12)
*/
/**
* Returns the id of the column at the specified index.
/**
- * 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
*/
/**
* Returns the width for the specified column.
* @param {Number} col The column index
+ * @param (optional) {String} gridSize bootstrap width size.
* @return {Number}
*/
- getColumnWidth : function(col){
- return this.config[col].width * 1 || this.defaultWidth;
+ getColumnWidth : function(col, gridSize)
+ {
+ var cfg = this.config[col];
+
+ if (typeof(gridSize) == 'undefined') {
+ return cfg.width * 1 || this.defaultWidth;
+ }
+ if (gridSize === false) { // if we set it..
+ return cfg.width || false;
+ }
+ var sizes = ['xl', 'lg', 'md', 'sm', 'xs'];
+
+ for(var i = sizes.indexOf(gridSize); i < sizes.length; i++) {
+ if (typeof(cfg[ sizes[i] ] ) == 'undefined') {
+ continue;
+ }
+ return cfg[ sizes[i] ];
+ }
+ return 1;
+
},
/**
*/
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)
* True to create a single-use mask that is automatically destroyed after loading (useful for page loads),
* False to persist the mask element reference for multiple uses (e.g., for paged data widgets). Defaults to false.
*/
+ removeMask : false,
/**
* @cfg {String} msg
* The text to display in a centered loading message box (defaults to 'Loading...')
um.un('failure', this.onLoad, this);
}
}
-};/*
- * - LGPL
- *
- * table
- *
- */
-
-/**
+};/**
* @class Roo.bootstrap.Table
+ * @licence LGBL
* @extends Roo.bootstrap.Component
- * Bootstrap Table class
- * @cfg {String} cls table class
- * @cfg {String} align (left|center|right) Specifies the alignment of a table according to surrounding text
- * @cfg {String} bgcolor Specifies the background color for a table
- * @cfg {Number} border Specifies whether the table cells should have borders or not
- * @cfg {Number} cellpadding Specifies the space between the cell wall and the cell content
- * @cfg {Number} cellspacing Specifies the space between cells
- * @cfg {String} frame Specifies which parts of the outside borders that should be visible
- * @cfg {String} rules Specifies which parts of the inside borders that should be visible
- * @cfg {String} sortable Specifies that the table should be sortable
- * @cfg {String} summary Specifies a summary of the content of a table
- * @cfg {Number} width Specifies the width of a table
- * @cfg {String} layout table layout (auto | fixed | initial | inherit)
+ * @children Roo.bootstrap.TableBody
+ * Bootstrap Table class. This class represents the primary interface of a component based grid control.
+ * Similar to Roo.grid.Grid
+ * <pre><code>
+ var table = Roo.factory({
+ xtype : 'Table',
+ xns : Roo.bootstrap,
+ autoSizeColumns: true,
+
+
+ store : {
+ xtype : 'Store',
+ xns : Roo.data,
+ remoteSort : true,
+ sortInfo : { direction : 'ASC', field: 'name' },
+ proxy : {
+ xtype : 'HttpProxy',
+ xns : Roo.data,
+ method : 'GET',
+ url : 'https://example.com/some.data.url.json'
+ },
+ reader : {
+ xtype : 'JsonReader',
+ xns : Roo.data,
+ fields : [ 'id', 'name', whatever' ],
+ id : 'id',
+ root : 'data'
+ }
+ },
+ cm : [
+ {
+ xtype : 'ColumnModel',
+ xns : Roo.grid,
+ align : 'center',
+ cursor : 'pointer',
+ dataIndex : 'is_in_group',
+ header : "Name",
+ sortable : true,
+ renderer : function(v, x , r) {
+
+ return String.format("{0}", v)
+ }
+ width : 3
+ } // more columns..
+ ],
+ selModel : {
+ xtype : 'RowSelectionModel',
+ xns : Roo.bootstrap.Table
+ // you can add listeners to catch selection change here....
+ }
+
+
+ });
+ // set any options
+ grid.render(Roo.get("some-div"));
+</code></pre>
+
+Currently the Table uses multiple headers to try and handle XL / Medium etc... styling
+
+
+
+ *
+ * @cfg {Roo.grid.AbstractSelectionModel} sm The selection model to use (cell selection is not supported yet)
+ * @cfg {Roo.data.Store} store The data store to use
+ * @cfg {Roo.grid.ColumnModel} cm[] A column for the grid.
*
+ * @cfg {String} cls table class
+ *
+ *
+ * @cfg {string} empty_results Text to display for no results
* @cfg {boolean} striped Should the rows be alternative striped
* @cfg {boolean} bordered Add borders to the table
* @cfg {boolean} hover Add hover highlighting
* @cfg {boolean} condensed Format condensed
- * @cfg {boolean} responsive Format condensed
+ * @cfg {boolean} responsive default false - if this is on, columns are rendered with col-xs-4 etc. classes, otherwise columns will be sized by CSS,
+ * also adds table-responsive (see bootstrap docs for details)
* @cfg {Boolean} loadMask (true|false) default false
* @cfg {Boolean} footerShow (true|false) generate tfoot, default true
* @cfg {Boolean} headerShow (true|false) generate thead, default true
* @cfg {Boolean} rowSelection (true|false) default false
* @cfg {Boolean} cellSelection (true|false) default false
- * @cfg {Boolean} scrollBody (true|false) default false - body scrolled / fixed header
+ * @cfg {Boolean} scrollBody (true|false) default false - body scrolled / fixed header (with resizable columns)
* @cfg {Roo.bootstrap.PagingToolbar} footer a paging toolbar
* @cfg {Boolean} lazyLoad auto load data while scrolling to the end (default false)
* @cfg {Boolean} auto_hide_footer auto hide footer if only one page (default false)
-
+ * @cfg {Boolean} enableColumnResize default true if columns can be resized = needs scrollBody to be set to work (drag/drop)
+ *
+ *
+ * @cfg {Number} minColumnWidth default 50 pixels minimum column width
*
* @constructor
* Create a new Table
* @param {Object} config The config object
*/
-Roo.bootstrap.Table = function(config){
+Roo.bootstrap.Table = function(config)
+{
Roo.bootstrap.Table.superclass.constructor.call(this, config);
-
-
-
+
// BC...
this.rowSelection = (typeof(config.rowSelection) != 'undefined') ? config.rowSelection : this.rowSelection;
this.cellSelection = (typeof(config.cellSelection) != 'undefined') ? config.cellSelection : this.cellSelection;
this.headerShow = (typeof(config.thead) != 'undefined') ? config.thead : this.headerShow;
this.footerShow = (typeof(config.tfoot) != 'undefined') ? config.tfoot : this.footerShow;
+ this.view = this; // compat with grid.
+
this.sm = this.sm || {xtype: 'RowSelectionModel'};
if (this.sm) {
this.sm.grid = this;
- this.selModel = Roo.factory(this.sm, Roo.bootstrap.Table);
+ this.selModel = Roo.factory(this.sm, Roo.grid);
this.sm = this.selModel;
this.sm.xmodule = this.xmodule || false;
}
* @param {Number} columnIndex
* @param {Roo.EventObject} e
*/
- "headercontextmenu" : true
+ "headercontextmenu" : true,
+ /**
+ * @event mousedown
+ * The raw mousedown event for the entire grid.
+ * @param {Roo.EventObject} e
+ */
+ "mousedown" : true
+
});
};
Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, {
cls: false,
- align: false,
- bgcolor: false,
- border: false,
- cellpadding: false,
- cellspacing: false,
- frame: false,
- rules: false,
- sortable: false,
- summary: false,
- width: false,
+
+ empty_results : '',
striped : false,
scrollBody : false,
bordered: false,
loadMask : false,
footerShow : true,
headerShow : true,
+ enableColumnResize: true,
rowSelection : false,
cellSelection : false,
layout : false,
+
+ minColumnWidth : 50,
// Roo.Element - the tbody
- mainBody: false,
- // Roo.Element - thead element
- mainHead: false,
+ bodyEl: false, // <tbody> Roo.Element - thead element
+ headEl: false, // <thead> Roo.Element - thead element
+ resizeProxy : false, // proxy element for dragging?
+
+
container: false, // used by gridpanel...
auto_hide_footer : false,
+ view: false, // actually points to this..
+
getAutoCreate : function()
{
var cfg = Roo.apply({}, Roo.bootstrap.Table.superclass.getAutoCreate.call(this));
cfg = {
tag: 'table',
- cls : 'table',
+ cls : 'table',
cn : []
};
+ // this get's auto added by panel.Grid
if (this.scrollBody) {
cfg.cls += ' table-body-fixed';
}
if (this.condensed) {
cfg.cls += ' table-condensed';
}
+
if (this.responsive) {
cfg.cls += ' table-responsive';
}
cfg.cls+= ' ' +this.cls;
}
- // this lot should be simplifed...
- var _t = this;
- var cp = [
- 'align',
- 'bgcolor',
- 'border',
- 'cellpadding',
- 'cellspacing',
- 'frame',
- 'rules',
- 'sortable',
- 'summary',
- 'width'
- ].forEach(function(k) {
- if (_t[k]) {
- cfg[k] = _t[k];
- }
- });
if (this.layout) {
//Roo.log('initEvents with ds!!!!');
- this.mainBody = this.el.select('tbody', true).first();
- this.mainHead = this.el.select('thead', true).first();
+ this.bodyEl = this.el.select('tbody', true).first();
+ this.headEl = this.el.select('thead', true).first();
this.mainFoot = this.el.select('tfoot', true).first();
- 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);
// why is this done????? = it breaks dialogs??
//this.parent().el.setStyle('position', 'relative');
this.el.on("contextmenu", this.onContextMenu, this);
- this.mainBody.on('scroll', this.onBodyScroll, this);
this.cm.on("headerchange", this.onHeaderChange, this);
-
this.cm.on("hiddenchange", this.onHiddenChange, this, arguments);
+
+ //?? does bodyEl get replaced on render?
+ this.bodyEl.on("click", this.onClick, this);
+ this.bodyEl.on("dblclick", this.onDblClick, this);
+ this.bodyEl.on('scroll', this.onBodyScroll, this);
+
+ // guessing mainbody will work - this relays usually caught by selmodel at present.
+ this.relayEvents(this.bodyEl, ["mousedown","mouseup","mouseover","mouseout","keypress"]);
+
+
+ this.resizeProxy = Roo.get(document.body).createChild({ cls:"x-grid-resize-proxy", html: ' ' });
+
+ if(this.headEl && this.enableColumnResize !== false && Roo.grid.SplitDragZone){
+ new Roo.grid.SplitDragZone(this, this.headEl.dom, false); // not sure what 'lockedHd is for this implementation..)
+ }
+
+ this.initCSS();
+ },
+ // Compatibility with grid - we implement all the view features at present.
+ getView : function()
+ {
+ return this;
},
+ initCSS : function()
+ {
+
+
+ var cm = this.cm, styles = [];
+ this.CSS.removeStyleSheet(this.id + '-cssrules');
+ var headHeight = this.headEl ? this.headEl.dom.clientHeight : 0;
+ // we can honour xs/sm/md/xl as widths...
+ // we first have to decide what widht we are currently at...
+ var sz = Roo.getGridSize();
+
+ var total = 0;
+ var last = -1;
+ var cols = []; // visable cols.
+ var total_abs = 0;
+ for(var i = 0, len = cm.getColumnCount(); i < len; i++) {
+ var w = cm.getColumnWidth(i, false);
+ if(cm.isHidden(i)){
+ cols.push( { rel : false, abs : 0 });
+ continue;
+ }
+ if (w !== false) {
+ cols.push( { rel : false, abs : w });
+ total_abs += w;
+ last = i; // not really..
+ continue;
+ }
+ var w = cm.getColumnWidth(i, sz);
+ if (w > 0) {
+ last = i
+ }
+ total += w;
+ cols.push( { rel : w, abs : false });
+ }
+
+ var avail = this.bodyEl.dom.clientWidth - total_abs;
+
+ var unitWidth = Math.floor(avail / total);
+ var rem = avail - (unitWidth * total);
+
+ var hidden, width, pos = 0 , splithide , left;
+ for(var i = 0, len = cm.getColumnCount(); i < len; i++) {
+
+ hidden = 'display:none;';
+ left = '';
+ width = 'width:0px;';
+ splithide = '';
+ if(!cm.isHidden(i)){
+ hidden = '';
+
+
+ // we can honour xs/sm/md/xl ?
+ var w = cols[i].rel == false ? cols[i].abs : (cols[i].rel * unitWidth);
+ if (w===0) {
+ hidden = 'display:none;';
+ }
+ // width should return a small number...
+ if (i == last) {
+ w+=rem; // add the remaining with..
+ }
+ pos += w;
+ left = "left:" + (pos -4) + "px;";
+ width = "width:" + w+ "px;";
+
+ }
+ if (this.responsive) {
+ width = '';
+ left = '';
+ hidden = cm.isHidden(i) ? 'display:none;' : '';
+ splithide = 'display: none;';
+ }
+
+ styles.push( '#' , this.id , ' .x-col-' , i, " {", cm.config[i].css, width, hidden, "}\n" );
+ if (this.headEl) {
+ if (i == last) {
+ splithide = 'display:none;';
+ }
+
+ styles.push('#' , this.id , ' .x-hcol-' , i, " { ", width, hidden," }\n",
+ '#' , this.id , ' .x-grid-split-' , i, " { ", left, splithide, 'height:', (headHeight - 4), "px;}\n",
+ // this is the popover version..
+ '.popover-inner #' , this.id , ' .x-grid-split-' , i, " { ", left, splithide, 'height:', 100, "%;}\n"
+ );
+ }
+
+ }
+ //Roo.log(styles.join(''));
+ this.CSS.createStyleSheet( styles.join(''), this.id + '-cssrules');
+
+ },
+
+
+
onContextMenu : function(e, t)
{
this.processEvent("contextmenu", e);
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)
this.fireEvent('rowdblclick', this, row, rowIndex, e);
}
},
-
+ findRowIndex : function(el)
+ {
+ var cell = Roo.get(el);
+ if(!cell) {
+ return false;
+ }
+ var row = cell.findParent('tr', false, true);
+
+ if(!row || typeof(row) == 'undefined'){
+ return false;
+ }
+ return this.getRowIndex(row);
+ },
sort : function(e,el)
{
var col = Roo.get(el);
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';
}
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 = '<i class="glyphicon"></i>' + c.html;
+ c.cls += ' sortable';
+ c.html = '<i class="fa"></i>' + c.html;
}
// could use BS4 hidden-..-down
c.colspan = config.colspan;
}
- if(typeof(config.hidden) != 'undefined' && config.hidden){
- c.style += ' display:none;';
- }
+ // hidden is handled by CSS now
if(typeof(config.dataIndex) != 'undefined'){
c.sort = config.dataIndex;
c.style += ' text-align:' + config.align + ';';
}
- if(typeof(config.width) != 'undefined'){
+ /* width is done in CSS
+ *if(typeof(config.width) != 'undefined'){
c.style += ' width:' + config.width + 'px;';
this.totalWidth += config.width;
} else {
this.totalWidth += 100; // assume minimum of 100 per column?
}
+ */
if(typeof(config.cls) != 'undefined'){
c.cls = (typeof(c.cls) == 'undefined') ? config.cls : (c.cls + ' ' + config.cls);
}
+ // this is the bit that doesnt reall work at all...
- ['xs','sm','md','lg'].map(function(size){
-
- if(typeof(config[size]) == 'undefined'){
- return;
- }
+ if (this.responsive) {
- if (!config[size]) { // 0 = hidden
- // BS 4 '0' is treated as hide that column and below.
- c.cls += ' hidden-' + size + ' hidden' + size + '-down';
- return;
- }
-
- c.cls += ' col-' + size + '-' + config[size] + (
- size == 'xs' ? (' col-' + config[size] ) : '' // bs4 col-{num} replaces col-xs
- );
-
-
- });
+
+ ['xs','sm','md','lg'].map(function(size){
+
+ if(typeof(config[size]) == 'undefined'){
+ return;
+ }
+
+ if (!config[size]) { // 0 = hidden
+ // BS 4 '0' is treated as hide that column and below.
+ c.cls += ' hidden-' + size + ' hidden' + size + '-down';
+ return;
+ }
+
+ c.cls += ' col-' + size + '-' + config[size] + (
+ size == 'xs' ? (' col-' + config[size] ) : '' // bs4 col-{num} replaces col-xs
+ );
+
+
+ });
+ }
+ // at the end?
+
+ c.html +=' <span class="x-grid-split x-grid-split-' + i + '"></span>';
+
+
+
header.cn.push(c)
}
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']);
}
}
});
- var tbody = this.mainBody;
+ var tbody = this.bodyEl;
if(ds.getCount() > 0){
ds.data.each(function(d,rowIndex){
}
}, this);
+ } else if (this.empty_results.length) {
+ this.el.mask(this.empty_results, 'no-spinner');
}
var tfoot = this.el.select('tfoot', true).first();
this.fireEvent('rowsrendered', this);
this.autoSize();
+
+ this.initCSS(); /// resize cols
+
+
},
if(isUpdate !== true){
this.fireEvent("beforerowremoved", this, index, record);
}
- var bt = this.mainBody.dom;
+ var bt = this.bodyEl.dom;
var rows = this.el.select('tbody > tr', true).elements;
{
//Roo.log('on Add called');
// - note this does not handle multiple adding very well..
- var bt = this.mainBody.dom;
+ var bt = this.bodyEl.dom;
for (var i =0 ; i < records.length;i++) {
//Roo.log('call insert row Add called on ' + rowIndex + ':' + i);
//Roo.log(records[i]);
//this.layout();
this.fireEvent("rowupdated", this, index, record);
},
+ // private - called by RowSelection
+ onRowSelect : function(rowIndex){
+ var row = this.getRowDom(rowIndex);
+ row.addClass(['bg-info','info']);
+ },
+ // private - called by RowSelection
+ onRowDeselect : function(rowIndex)
+ {
+ if (rowIndex < 0) {
+ return;
+ }
+ var row = this.getRowDom(rowIndex);
+ row.removeClass(['bg-info','info']);
+ },
+ /**
+ * Focuses the specified row.
+ * @param {Number} row The row index
+ */
+ focusRow : function(row)
+ {
+ //Roo.log('GridView.focusRow');
+ var x = this.bodyEl.dom.scrollLeft;
+ this.focusCell(row, 0, false);
+ this.bodyEl.dom.scrollLeft = x;
+
+ },
+ /**
+ * Focuses the specified cell.
+ * @param {Number} row The row index
+ * @param {Number} col The column index
+ * @param {Boolean} hscroll false to disable horizontal scrolling
+ */
+ focusCell : function(row, col, hscroll)
+ {
+ //Roo.log('GridView.focusCell');
+ var el = this.ensureVisible(row, col, hscroll);
+ // not sure what focusEL achives = it's a <a> pos relative
+ //this.focusEl.alignTo(el, "tl-tl");
+ //if(Roo.isGecko){
+ // this.focusEl.focus();
+ //}else{
+ // this.focusEl.focus.defer(1, this.focusEl);
+ //}
+ },
+
+ /**
+ * Scrolls the specified cell into view
+ * @param {Number} row The row index
+ * @param {Number} col The column index
+ * @param {Boolean} hscroll false to disable horizontal scrolling
+ */
+ ensureVisible : function(row, col, hscroll)
+ {
+ //Roo.log('GridView.ensureVisible,' + row + ',' + col);
+ //return null; //disable for testing.
+ if(typeof row != "number"){
+ row = row.rowIndex;
+ }
+ if(row < 0 && row >= this.ds.getCount()){
+ return null;
+ }
+ col = (col !== undefined ? col : 0);
+ var cm = this.cm;
+ while(cm.isHidden(col)){
+ col++;
+ }
+
+ var el = this.getCellDom(row, col);
+ if(!el){
+ return null;
+ }
+ var c = this.bodyEl.dom;
+
+ var ctop = parseInt(el.offsetTop, 10);
+ var cleft = parseInt(el.offsetLeft, 10);
+ var cbot = ctop + el.offsetHeight;
+ var cright = cleft + el.offsetWidth;
+
+ //var ch = c.clientHeight - this.mainHd.dom.offsetHeight;
+ var ch = 0; //?? header is not withing the area?
+ var stop = parseInt(c.scrollTop, 10);
+ var sleft = parseInt(c.scrollLeft, 10);
+ var sbot = stop + ch;
+ var sright = sleft + c.clientWidth;
+ /*
+ Roo.log('GridView.ensureVisible:' +
+ ' ctop:' + ctop +
+ ' c.clientHeight:' + c.clientHeight +
+ ' this.mainHd.dom.offsetHeight:' + this.mainHd.dom.offsetHeight +
+ ' stop:' + stop +
+ ' cbot:' + cbot +
+ ' sbot:' + sbot +
+ ' ch:' + ch
+ );
+ */
+ if(ctop < stop){
+ c.scrollTop = ctop;
+ //Roo.log("set scrolltop to ctop DISABLE?");
+ }else if(cbot > sbot){
+ //Roo.log("set scrolltop to cbot-ch");
+ c.scrollTop = cbot-ch;
+ }
+
+ if(hscroll !== false){
+ if(cleft < sleft){
+ c.scrollLeft = cleft;
+ }else if(cright > sright){
+ c.scrollLeft = cright-c.clientWidth;
+ }
+ }
+
+ return el;
+ },
+
insertRow : function(dm, rowIndex, isUpdate){
//var s = this.getScrollState();
var row = this.renderRow(this.cm, this.store, rowIndex);
// insert before rowIndex..
- var e = this.mainBody.createChild(row,this.getRowDom(rowIndex));
+ var e = this.bodyEl.createChild(row,this.getRowDom(rowIndex));
var _this = this;
return (typeof(rows[rowIndex]) == 'undefined') ? false : rows[rowIndex];
},
+ getCellDom : function(rowIndex, colIndex)
+ {
+ var row = this.getRowDom(rowIndex);
+ if (row === false) {
+ return false;
+ }
+ var cols = row.select('td', true).elements;
+ return (typeof(cols[colIndex]) == 'undefined') ? false : cols[colIndex];
+
+ },
+
// returns the object tree for a tr..
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
td.colspan = config.colspan;
}
- if(typeof(config.hidden) != 'undefined' && config.hidden){
- td.style += ' display:none;';
- }
+
if(typeof(config.align) != 'undefined' && config.align.length){
td.style += ' text-align:' + config.align + ';';
if(typeof(config.valign) != 'undefined' && config.valign.length){
td.style += ' vertical-align:' + config.valign + ';';
}
-
+ /*
if(typeof(config.width) != 'undefined'){
td.style += ' width:' + config.width + 'px;';
}
+ */
if(typeof(config.cursor) != 'undefined'){
td.style += ' cursor:' + config.cursor + ';';
if(typeof(config.cls) != 'undefined'){
td.cls = (typeof(td.cls) == 'undefined') ? config.cls : (td.cls + ' ' + config.cls);
}
-
- ['xs','sm','md','lg'].map(function(size){
-
- if(typeof(config[size]) == 'undefined'){
- return;
- }
-
-
-
- if (!config[size]) { // 0 = hidden
- // BS 4 '0' is treated as hide that column and below.
- td.cls += ' hidden-' + size + ' hidden' + size + '-down';
- return;
- }
-
- td.cls += ' col-' + size + '-' + config[size] + (
- size == 'xs' ? (' col-' + config[size] ) : '' // bs4 col-{num} replaces col-xs
- );
-
-
- });
-
+ if (this.responsive) {
+ ['xs','sm','md','lg'].map(function(size){
+
+ if(typeof(config[size]) == 'undefined'){
+ return;
+ }
+
+
+
+ if (!config[size]) { // 0 = hidden
+ // BS 4 '0' is treated as hide that column and below.
+ td.cls += ' hidden-' + size + ' hidden' + size + '-down';
+ return;
+ }
+
+ td.cls += ' col-' + size + '-' + config[size] + (
+ size == 'xs' ? (' col-' + config[size] ) : '' // bs4 col-{num} replaces col-xs
+ );
+
+
+ });
+ }
row.cn.push(td);
}
onBeforeLoad : function()
{
-
+ this.el.unmask(); // if needed.
},
/**
* Remove all rows
*/
setRowVisibility : function(rowIndex, state)
{
- var bt = this.mainBody.dom;
+ var bt = this.bodyEl.dom;
var rows = this.el.select('tbody > tr', true).elements;
if(typeof(rows[rowIndex]) == 'undefined'){
return;
}
- rows[rowIndex].dom.style.display = state ? '' : 'none';
+ rows[rowIndex][ state ? 'removeClass' : 'addClass']('d-none');
+
},
})
}
},
-
+ /**
+ * get the Row Index from a dom element.
+ * @param {Roo.Element} row The row to look for
+ * @returns {Number} the row
+ */
getRowIndex : function(row)
{
var rowIndex = -1;
});
return rowIndex;
+ },
+ /**
+ * get the header TH element for columnIndex
+ * @param {Number} columnIndex
+ * @returns {Roo.Element}
+ */
+ getHeaderIndex: function(colIndex)
+ {
+ var cols = this.headEl.select('th', true).elements;
+ return cols[colIndex];
+ },
+ /**
+ * get the Column Index from a dom element. (using regex on x-hcol-{colid})
+ * @param {domElement} cell to look for
+ * @returns {Number} the column
+ */
+ getCellIndex : function(cell)
+ {
+ var id = String(cell.className).match(Roo.bootstrap.Table.cellRE);
+ if(id){
+ return parseInt(id[1], 10);
+ }
+ return 0;
},
/**
* Returns the grid's underlying element = used by panel.Grid
}
cw = Math.max(cw, this.totalWidth);
this.getGridEl().select('tbody tr',true).setWidth(cw);
+ this.initCSS();
// resize 'expandable coloumn?
},
onBodyScroll: function()
{
- //Roo.log("body scrolled');" + this.mainBody.dom.scrollLeft);
- if(this.mainHead){
- this.mainHead.setStyle({
+ //Roo.log("body scrolled');" + this.bodyEl.dom.scrollLeft);
+ if(this.headEl){
+ this.headEl.setStyle({
'position' : 'relative',
- 'left': (-1* this.mainBody.dom.scrollLeft) + 'px'
+ 'left': (-1* this.bodyEl.dom.scrollLeft) + 'px'
});
}
if(this.lazyLoad){
- var scrollHeight = this.mainBody.dom.scrollHeight;
+ var scrollHeight = this.bodyEl.dom.scrollHeight;
- var scrollTop = Math.ceil(this.mainBody.getScroll().top);
+ var scrollTop = Math.ceil(this.bodyEl.getScroll().top);
- var height = this.mainBody.getHeight();
+ var height = this.bodyEl.getHeight();
if(scrollHeight - height == scrollTop) {
}
},
-
+ onColumnSplitterMoved : function(i, diff)
+ {
+ this.userResized = true;
+
+ var cm = this.colModel;
+
+ var w = this.getHeaderIndex(i).getWidth() + diff;
+
+
+ cm.setColumnWidth(i, w, true);
+ this.initCSS();
+ //var cid = cm.getColumnId(i); << not used in this version?
+ /* Roo.log(['#' + this.id + ' .x-col-' + i, "width", w + "px"]);
+
+ this.CSS.updateRule( '#' + this.id + ' .x-col-' + i, "width", w + "px");
+ this.CSS.updateRule('#' + this.id + ' .x-hcol-' + i, "width", w + "px");
+ this.CSS.updateRule('#' + this.id + ' .x-grid-split-' + i, "left", w + "px");
+*/
+ //this.updateSplitters();
+ //this.layout(); << ??
+ this.fireEvent("columnresize", i, w);
+ },
onHeaderChange : function()
{
var header = this.renderHeader();
var table = this.el.select('table', true).first();
- this.mainHead.remove();
- this.mainHead = table.createChild(header, this.mainBody, false);
+ this.headEl.remove();
+ this.headEl = table.createChild(header, this.bodyEl, false);
+
+ Roo.each(this.el.select('thead th.sortable', true).elements, function(e){
+ e.on('click', this.sort, this);
+ }, this);
+
+ if(this.enableColumnResize !== false && Roo.grid.SplitDragZone){
+ new Roo.grid.SplitDragZone(this, this.headEl.dom, false); // not sure what 'lockedHd is for this implementation..)
+ }
+
},
onHiddenChange : function(colModel, colIndex, hidden)
{
+ /*
+ this.cm.setHidden()
var thSelector = '#' + this.id + ' .x-hcol-' + colIndex;
var tdSelector = '#' + this.id + ' .x-col-' + colIndex;
this.CSS.updateRule(thSelector, "display", "none");
this.CSS.updateRule(tdSelector, "display", "none");
}
-
+ */
+ // onload calls initCSS()
this.onHeaderChange();
this.onLoad();
},
}
});
-
+// currently only used to find the split on drag..
+Roo.bootstrap.Table.cellRE = /(?:.*?)x-grid-(?:hd|cell|split)-([\d]+)(?:.*?)/;
- /*
+/**
+ * @depricated
+*/
+Roo.bootstrap.Table.AbstractSelectionModel = Roo.grid.AbstractSelectionModel;
+Roo.bootstrap.Table.RowSelectionModel = Roo.grid.RowSelectionModel;
+/*
* - LGPL
*
* table cell
/**
* @class Roo.bootstrap.TableCell
* @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.Component
+ * @parent Roo.bootstrap.TableRow
* Bootstrap TableCell class
+ *
* @cfg {String} html cell contain text
* @cfg {String} cls cell class
* @cfg {String} tag cell tag (td|th) default td
/**
* @class Roo.bootstrap.TableRow
* @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.TableCell
+ * @parent Roo.bootstrap.TableBody
* Bootstrap TableRow class
* @cfg {String} cls row class
* @cfg {String} align Aligns the content in a table row
/**
* @class Roo.bootstrap.TableBody
* @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.TableRow
+ * @parent Roo.bootstrap.Table
* Bootstrap TableBody class
* @cfg {String} cls element class
* @cfg {String} tag element tag (thead|tbody|tfoot) default tbody
*/
/**
- * @class Roo.bootstrap.Form
+ * @class Roo.bootstrap.form.Form
* @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.Component
* Bootstrap Form class
* @cfg {String} method GET | POST (default POST)
* @cfg {String} labelAlign top | left (default top)
*/
-Roo.bootstrap.Form = function(config){
+Roo.bootstrap.form.Form = function(config){
- Roo.bootstrap.Form.superclass.constructor.call(this, config);
+ Roo.bootstrap.form.Form.superclass.constructor.call(this, config);
- Roo.bootstrap.Form.popover.apply();
+ Roo.bootstrap.form.Form.popover.apply();
this.addEvents({
/**
});
};
-Roo.extend(Roo.bootstrap.Form, Roo.bootstrap.Component, {
+Roo.extend(Roo.bootstrap.form.Form, Roo.bootstrap.Component, {
/**
* @cfg {String} method
});
if(this.errorMask && !valid){
- Roo.bootstrap.Form.popover.mask(this, target);
+ Roo.bootstrap.form.Form.popover.mask(this, target);
}
return valid;
});
-Roo.apply(Roo.bootstrap.Form, {
+Roo.apply(Roo.bootstrap.form.Form, {
popover : {
this.toolTip.show(tip);
this.intervalID = window.setInterval(function() {
- Roo.bootstrap.Form.popover.unmask();
+ Roo.bootstrap.form.Form.popover.unmask();
}, 10000);
window.onwheel = function(){ return false;};
/**
* @class Roo.form.VTypes
* Overridable validation definitions. The validations provided are basic and intended to be easily customizable and extended.
- * @singleton
+ * @static
*/
Roo.form.VTypes = function(){
// closure these in so they are only created once.
*/
/**
- * @class Roo.bootstrap.Input
+ * @class Roo.bootstrap.form.Input
* @extends Roo.bootstrap.Component
* Bootstrap Input class
* @cfg {Boolean} disabled is it disabled
- * @cfg {String} (button|checkbox|email|file|hidden|image|number|password|radio|range|reset|search|submit|text) inputType
+ * @cfg {String} inputType (button|checkbox|email|file|hidden|image|number|password|radio|range|reset|search|submit|text)
* @cfg {String} name name of the input
* @cfg {string} fieldLabel - the label associated
* @cfg {string} placeholder - placeholder to put in text.
- * @cfg {string} before - input group add on before
+ * @cfg {string} before - input group add on before
* @cfg {string} after - input group add on after
* @cfg {string} size - (lg|sm) or leave empty..
* @cfg {Number} xs colspan out of 12 for mobile-sized screens
* @cfg {String} capture (user|camera) use for file input only. (default empty)
* @cfg {String} accept (image|video|audio) use for file input only. (default empty)
* @cfg {Boolean} preventMark Do not show tick or cross if error/success
-
+ * @cfg {Roo.bootstrap.Button} before Button to show before
+ * @cfg {Roo.bootstrap.Button} afterButton to show before
* @cfg {String} align (left|center|right) Default left
* @cfg {Boolean} forceFeedback (true|false) Default false
*
* @param {Object} config The config object
*/
-Roo.bootstrap.Input = function(config){
+Roo.bootstrap.form.Input = function(config){
- Roo.bootstrap.Input.superclass.constructor.call(this, config);
+ Roo.bootstrap.form.Input.superclass.constructor.call(this, config);
this.addEvents({
/**
});
};
-Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component, {
+Roo.extend(Roo.bootstrap.form.Input, Roo.bootstrap.Component, {
/**
* @cfg {String/Boolean} validationEvent The event that should initiate field validation. Set to false to disable
automatic validation (defaults to "keyup").
*/
/**
- * @class Roo.bootstrap.TextArea
- * @extends Roo.bootstrap.Input
+ * @class Roo.bootstrap.form.TextArea
+ * @extends Roo.bootstrap.form.Input
* Bootstrap TextArea class
* @cfg {Number} cols Specifies the visible width of a text area
* @cfg {Number} rows Specifies the visible number of lines in a text area
* @param {Object} config The config object
*/
-Roo.bootstrap.TextArea = function(config){
- Roo.bootstrap.TextArea.superclass.constructor.call(this, config);
+Roo.bootstrap.form.TextArea = function(config){
+ Roo.bootstrap.form.TextArea.superclass.constructor.call(this, config);
};
-Roo.extend(Roo.bootstrap.TextArea, Roo.bootstrap.Input, {
+Roo.extend(Roo.bootstrap.form.TextArea, Roo.bootstrap.form.Input, {
cols : false,
rows : 5,
*/
/**
- * @class Roo.bootstrap.TriggerField
- * @extends Roo.bootstrap.Input
+ * @class Roo.bootstrap.form.TriggerField
+ * @extends Roo.bootstrap.form.Input
* Provides a convenient wrapper for TextFields that adds a clickable trigger button (looks like a combobox by default).
* The trigger has no default action, so you must assign a function to implement the trigger click handler by
* overriding {@link #onTriggerClick}. You can create a TriggerField directly, as it renders exactly like a combobox
* for which you can provide a custom implementation. For example:
* <pre><code>
-var trigger = new Roo.bootstrap.TriggerField();
+var trigger = new Roo.bootstrap.form.TriggerField();
trigger.onTriggerClick = myTriggerFn;
trigger.applyTo('my-field');
</code></pre>
*
* However, in general you will most likely want to use TriggerField as the base class for a reusable component.
- * {@link Roo.bootstrap.DateField} and {@link Roo.bootstrap.ComboBox} are perfect examples of this.
+ * {@link Roo.bootstrap.form.DateField} and {@link Roo.bootstrap.form.ComboBox} are perfect examples of this.
* @cfg {String} triggerClass An additional CSS class used to style the trigger button. The trigger will always get the
* class 'x-form-trigger' by default and triggerClass will be <b>appended</b> if specified.
* @cfg {String} caret (search|calendar) BS3 only - carat fa name
* @constructor
* Create a new TriggerField.
- * @param {Object} config Configuration options (valid {@Roo.bootstrap.Input} config options will also be applied
+ * @param {Object} config Configuration options (valid {@Roo.bootstrap.form.Input} config options will also be applied
* to the base TextField)
*/
-Roo.bootstrap.TriggerField = function(config){
+Roo.bootstrap.form.TriggerField = function(config){
this.mimicing = false;
- Roo.bootstrap.TriggerField.superclass.constructor.call(this, config);
+ Roo.bootstrap.form.TriggerField.superclass.constructor.call(this, config);
};
-Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input, {
+Roo.extend(Roo.bootstrap.form.TriggerField, Roo.bootstrap.form.Input, {
/**
* @cfg {String} triggerClass A CSS class to apply to the trigger
*/
// private
onResize : function(w, h){
-// Roo.bootstrap.TriggerField.superclass.onResize.apply(this, arguments);
+// Roo.bootstrap.form.TriggerField.superclass.onResize.apply(this, arguments);
// if(typeof w == 'number'){
// var x = w - this.trigger.getWidth();
// this.inputEl().setWidth(this.adjustWidth('input', x));
this.createList();
- Roo.bootstrap.TriggerField.superclass.initEvents.call(this);
+ Roo.bootstrap.form.TriggerField.superclass.initEvents.call(this);
//this.wrap = this.el.wrap({cls: "x-form-field-wrap"});
if(!this.multiple && this.showToggleBtn){
this.trigger = this.el.select('span.dropdown-toggle',true).first();
//if(this.wrap){
// this.wrap.remove();
//}
- Roo.bootstrap.TriggerField.superclass.onDestroy.call(this);
+ Roo.bootstrap.form.TriggerField.superclass.onDestroy.call(this);
},
// private
onFocus : function(){
- Roo.bootstrap.TriggerField.superclass.onFocus.call(this);
+ Roo.bootstrap.form.TriggerField.superclass.onFocus.call(this);
/*
if(!this.mimicing){
this.wrap.addClass('x-trigger-wrap-focus');
this.el.un("keydown", this.checkTab, this);
}
//this.wrap.removeClass('x-trigger-wrap-focus');
- Roo.bootstrap.TriggerField.superclass.onBlur.call(this);
+ Roo.bootstrap.form.TriggerField.superclass.onBlur.call(this);
},
// private
// private
onDisable : function(){
this.inputEl().dom.disabled = true;
- //Roo.bootstrap.TriggerField.superclass.onDisable.call(this);
+ //Roo.bootstrap.form.TriggerField.superclass.onDisable.call(this);
//if(this.wrap){
// this.wrap.addClass('x-item-disabled');
//}
// private
onEnable : function(){
this.inputEl().dom.disabled = false;
- //Roo.bootstrap.TriggerField.superclass.onEnable.call(this);
+ //Roo.bootstrap.form.TriggerField.superclass.onEnable.call(this);
//if(this.wrap){
// this.el.removeClass('x-item-disabled');
//}
*/
/**
- * @class Roo.bootstrap.CardUploader
+ * @class Roo.bootstrap.form.CardUploader
* @extends Roo.bootstrap.Button
* Bootstrap Card Uploader class - it's a button which when you add files to it, adds cards below with preview and the name...
* @cfg {Number} errorTimeout default 3000
* @param {Object} config The config object
*/
-Roo.bootstrap.CardUploader = function(config){
+Roo.bootstrap.form.CardUploader = function(config){
- Roo.bootstrap.CardUploader.superclass.constructor.call(this, config);
+ Roo.bootstrap.form.CardUploader.superclass.constructor.call(this, config);
this.fileCollection = new Roo.util.MixedCollection(false,function(r) {
});
};
-Roo.extend(Roo.bootstrap.CardUploader, Roo.bootstrap.Input, {
+Roo.extend(Roo.bootstrap.form.CardUploader, Roo.bootstrap.form.Input, {
errorTimeout : 3000,
initEvents : function()
{
- Roo.bootstrap.Input.prototype.initEvents.call(this);
+ Roo.bootstrap.form.Input.prototype.initEvents.call(this);
var t = this;
this.addxtype({
var url = _this.urlAPI.createObjectURL( file);
this.addCard({
- id : Roo.bootstrap.CardUploader.ID--,
+ id : Roo.bootstrap.form.CardUploader.ID--,
is_uploaded : false,
src : url,
srcfile : file,
});
-Roo.bootstrap.CardUploader.ID = -1;/*
+Roo.bootstrap.form.CardUploader.ID = -1;/*
* Based on:
* Ext JS Library 1.1.1
* Copyright(c) 2006-2007, Ext JS, LLC.
/**
* @class Roo.data.SortTypes
- * @singleton
+ * @static
* Defines the default sorting (casting?) comparison functions used when sorting data.
*/
Roo.data.SortTypes = {
*/
/**
- * @cfg {Roo.data.DataProxy} proxy The Proxy object which provides access to a data object.
+ * @cfg {Roo.data.DataProxy} proxy [required] The Proxy object which provides access to a data object.
*/
/**
* @cfg {Array} data Inline data to be loaded when the store is initialized.
*/
/**
- * @cfg {Roo.data.Reader} reader The Reader object which processes the data object and returns
+ * @cfg {Roo.data.DataReader} reader [required] The Reader object which processes the data object and returns
* an Array of Roo.data.record objects which are cached keyed by their <em>id</em> property.
*/
/**
* <p>
* @param {Object} options An object containing properties which control loading options:<ul>
* <li>params {Object} An object containing properties to pass as HTTP parameters to a remote data source.</li>
+ * <li>params.data {Object} if you are using a MemoryProxy / JsonReader, use this as the data to load stuff..
+ * <pre>
+ {
+ data : data, // array of key=>value data like JsonReader
+ total : data.length,
+ success : true
+
+ }
+ </pre>
+ }.</li>
* <li>callback {Function} A function to be called after the Records have been loaded. The callback is
* passed the following arguments:<ul>
* <li>r : Roo.data.Record[]</li>
// private
// Called as a callback by the Reader during a load operation.
loadRecords : function(o, options, success){
- if(!o || success === false){
+
+ if(!o){
if(success !== false){
this.fireEvent("load", this, [], options, o);
}
* @cfg {Array} fields An array of field definition objects, or field name strings.
* @cfg {Object} an existing reader (eg. copied from another store)
* @cfg {Array} data The multi-dimensional array of data
+ * @cfg {Roo.data.DataProxy} proxy [not-required]
+ * @cfg {Roo.data.Reader} reader [not-required]
* @constructor
* @param {Object} config
*/
/**
* @class Roo.data.DataReader
+ * @abstract
* Base class for reading structured data from a data source. This class is intended to be
* extended (see {Roo.data.ArrayReader}, {Roo.data.JsonReader} and {Roo.data.XmlReader}) and should not be created directly.
*/
/**
* @class Roo.data.DataProxy
- * @extends Roo.data.Observable
+ * @extends Roo.util.Observable
+ * @abstract
* This class is an abstract base class for implementations which provide retrieval of
* unformatted data objects.<br>
* <p>
try {
result = o.reader.read(response);
}catch(e){
+ o.success = false;
+ o.raw = { errorMsg : response.responseText };
this.fireEvent("loadexception", this, o, response, e);
- o.request.callback.call(o.request.scope, null, o.request.arg, false);
+ o.request.callback.call(o.request.scope, o, o.request.arg, false);
return;
}
}
var records = [];
for(var i = 0; i < c; i++){
- var n = root[i];
+ var n = root[i];
var values = {};
var id = this.getId(n);
for(var j = 0; j < fl; j++){
f = fi[j];
- var v = this.ef[j](n);
- if (!f.convert) {
- Roo.log('missing convert for ' + f.name);
- Roo.log(f);
- continue;
- }
- values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue);
- }
+ var v = this.ef[j](n);
+ if (!f.convert) {
+ Roo.log('missing convert for ' + f.name);
+ Roo.log(f);
+ continue;
+ }
+ values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue);
+ }
+ if (!Record) {
+ return {
+ raw : { errorMsg : "JSON Reader Error: fields or metadata not available to create Record" },
+ success : false,
+ records : [],
+ totalRecords : 0
+ };
+ }
var record = new Record(values, id);
record.json = n;
records[i] = record;
*/
/**
- * @class Roo.bootstrap.ComboBox
- * @extends Roo.bootstrap.TriggerField
+ * @class Roo.bootstrap.form.ComboBox
+ * @extends Roo.bootstrap.form.TriggerField
* A combobox control with support for autocomplete, remote-loading, paging and many other features.
* @cfg {Boolean} append (true|false) default false
* @cfg {Boolean} autoFocus (true|false) auto focus the first item, default true
* Create a new ComboBox.
* @param {Object} config Configuration options
*/
-Roo.bootstrap.ComboBox = function(config){
- Roo.bootstrap.ComboBox.superclass.constructor.call(this, config);
+Roo.bootstrap.form.ComboBox = function(config){
+ Roo.bootstrap.form.ComboBox.superclass.constructor.call(this, config);
this.addEvents({
/**
* @event expand
* Fires when the dropdown list is expanded
- * @param {Roo.bootstrap.ComboBox} combo This combo box
+ * @param {Roo.bootstrap.form.ComboBox} combo This combo box
*/
'expand' : true,
/**
* @event collapse
* Fires when the dropdown list is collapsed
- * @param {Roo.bootstrap.ComboBox} combo This combo box
+ * @param {Roo.bootstrap.form.ComboBox} combo This combo box
*/
'collapse' : true,
/**
* @event beforeselect
* Fires before a list item is selected. Return false to cancel the selection.
- * @param {Roo.bootstrap.ComboBox} combo This combo box
+ * @param {Roo.bootstrap.form.ComboBox} combo This combo box
* @param {Roo.data.Record} record The data record returned from the underlying store
* @param {Number} index The index of the selected item in the dropdown list
*/
/**
* @event select
* Fires when a list item is selected
- * @param {Roo.bootstrap.ComboBox} combo This combo box
+ * @param {Roo.bootstrap.form.ComboBox} combo This combo box
* @param {Roo.data.Record} record The data record returned from the underlying store (or false on clear)
* @param {Number} index The index of the selected item in the dropdown list
*/
* @event beforequery
* Fires before all queries are processed. Return false to cancel the query or set cancel to true.
* The event object passed has these properties:
- * @param {Roo.bootstrap.ComboBox} combo This combo box
+ * @param {Roo.bootstrap.form.ComboBox} combo This combo box
* @param {String} query The query
* @param {Boolean} forceAll true to force "all" query
* @param {Boolean} cancel true to cancel the query
/**
* @event add
* Fires when the 'add' icon is pressed (add a listener to enable add button)
- * @param {Roo.bootstrap.ComboBox} combo This combo box
+ * @param {Roo.bootstrap.form.ComboBox} combo This combo box
*/
'add' : true,
/**
* @event edit
* Fires when the 'edit' icon is pressed (add a listener to enable add button)
- * @param {Roo.bootstrap.ComboBox} combo This combo box
+ * @param {Roo.bootstrap.form.ComboBox} combo This combo box
* @param {Roo.data.Record|false} record The data record returned from the underlying store (or false on nothing selected)
*/
'edit' : true,
/**
* @event remove
* Fires when the remove value from the combobox array
- * @param {Roo.bootstrap.ComboBox} combo This combo box
+ * @param {Roo.bootstrap.form.ComboBox} combo This combo box
*/
'remove' : true,
/**
* @event afterremove
* Fires when the remove value from the combobox array
- * @param {Roo.bootstrap.ComboBox} combo This combo box
+ * @param {Roo.bootstrap.form.ComboBox} combo This combo box
*/
'afterremove' : true,
/**
* @event specialfilter
* Fires when specialfilter
- * @param {Roo.bootstrap.ComboBox} combo This combo box
+ * @param {Roo.bootstrap.form.ComboBox} combo This combo box
*/
'specialfilter' : true,
/**
* @event tick
* Fires when tick the element
- * @param {Roo.bootstrap.ComboBox} combo This combo box
+ * @param {Roo.bootstrap.form.ComboBox} combo This combo box
*/
'tick' : true,
/**
* @event touchviewdisplay
* Fires when touch view require special display (default is using displayField)
- * @param {Roo.bootstrap.ComboBox} combo This combo box
+ * @param {Roo.bootstrap.form.ComboBox} combo This combo box
* @param {Object} cfg set html .
*/
'touchviewdisplay' : true
}
};
-Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
+Roo.extend(Roo.bootstrap.form.ComboBox, Roo.bootstrap.form.TriggerField, {
/**
* @cfg {Boolean} lazyRender True to prevent the ComboBox from rendering until requested (should always be used when
* Normal ComboBox
*/
if(!this.tickable){
- cfg = Roo.bootstrap.ComboBox.superclass.getAutoCreate.call(this);
+ cfg = Roo.bootstrap.form.ComboBox.superclass.getAutoCreate.call(this);
return cfg;
}
return;
}
- Roo.bootstrap.ComboBox.superclass.initEvents.call(this);
+ Roo.bootstrap.form.ComboBox.superclass.initEvents.call(this);
if(this.hiddenName){
this.store.un('load', this.onLoad, this);
this.store.un('loadexception', this.onLoadException, this);
}
- Roo.bootstrap.ComboBox.superclass.onDestroy.call(this);
+ Roo.bootstrap.form.ComboBox.superclass.onDestroy.call(this);
},
// private
{
-// Roo.bootstrap.ComboBox.superclass.onResize.apply(this, arguments);
+// Roo.bootstrap.form.ComboBox.superclass.onResize.apply(this, arguments);
//
// if(typeof w != 'number'){
// // we do not handle it!?!?
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');
}
if(this.valueField){
return typeof this.value != 'undefined' ? this.value : '';
}else{
- return Roo.bootstrap.ComboBox.superclass.getValue.call(this);
+ return Roo.bootstrap.form.ComboBox.superclass.getValue.call(this);
}
},
if(this.hiddenField){
this.hiddenField.dom.value = v;
}
- Roo.bootstrap.ComboBox.superclass.setValue.call(this, text);
+ Roo.bootstrap.form.ComboBox.superclass.setValue.call(this, text);
this.value = v;
var close = this.closeTriggerEl();
this.hiddenField.dom.value = vv;
this.lastSelectionText = dv;
- Roo.bootstrap.ComboBox.superclass.setValue.call(this, dv);
+ Roo.bootstrap.form.ComboBox.superclass.setValue.call(this, dv);
this.value = vv;
return;
}
// no hidden field.. - we store the value in 'value', but still display
// display field!!!!
this.lastSelectionText = dv;
- Roo.bootstrap.ComboBox.superclass.setValue.call(this, dv);
+ Roo.bootstrap.form.ComboBox.superclass.setValue.call(this, dv);
this.value = vv;
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',
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
]
},
{
} 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',
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
]
},
{
renderTouchView : function()
{
- this.touchViewEl = Roo.get(document.body).createChild(Roo.bootstrap.ComboBox.touchViewTemplate);
+ this.touchViewEl = Roo.get(document.body).createChild(Roo.bootstrap.form.ComboBox.touchViewTemplate);
this.touchViewEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
this.touchViewHeaderEl = this.touchViewEl.select('.modal-header', true).first();
var rawValue = this.getRawValue();
- var template = (this.multiple) ? Roo.bootstrap.ComboBox.listItemCheckbox : Roo.bootstrap.ComboBox.listItemRadio;
+ var template = (this.multiple) ? Roo.bootstrap.form.ComboBox.listItemCheckbox : Roo.bootstrap.form.ComboBox.listItemRadio;
this.tickItems = [];
{
this.clearTouchView();
- this.touchViewListGroup.createChild(Roo.bootstrap.ComboBox.emptyResult);
+ this.touchViewListGroup.createChild(Roo.bootstrap.form.ComboBox.emptyResult);
this.touchViewListGroup.select('.roo-combobox-touch-view-empty-result', true).first().dom.innerHTML = this.emptyResultText;
*/
});
-Roo.apply(Roo.bootstrap.ComboBox, {
+Roo.apply(Roo.bootstrap.form.ComboBox, {
header : {
tag: 'div',
}
});
-Roo.apply(Roo.bootstrap.ComboBox, {
+Roo.apply(Roo.bootstrap.form.ComboBox, {
touchViewTemplate : {
tag: 'div',
tag: 'div',
cls: 'modal-content',
cn: [
- Roo.bootstrap.ComboBox.header,
- Roo.bootstrap.ComboBox.body,
- Roo.bootstrap.ComboBox.footer
+ Roo.bootstrap.form.ComboBox.header,
+ Roo.bootstrap.form.ComboBox.body,
+ Roo.bootstrap.form.ComboBox.footer
]
}
]
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)
/**
* @class Roo.bootstrap.Popover
* @extends Roo.bootstrap.Component
+ * @parent none builder
+ * @children Roo.bootstrap.Component
* Bootstrap Popover class
* @cfg {String} html contents of the popover (or false to use children..)
* @cfg {String} title of popover (or false to hide)
}
}, this.delay.hide)
},
+
+ /**
+ * update the position of the dialog
+ * normally this is needed if the popover get's bigger - due to a Table reload etc..
+ *
+ *
+ */
+
+ doAlign : function()
+ {
+
+ if (this.alignEl) {
+ this.updatePosition(this.placement, true);
+
+ } else {
+ // this is usually just done by the builder = to show the popoup in the middle of the scren.
+ var es = this.el.getSize();
+ var x = Roo.lib.Dom.getViewWidth()/2;
+ var y = Roo.lib.Dom.getViewHeight()/2;
+ this.el.setXY([ x-(es.width/2), y-(es.height/2)] );
+
+ }
+
+
+
+
+
+ },
+
/**
* Show the popover
* @param {Roo.Element|string|Boolean} - element to align and point to. (set align to [ pos, offset ])
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);
}
}
this.el.show();
this.el.dom.style.display = 'block';
-
- if (this.alignEl) {
- this.updatePosition(this.placement, true);
-
- } else {
- // this is usually just done by the builder = to show the popoup in the middle of the scren.
- var es = this.el.getSize();
- var x = Roo.lib.Dom.getViewWidth()/2;
- var y = Roo.lib.Dom.getViewHeight()/2;
- this.el.setXY([ x-(es.width/2), y-(es.height/2)] );
-
- }
-
+ this.doAlign();
//var arrow = this.el.select('.arrow',true).first();
//arrow.set(align[2],
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)
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();
});
- }
-
-});/*
- * - LGPL
- *
- * Card header - holder for the card header elements.
- *
- */
+ },
+ onShow : function() {
+ Roo.bootstrap.Popover.popups.push(this);
+ },
+ onHide : function() {
+ Roo.bootstrap.Popover.popups.remove(this);
+ }
+});
/**
* @class Roo.bootstrap.PopoverNav
- * @extends Roo.bootstrap.NavGroup
+ * @extends Roo.bootstrap.nav.Simplebar
+ * @parent Roo.bootstrap.Popover
+ * @children Roo.bootstrap.nav.Group Roo.bootstrap.Container
+ * @licence LGPL
* Bootstrap Popover header navigation class
+ * FIXME? should this go under nav?
+ *
+ *
* @constructor
* Create a new Popover Header Navigation
* @param {Object} config The config object
Roo.bootstrap.PopoverNav.superclass.constructor.call(this, config);
};
-Roo.extend(Roo.bootstrap.PopoverNav, Roo.bootstrap.NavSimplebar, {
+Roo.extend(Roo.bootstrap.PopoverNav, Roo.bootstrap.nav.Simplebar, {
container_method : 'getPopoverHeader'
/**
* @class Roo.bootstrap.Progress
* @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.ProgressBar
* Bootstrap Progress class
* @cfg {Boolean} striped striped of the progress bar
* @cfg {Boolean} active animated of the progress bar
- /*
- * - LGPL
- *
- * column
- *
- */
-
-/**
+ /**
* @class Roo.bootstrap.TabGroup
* @extends Roo.bootstrap.Column
+ * @children Roo.bootstrap.TabPanel
* Bootstrap Column class
* @cfg {String} navId the navigation id (for use with navbars) - will be auto generated if it does not exist..
* @cfg {Boolean} carousel true to make the group behave like a carousel
/**
* register a Navigation item
- * @param {Roo.bootstrap.NavItem} the navitem to add
+ * @param {Roo.bootstrap.nav.Item} the navitem to add
*/
register : function(item)
{
groups: {},
/**
* register a Navigation Group
- * @param {Roo.bootstrap.NavGroup} the navgroup to add
+ * @param {Roo.bootstrap.nav.Group} the navgroup to add
*/
register : function(navgrp)
{
* fetch a Navigation Group based on the navigation ID
* if one does not exist , it will get created.
* @param {string} the navgroup to add
- * @returns {Roo.bootstrap.NavGroup} the navgroup
+ * @returns {Roo.bootstrap.nav.Group} the navgroup
*/
get: function(navId) {
if (typeof(this.groups[navId]) == 'undefined') {
/**
* @class Roo.bootstrap.TabPanel
* @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.Component
* Bootstrap TabPanel class
* @cfg {Boolean} active panel active
* @cfg {String} html panel content
* @cfg {String} tabId unique tab ID (will be autogenerated if not set. - used to match TabItem to Panel)
- * @cfg {String} navId The Roo.bootstrap.NavGroup which triggers show hide ()
+ * @cfg {String} navId The Roo.bootstrap.nav.Group which triggers show hide ()
* @cfg {String} href click to link..
* @cfg {Boolean} touchSlide if swiping slides tab to next panel (default off)
*
*/
/**
- * @class Roo.bootstrap.DateField
- * @extends Roo.bootstrap.Input
+ * @class Roo.bootstrap.form.DateField
+ * @extends Roo.bootstrap.form.Input
* Bootstrap DateField class
* @cfg {Number} weekStart default 0
* @cfg {String} viewMode default empty, (months|years)
* @param {Object} config The config object
*/
-Roo.bootstrap.DateField = function(config){
- Roo.bootstrap.DateField.superclass.constructor.call(this, config);
+Roo.bootstrap.form.DateField = function(config){
+ Roo.bootstrap.form.DateField.superclass.constructor.call(this, config);
this.addEvents({
/**
* @event show
* Fires when this field show.
- * @param {Roo.bootstrap.DateField} this
+ * @param {Roo.bootstrap.form.DateField} this
* @param {Mixed} date The date value
*/
show : true,
/**
* @event show
* Fires when this field hide.
- * @param {Roo.bootstrap.DateField} this
+ * @param {Roo.bootstrap.form.DateField} this
* @param {Mixed} date The date value
*/
hide : true,
/**
* @event select
* Fires when select a date.
- * @param {Roo.bootstrap.DateField} this
+ * @param {Roo.bootstrap.form.DateField} this
* @param {Mixed} date The date value
*/
select : true,
/**
* @event beforeselect
* Fires when before select a date.
- * @param {Roo.bootstrap.DateField} this
+ * @param {Roo.bootstrap.form.DateField} this
* @param {Mixed} date The date value
*/
beforeselect : true
});
};
-Roo.extend(Roo.bootstrap.DateField, Roo.bootstrap.Input, {
+Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input, {
/**
* @cfg {String} format
onRender: function(ct, position)
{
- Roo.bootstrap.DateField.superclass.onRender.call(this, ct, position);
+ Roo.bootstrap.form.DateField.superclass.onRender.call(this, ct, position);
this.language = this.language || 'en';
- this.language = this.language in Roo.bootstrap.DateField.dates ? this.language : this.language.split('-')[0];
- this.language = this.language in Roo.bootstrap.DateField.dates ? this.language : "en";
+ this.language = this.language in Roo.bootstrap.form.DateField.dates ? this.language : this.language.split('-')[0];
+ this.language = this.language in Roo.bootstrap.form.DateField.dates ? this.language : "en";
- this.isRTL = Roo.bootstrap.DateField.dates[this.language].rtl || false;
+ this.isRTL = Roo.bootstrap.form.DateField.dates[this.language].rtl || false;
this.format = this.format || 'm/d/y';
this.isInline = false;
this.isInput = true;
}
}
- this.pickerEl = Roo.get(document.body).createChild(Roo.bootstrap.DateField.template);
+ this.pickerEl = Roo.get(document.body).createChild(Roo.bootstrap.form.DateField.template);
-// this.el.select('>.input-group', true).first().createChild(Roo.bootstrap.DateField.template);
+// this.el.select('>.input-group', true).first().createChild(Roo.bootstrap.form.DateField.template);
this.picker().setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
return;
}
- v.dom.innerHTML = Roo.bootstrap.DateField.dates[this.language].today;
+ v.dom.innerHTML = Roo.bootstrap.form.DateField.dates[this.language].today;
v.attr('colspan', function(i, val){
return parseInt(val) + 1;
});
dow.cn.push({
tag: 'th',
cls: 'dow',
- html: Roo.bootstrap.DateField.dates[this.language].daysMin[(dowCnt++)%7]
+ html: Roo.bootstrap.form.DateField.dates[this.language].daysMin[(dowCnt++)%7]
});
}
var month = {
tag: 'span',
cls: 'month',
- html: Roo.bootstrap.DateField.dates[this.language].monthsShort[i++]
+ html: Roo.bootstrap.form.DateField.dates[this.language].monthsShort[i++]
};
months.createChild(month);
currentDate = this.date && this.date.valueOf(),
today = this.UTCToday();
- this.picker().select('>.datepicker-days thead th.switch', true).first().dom.innerHTML = Roo.bootstrap.DateField.dates[this.language].months[month]+' '+year;
+ this.picker().select('>.datepicker-days thead th.switch', true).first().dom.innerHTML = Roo.bootstrap.form.DateField.dates[this.language].months[month]+' '+year;
-// this.picker().select('>tfoot th.today', true).first().dom.innerHTML = Roo.bootstrap.DateField.dates[this.language].today;
+// this.picker().select('>tfoot th.today', true).first().dom.innerHTML = Roo.bootstrap.form.DateField.dates[this.language].today;
// this.picker.select('>tfoot th.today').
// .text(dates[this.language].today)
v.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
v.hide();
});
- this.picker().select('>.datepicker-'+Roo.bootstrap.DateField.modes[this.viewMode].clsName, true).first().show();
+ this.picker().select('>.datepicker-'+Roo.bootstrap.form.DateField.modes[this.viewMode].clsName, true).first().show();
},
place: function()
onFocus : function()
{
- Roo.bootstrap.DateField.superclass.onFocus.call(this);
+ Roo.bootstrap.form.DateField.superclass.onFocus.call(this);
this.showPopup();
},
onBlur : function()
{
- Roo.bootstrap.DateField.superclass.onBlur.call(this);
+ Roo.bootstrap.form.DateField.superclass.onBlur.call(this);
var d = this.inputEl().getValue();
keyup: function(e)
{
- Roo.bootstrap.DateField.superclass.keyup.call(this);
+ Roo.bootstrap.form.DateField.superclass.keyup.call(this);
this.update();
},
if(isNaN(d.getTime())){
this.date = this.viewDate = '';
- Roo.bootstrap.DateField.superclass.setValue.call(this, '');
+ Roo.bootstrap.form.DateField.superclass.setValue.call(this, '');
return;
}
v = this.formatDate(d);
- Roo.bootstrap.DateField.superclass.setValue.call(this, v);
+ Roo.bootstrap.form.DateField.superclass.setValue.call(this, v);
this.date = new Date(d.getTime() - d.getTimezoneOffset()*60000);
break;
case 'prev':
case 'next':
- var dir = Roo.bootstrap.DateField.modes[this.viewMode].navStep * (className == 'prev' ? -1 : 1);
+ var dir = Roo.bootstrap.form.DateField.modes[this.viewMode].navStep * (className == 'prev' ? -1 : 1);
switch(this.viewMode){
case 0:
this.viewDate = this.moveMonth(this.viewDate, dir);
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));
+ this.viewDate.setUTCMonth(Roo.bootstrap.form.DateField.dates[this.language].monthsShort.indexOf(html));
} else {
var year = parseInt(html, 10) || 0;
this.viewDate.setUTCFullYear(year);
{
this.date = this.viewDate = '';
- Roo.bootstrap.DateField.superclass.setValue.call(this, '');
+ Roo.bootstrap.form.DateField.superclass.setValue.call(this, '');
}
});
-Roo.apply(Roo.bootstrap.DateField, {
+Roo.apply(Roo.bootstrap.form.DateField, {
head : {
tag: 'thead',
}]
});
-Roo.apply(Roo.bootstrap.DateField, {
+Roo.apply(Roo.bootstrap.form.DateField, {
template : {
tag: 'div',
tag: 'table',
cls: 'table-condensed',
cn:[
- Roo.bootstrap.DateField.head,
+ Roo.bootstrap.form.DateField.head,
{
tag: 'tbody'
},
- Roo.bootstrap.DateField.footer
+ Roo.bootstrap.form.DateField.footer
]
}
]
tag: 'table',
cls: 'table-condensed',
cn:[
- Roo.bootstrap.DateField.head,
- Roo.bootstrap.DateField.content,
- Roo.bootstrap.DateField.footer
+ Roo.bootstrap.form.DateField.head,
+ Roo.bootstrap.form.DateField.content,
+ Roo.bootstrap.form.DateField.footer
]
}
]
tag: 'table',
cls: 'table-condensed',
cn:[
- Roo.bootstrap.DateField.head,
- Roo.bootstrap.DateField.content,
- Roo.bootstrap.DateField.footer
+ Roo.bootstrap.form.DateField.head,
+ Roo.bootstrap.form.DateField.content,
+ Roo.bootstrap.form.DateField.footer
]
}
]
*/
/**
- * @class Roo.bootstrap.TimeField
- * @extends Roo.bootstrap.Input
+ * @class Roo.bootstrap.form.TimeField
+ * @extends Roo.bootstrap.form.Input
* Bootstrap DateField class
*
*
* @param {Object} config The config object
*/
-Roo.bootstrap.TimeField = function(config){
- Roo.bootstrap.TimeField.superclass.constructor.call(this, config);
+Roo.bootstrap.form.TimeField = function(config){
+ Roo.bootstrap.form.TimeField.superclass.constructor.call(this, config);
this.addEvents({
/**
* @event show
* Fires when this field show.
- * @param {Roo.bootstrap.DateField} thisthis
+ * @param {Roo.bootstrap.form.DateField} thisthis
* @param {Mixed} date The date value
*/
show : true,
/**
* @event show
* Fires when this field hide.
- * @param {Roo.bootstrap.DateField} this
+ * @param {Roo.bootstrap.form.DateField} this
* @param {Mixed} date The date value
*/
hide : true,
/**
* @event select
* Fires when select a date.
- * @param {Roo.bootstrap.DateField} this
+ * @param {Roo.bootstrap.form.DateField} this
* @param {Mixed} date The date value
*/
select : true
});
};
-Roo.extend(Roo.bootstrap.TimeField, Roo.bootstrap.Input, {
+Roo.extend(Roo.bootstrap.form.TimeField, Roo.bootstrap.form.Input, {
/**
* @cfg {String} format
getAutoCreate : function()
{
this.after = '<i class="fa far fa-clock"></i>';
- return Roo.bootstrap.TimeField.superclass.getAutoCreate.call(this);
+ return Roo.bootstrap.form.TimeField.superclass.getAutoCreate.call(this);
},
onRender: function(ct, position)
{
- Roo.bootstrap.TimeField.superclass.onRender.call(this, ct, position);
+ Roo.bootstrap.form.TimeField.superclass.onRender.call(this, ct, position);
- this.pickerEl = Roo.get(document.body).createChild(Roo.bootstrap.TimeField.template);
+ this.pickerEl = Roo.get(document.body).createChild(Roo.bootstrap.form.TimeField.template);
this.picker().setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
onFocus : function()
{
- Roo.bootstrap.TimeField.superclass.onFocus.call(this);
+ Roo.bootstrap.form.TimeField.superclass.onFocus.call(this);
this.show();
},
onBlur : function()
{
- Roo.bootstrap.TimeField.superclass.onBlur.call(this);
+ Roo.bootstrap.form.TimeField.superclass.onBlur.call(this);
this.hide();
},
});
-Roo.apply(Roo.bootstrap.TimeField, {
+Roo.apply(Roo.bootstrap.form.TimeField, {
template : {
tag: 'div',
*/
/**
- * @class Roo.bootstrap.MonthField
- * @extends Roo.bootstrap.Input
+ * @class Roo.bootstrap.form.MonthField
+ * @extends Roo.bootstrap.form.Input
* Bootstrap MonthField class
*
* @cfg {String} language default en
* @param {Object} config The config object
*/
-Roo.bootstrap.MonthField = function(config){
- Roo.bootstrap.MonthField.superclass.constructor.call(this, config);
+Roo.bootstrap.form.MonthField = function(config){
+ Roo.bootstrap.form.MonthField.superclass.constructor.call(this, config);
this.addEvents({
/**
* @event show
* Fires when this field show.
- * @param {Roo.bootstrap.MonthField} this
+ * @param {Roo.bootstrap.form.MonthField} this
* @param {Mixed} date The date value
*/
show : true,
/**
* @event show
* Fires when this field hide.
- * @param {Roo.bootstrap.MonthField} this
+ * @param {Roo.bootstrap.form.MonthField} this
* @param {Mixed} date The date value
*/
hide : true,
/**
* @event select
* Fires when select a date.
- * @param {Roo.bootstrap.MonthField} this
+ * @param {Roo.bootstrap.form.MonthField} this
* @param {String} oldvalue The old value
* @param {String} newvalue The new value
*/
});
};
-Roo.extend(Roo.bootstrap.MonthField, Roo.bootstrap.Input, {
+Roo.extend(Roo.bootstrap.form.MonthField, Roo.bootstrap.form.Input, {
onRender: function(ct, position)
{
- Roo.bootstrap.MonthField.superclass.onRender.call(this, ct, position);
+ Roo.bootstrap.form.MonthField.superclass.onRender.call(this, ct, position);
this.language = this.language || 'en';
- this.language = this.language in Roo.bootstrap.MonthField.dates ? this.language : this.language.split('-')[0];
- this.language = this.language in Roo.bootstrap.MonthField.dates ? this.language : "en";
+ this.language = this.language in Roo.bootstrap.form.MonthField.dates ? this.language : this.language.split('-')[0];
+ this.language = this.language in Roo.bootstrap.form.MonthField.dates ? this.language : "en";
- this.isRTL = Roo.bootstrap.MonthField.dates[this.language].rtl || false;
+ this.isRTL = Roo.bootstrap.form.MonthField.dates[this.language].rtl || false;
this.isInline = false;
this.isInput = true;
this.component = this.el.select('.add-on', true).first() || false;
this.component = (this.component && this.component.length === 0) ? false : this.component;
this.hasInput = this.component && this.inputEL().length;
- this.pickerEl = Roo.get(document.body).createChild(Roo.bootstrap.MonthField.template);
+ this.pickerEl = Roo.get(document.body).createChild(Roo.bootstrap.form.MonthField.template);
this.picker().setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
{
var o = this.getValue();
- Roo.bootstrap.MonthField.superclass.setValue.call(this, v);
+ Roo.bootstrap.form.MonthField.superclass.setValue.call(this, v);
this.update();
return;
}
- this.vIndex = Roo.bootstrap.MonthField.dates[this.language].monthsShort.indexOf(html);
+ this.vIndex = Roo.bootstrap.form.MonthField.dates[this.language].monthsShort.indexOf(html);
- this.setValue(Roo.bootstrap.MonthField.dates[this.language].months[this.vIndex]);
+ this.setValue(Roo.bootstrap.form.MonthField.dates[this.language].months[this.vIndex]);
this.hide();
var month = {
tag: 'span',
cls: 'month',
- html: Roo.bootstrap.MonthField.dates[this.language].monthsShort[i++]
+ html: Roo.bootstrap.form.MonthField.dates[this.language].monthsShort[i++]
};
months.createChild(month);
var _this = this;
if(typeof(this.vIndex) == 'undefined' && this.value.length){
- this.vIndex = Roo.bootstrap.MonthField.dates[this.language].months.indexOf(this.value);
+ this.vIndex = Roo.bootstrap.form.MonthField.dates[this.language].months.indexOf(this.value);
}
Roo.each(this.pickerEl.select('> .datepicker-months tbody > tr > td > span', true).elements, function(e, k){
onFocus : function()
{
- Roo.bootstrap.MonthField.superclass.onFocus.call(this);
+ Roo.bootstrap.form.MonthField.superclass.onFocus.call(this);
this.show();
},
onBlur : function()
{
- Roo.bootstrap.MonthField.superclass.onBlur.call(this);
+ Roo.bootstrap.form.MonthField.superclass.onBlur.call(this);
var d = this.inputEl().getValue();
keyup: function(e)
{
- Roo.bootstrap.MonthField.superclass.keyup.call(this);
+ Roo.bootstrap.form.MonthField.superclass.keyup.call(this);
this.update();
},
this.vIndex = 0;
}
- this.setValue(Roo.bootstrap.MonthField.dates[this.language].months[this.vIndex]);
+ this.setValue(Roo.bootstrap.form.MonthField.dates[this.language].months[this.vIndex]);
break;
case 38: // up
this.vIndex = 0;
}
- this.setValue(Roo.bootstrap.MonthField.dates[this.language].months[this.vIndex]);
+ this.setValue(Roo.bootstrap.form.MonthField.dates[this.language].months[this.vIndex]);
break;
case 13: // enter
if(typeof(this.vIndex) != 'undefined' && !isNaN(this.vIndex)){
- this.setValue(Roo.bootstrap.MonthField.dates[this.language].months[this.vIndex]);
+ this.setValue(Roo.bootstrap.form.MonthField.dates[this.language].months[this.vIndex]);
}
this.hide();
break;
case 9: // tab
if(typeof(this.vIndex) != 'undefined' && !isNaN(this.vIndex)){
- this.setValue(Roo.bootstrap.MonthField.dates[this.language].months[this.vIndex]);
+ this.setValue(Roo.bootstrap.form.MonthField.dates[this.language].months[this.vIndex]);
}
this.hide();
break;
});
-Roo.apply(Roo.bootstrap.MonthField, {
+Roo.apply(Roo.bootstrap.form.MonthField, {
content : {
tag: 'tbody',
}
});
-Roo.apply(Roo.bootstrap.MonthField, {
+Roo.apply(Roo.bootstrap.form.MonthField, {
template : {
tag: 'div',
tag: 'table',
cls: 'table-condensed',
cn:[
- Roo.bootstrap.DateField.content
+ Roo.bootstrap.form.DateField.content
]
}
]
*/
/**
- * @class Roo.bootstrap.CheckBox
- * @extends Roo.bootstrap.Input
+ * @class Roo.bootstrap.form.CheckBox
+ * @extends Roo.bootstrap.form.Input
* Bootstrap CheckBox class
*
* @cfg {String} valueOff The value that should go into the generated input element's value when unchecked.
* @param {Object} config The config object
*/
-Roo.bootstrap.CheckBox = function(config){
- Roo.bootstrap.CheckBox.superclass.constructor.call(this, config);
+Roo.bootstrap.form.CheckBox = function(config){
+ Roo.bootstrap.form.CheckBox.superclass.constructor.call(this, config);
this.addEvents({
/**
* @event check
* Fires when the element is checked or unchecked.
- * @param {Roo.bootstrap.CheckBox} this This input
+ * @param {Roo.bootstrap.form.CheckBox} this This input
* @param {Boolean} checked The new checked value
*/
check : true,
/**
* @event click
* Fires when the element is click.
- * @param {Roo.bootstrap.CheckBox} this This input
+ * @param {Roo.bootstrap.form.CheckBox} this This input
*/
click : true
});
};
-Roo.extend(Roo.bootstrap.CheckBox, Roo.bootstrap.Input, {
+Roo.extend(Roo.bootstrap.form.CheckBox, Roo.bootstrap.form.Input, {
inputType: 'checkbox',
inputValue: 1,
initEvents : function()
{
-// Roo.bootstrap.CheckBox.superclass.initEvents.call(this);
+// Roo.bootstrap.form.CheckBox.superclass.initEvents.call(this);
this.inputEl().on('click', this.onClick, this);
this.startValue = this.getValue();
if(this.groupId){
- Roo.bootstrap.CheckBox.register(this);
+ Roo.bootstrap.form.CheckBox.register(this);
}
},
//return (this.getValue() == this.inputValue) ? true : false;
}
- var group = Roo.bootstrap.CheckBox.get(this.groupId);
+ var group = Roo.bootstrap.form.CheckBox.get(this.groupId);
if(!group){
return false;
this.fireEvent('valid', this);
- var label = Roo.bootstrap.FieldLabel.get(this.name + '-group');
+ var label = Roo.bootstrap.form.FieldLabel.get(this.name + '-group');
if(this.groupId){
- label = Roo.bootstrap.FieldLabel.get(this.groupId + '-group');
+ label = Roo.bootstrap.form.FieldLabel.get(this.groupId + '-group');
}
if(label){
return;
}
- var group = Roo.bootstrap.CheckBox.get(this.groupId);
+ var group = Roo.bootstrap.form.CheckBox.get(this.groupId);
if(!group){
return;
this.fireEvent('invalid', this, msg);
- var label = Roo.bootstrap.FieldLabel.get(this.name + '-group');
+ var label = Roo.bootstrap.form.FieldLabel.get(this.name + '-group');
if(this.groupId){
- label = Roo.bootstrap.FieldLabel.get(this.groupId + '-group');
+ label = Roo.bootstrap.form.FieldLabel.get(this.groupId + '-group');
}
if(label){
return;
}
- var group = Roo.bootstrap.CheckBox.get(this.groupId);
+ var group = Roo.bootstrap.form.CheckBox.get(this.groupId);
if(!group){
return;
clearInvalid : function()
{
- Roo.bootstrap.Input.prototype.clearInvalid.call(this);
+ Roo.bootstrap.form.Input.prototype.clearInvalid.call(this);
// this.el.findParent('.form-group', false, true).removeClass([this.invalidClass, this.validClass]);
- var label = Roo.bootstrap.FieldLabel.get(this.name + '-group');
+ var label = Roo.bootstrap.form.FieldLabel.get(this.name + '-group');
if (label && label.iconEl) {
label.iconEl.removeClass([ label.validClass, label.invalidClass ]);
disable : function()
{
if(this.inputType != 'radio'){
- Roo.bootstrap.CheckBox.superclass.disable.call(this);
+ Roo.bootstrap.form.CheckBox.superclass.disable.call(this);
return;
}
enable : function()
{
if(this.inputType != 'radio'){
- Roo.bootstrap.CheckBox.superclass.enable.call(this);
+ Roo.bootstrap.form.CheckBox.superclass.enable.call(this);
return;
}
});
-Roo.apply(Roo.bootstrap.CheckBox, {
+Roo.apply(Roo.bootstrap.form.CheckBox, {
groups: {},
/**
* register a CheckBox Group
- * @param {Roo.bootstrap.CheckBox} the CheckBox to add
+ * @param {Roo.bootstrap.form.CheckBox} the CheckBox to add
*/
register : function(checkbox)
{
/**
* fetch a CheckBox Group based on the group ID
* @param {string} the group ID
- * @returns {Roo.bootstrap.CheckBox} the CheckBox group
+ * @returns {Roo.bootstrap.form.CheckBox} the CheckBox group
*/
get: function(groupId) {
if (typeof(this.groups[groupId]) == 'undefined') {
*/
/**
- * @class Roo.bootstrap.Radio
+ * @class Roo.bootstrap.form.Radio
* @extends Roo.bootstrap.Component
* Bootstrap Radio class
* @cfg {String} boxLabel - the label associated
* Create a new Radio
* @param {Object} config The config object
*/
-Roo.bootstrap.Radio = function(config){
- Roo.bootstrap.Radio.superclass.constructor.call(this, config);
+Roo.bootstrap.form.Radio = function(config){
+ Roo.bootstrap.form.Radio.superclass.constructor.call(this, config);
};
-Roo.extend(Roo.bootstrap.Radio, Roo.bootstrap.Component, {
+Roo.extend(Roo.bootstrap.form.Radio, Roo.bootstrap.Component, {
boxLabel : '',
- value : '',
+ value : '',
+
+ getAutoCreate : function()
+ {
+ var cfg = {
+ tag : 'div',
+ cls : 'form-group radio',
+ cn : [
+ {
+ tag : 'label',
+ cls : 'box-label',
+ html : this.boxLabel
+ }
+ ]
+ };
+
+ return cfg;
+ },
+
+ initEvents : function()
+ {
+ this.parent().register(this);
+
+ this.el.on('click', this.onClick, this);
+
+ },
+
+ onClick : function(e)
+ {
+ if(this.parent().fireEvent('click', this.parent(), this, e) !== false){
+ this.setChecked(true);
+ }
+ },
+
+ setChecked : function(state, suppressEvent)
+ {
+ this.parent().setValue(this.value, suppressEvent);
+
+ },
+
+ setBoxLabel : function(v)
+ {
+ this.boxLabel = v;
+
+ if(this.rendered){
+ this.el.select('label.box-label',true).first().dom.innerHTML = (v === null || v === undefined ? '' : v);
+ }
+ }
+
+});
+
+
+ /*
+ * - LGPL
+ *
+ * Input
+ *
+ */
+
+/**
+ * @class Roo.bootstrap.form.SecurePass
+ * @extends Roo.bootstrap.form.Input
+ * Bootstrap SecurePass class
+ *
+ *
+ * @constructor
+ * Create a new SecurePass
+ * @param {Object} config The config object
+ */
+
+Roo.bootstrap.form.SecurePass = function (config) {
+ // these go here, so the translation tool can replace them..
+ this.errors = {
+ PwdEmpty: "Please type a password, and then retype it to confirm.",
+ PwdShort: "Your password must be at least 6 characters long. Please type a different password.",
+ PwdLong: "Your password can't contain more than 16 characters. Please type a different password.",
+ PwdBadChar: "The password contains characters that aren't allowed. Please type a different password.",
+ IDInPwd: "Your password can't include the part of your ID. Please type a different password.",
+ FNInPwd: "Your password can't contain your first name. Please type a different password.",
+ LNInPwd: "Your password can't contain your last name. Please type a different password.",
+ TooWeak: "Your password is Too Weak."
+ },
+ this.meterLabel = "Password strength:";
+ this.pwdStrengths = ["Too Weak", "Weak", "Medium", "Strong"];
+ this.meterClass = [
+ "roo-password-meter-tooweak",
+ "roo-password-meter-weak",
+ "roo-password-meter-medium",
+ "roo-password-meter-strong",
+ "roo-password-meter-grey"
+ ];
+
+ this.errors = {};
+
+ Roo.bootstrap.form.SecurePass.superclass.constructor.call(this, config);
+}
+
+Roo.extend(Roo.bootstrap.form.SecurePass, Roo.bootstrap.form.Input, {
+ /**
+ * @cfg {String/Object} errors A Error spec, or true for a default spec (defaults to
+ * {
+ * PwdEmpty: "Please type a password, and then retype it to confirm.",
+ * PwdShort: "Your password must be at least 6 characters long. Please type a different password.",
+ * PwdLong: "Your password can't contain more than 16 characters. Please type a different password.",
+ * PwdBadChar: "The password contains characters that aren't allowed. Please type a different password.",
+ * IDInPwd: "Your password can't include the part of your ID. Please type a different password.",
+ * FNInPwd: "Your password can't contain your first name. Please type a different password.",
+ * LNInPwd: "Your password can't contain your last name. Please type a different password."
+ * })
+ */
+ // private
+
+ meterWidth: 300,
+ errorMsg :'',
+ errors: false,
+ imageRoot: '/',
+ /**
+ * @cfg {String/Object} Label for the strength meter (defaults to
+ * 'Password strength:')
+ */
+ // private
+ meterLabel: '',
+ /**
+ * @cfg {String/Object} pwdStrengths A pwdStrengths spec, or true for a default spec (defaults to
+ * ['Weak', 'Medium', 'Strong'])
+ */
+ // private
+ pwdStrengths: false,
+ // private
+ strength: 0,
+ // private
+ _lastPwd: null,
+ // private
+ kCapitalLetter: 0,
+ kSmallLetter: 1,
+ kDigit: 2,
+ kPunctuation: 3,
+
+ insecure: false,
+ // private
+ initEvents: function ()
+ {
+ Roo.bootstrap.form.SecurePass.superclass.initEvents.call(this);
+
+ if (this.el.is('input[type=password]') && Roo.isSafari) {
+ this.el.on('keydown', this.SafariOnKeyDown, this);
+ }
+
+ this.el.on('keyup', this.checkStrength, this, {buffer: 50});
+ },
+ // private
+ onRender: function (ct, position)
+ {
+ Roo.bootstrap.form.SecurePass.superclass.onRender.call(this, ct, position);
+ this.wrap = this.el.wrap({cls: 'x-form-field-wrap'});
+ this.trigger = this.wrap.createChild({tag: 'div', cls: 'StrengthMeter ' + this.triggerClass});
+
+ this.trigger.createChild({
+ cn: [
+ {
+ //id: 'PwdMeter',
+ tag: 'div',
+ cls: 'roo-password-meter-grey col-xs-12',
+ style: {
+ //width: 0,
+ //width: this.meterWidth + 'px'
+ }
+ },
+ {
+ cls: 'roo-password-meter-text'
+ }
+ ]
+ });
+
+
+ if (this.hideTrigger) {
+ this.trigger.setDisplayed(false);
+ }
+ this.setSize(this.width || '', this.height || '');
+ },
+ // private
+ onDestroy: function ()
+ {
+ if (this.trigger) {
+ this.trigger.removeAllListeners();
+ this.trigger.remove();
+ }
+ if (this.wrap) {
+ this.wrap.remove();
+ }
+ Roo.bootstrap.form.TriggerField.superclass.onDestroy.call(this);
+ },
+ // private
+ checkStrength: function ()
+ {
+ var pwd = this.inputEl().getValue();
+ if (pwd == this._lastPwd) {
+ return;
+ }
+
+ var strength;
+ if (this.ClientSideStrongPassword(pwd)) {
+ strength = 3;
+ } else if (this.ClientSideMediumPassword(pwd)) {
+ strength = 2;
+ } else if (this.ClientSideWeakPassword(pwd)) {
+ strength = 1;
+ } else {
+ strength = 0;
+ }
+
+ Roo.log('strength1: ' + strength);
+
+ //var pm = this.trigger.child('div/div/div').dom;
+ var pm = this.trigger.child('div/div');
+ pm.removeClass(this.meterClass);
+ pm.addClass(this.meterClass[strength]);
+
+
+ var pt = this.trigger.child('/div').child('>*[class=roo-password-meter-text]').dom;
+
+ pt.innerHTML = this.meterLabel + ' ' + this.pwdStrengths[strength];
+
+ this._lastPwd = pwd;
+ },
+ reset: function ()
+ {
+ Roo.bootstrap.form.SecurePass.superclass.reset.call(this);
+
+ this._lastPwd = '';
+
+ var pm = this.trigger.child('div/div');
+ pm.removeClass(this.meterClass);
+ pm.addClass('roo-password-meter-grey');
+
+
+ var pt = this.trigger.child('/div').child('>*[class=roo-password-meter-text]').dom;
+
+ pt.innerHTML = '';
+ this.inputEl().dom.type='password';
+ },
+ // private
+ validateValue: function (value)
+ {
+ if (!Roo.bootstrap.form.SecurePass.superclass.validateValue.call(this, value)) {
+ return false;
+ }
+ if (value.length == 0) {
+ if (this.allowBlank) {
+ this.clearInvalid();
+ return true;
+ }
+
+ this.markInvalid(this.errors.PwdEmpty);
+ this.errorMsg = this.errors.PwdEmpty;
+ return false;
+ }
+
+ if(this.insecure){
+ return true;
+ }
+
+ if (!value.match(/[\x21-\x7e]+/)) {
+ this.markInvalid(this.errors.PwdBadChar);
+ this.errorMsg = this.errors.PwdBadChar;
+ return false;
+ }
+ if (value.length < 6) {
+ this.markInvalid(this.errors.PwdShort);
+ this.errorMsg = this.errors.PwdShort;
+ return false;
+ }
+ if (value.length > 16) {
+ this.markInvalid(this.errors.PwdLong);
+ this.errorMsg = this.errors.PwdLong;
+ return false;
+ }
+ var strength;
+ if (this.ClientSideStrongPassword(value)) {
+ strength = 3;
+ } else if (this.ClientSideMediumPassword(value)) {
+ strength = 2;
+ } else if (this.ClientSideWeakPassword(value)) {
+ strength = 1;
+ } else {
+ strength = 0;
+ }
+
+
+ if (strength < 2) {
+ //this.markInvalid(this.errors.TooWeak);
+ this.errorMsg = this.errors.TooWeak;
+ //return false;
+ }
+
+
+ console.log('strength2: ' + strength);
+
+ //var pm = this.trigger.child('div/div/div').dom;
+
+ var pm = this.trigger.child('div/div');
+ pm.removeClass(this.meterClass);
+ pm.addClass(this.meterClass[strength]);
+
+ var pt = this.trigger.child('/div').child('>*[class=roo-password-meter-text]').dom;
+
+ pt.innerHTML = this.meterLabel + ' ' + this.pwdStrengths[strength];
+
+ this.errorMsg = '';
+ return true;
+ },
+ // private
+ CharacterSetChecks: function (type)
+ {
+ this.type = type;
+ this.fResult = false;
+ },
+ // private
+ isctype: function (character, type)
+ {
+ switch (type) {
+ case this.kCapitalLetter:
+ if (character >= 'A' && character <= 'Z') {
+ return true;
+ }
+ break;
+
+ case this.kSmallLetter:
+ if (character >= 'a' && character <= 'z') {
+ return true;
+ }
+ break;
+
+ case this.kDigit:
+ if (character >= '0' && character <= '9') {
+ return true;
+ }
+ break;
+
+ case this.kPunctuation:
+ if ('!@#$%^&*()_+-=\'";:[{]}|.>,</?`~'.indexOf(character) >= 0) {
+ return true;
+ }
+ break;
+
+ default:
+ return false;
+ }
+
+ },
+ // private
+ IsLongEnough: function (pwd, size)
+ {
+ return !(pwd == null || isNaN(size) || pwd.length < size);
+ },
+ // private
+ SpansEnoughCharacterSets: function (word, nb)
+ {
+ if (!this.IsLongEnough(word, nb))
+ {
+ return false;
+ }
+
+ var characterSetChecks = new Array(
+ new this.CharacterSetChecks(this.kCapitalLetter), new this.CharacterSetChecks(this.kSmallLetter),
+ new this.CharacterSetChecks(this.kDigit), new this.CharacterSetChecks(this.kPunctuation)
+ );
+
+ for (var index = 0; index < word.length; ++index) {
+ for (var nCharSet = 0; nCharSet < characterSetChecks.length; ++nCharSet) {
+ if (!characterSetChecks[nCharSet].fResult && this.isctype(word.charAt(index), characterSetChecks[nCharSet].type)) {
+ characterSetChecks[nCharSet].fResult = true;
+ break;
+ }
+ }
+ }
+
+ var nCharSets = 0;
+ for (var nCharSet = 0; nCharSet < characterSetChecks.length; ++nCharSet) {
+ if (characterSetChecks[nCharSet].fResult) {
+ ++nCharSets;
+ }
+ }
+
+ if (nCharSets < nb) {
+ return false;
+ }
+ return true;
+ },
+ // private
+ ClientSideStrongPassword: function (pwd)
+ {
+ return this.IsLongEnough(pwd, 8) && this.SpansEnoughCharacterSets(pwd, 3);
+ },
+ // private
+ ClientSideMediumPassword: function (pwd)
+ {
+ return this.IsLongEnough(pwd, 7) && this.SpansEnoughCharacterSets(pwd, 2);
+ },
+ // private
+ ClientSideWeakPassword: function (pwd)
+ {
+ return this.IsLongEnough(pwd, 6) || !this.IsLongEnough(pwd, 0);
+ }
+
+});
+Roo.htmleditor = {};
+
+/**
+ * @class Roo.htmleditor.Filter
+ * Base Class for filtering htmleditor stuff. - do not use this directly - extend it.
+ * @cfg {DomElement} node The node to iterate and filter
+ * @cfg {boolean|String|Array} tag Tags to replace
+ * @constructor
+ * Create a new Filter.
+ * @param {Object} config Configuration options
+ */
+
+
+
+Roo.htmleditor.Filter = function(cfg) {
+ Roo.apply(this.cfg);
+ // this does not actually call walk as it's really just a abstract class
+}
+
+
+Roo.htmleditor.Filter.prototype = {
+
+ node: false,
+
+ tag: false,
+
+ // overrride to do replace comments.
+ replaceComment : false,
+
+ // overrride to do replace or do stuff with tags..
+ replaceTag : false,
+
+ walk : function(dom)
+ {
+ Roo.each( Array.from(dom.childNodes), function( e ) {
+ switch(true) {
+
+ case e.nodeType == 8 && this.replaceComment !== false: // comment
+ this.replaceComment(e);
+ return;
+
+ case e.nodeType != 1: //not a node.
+ return;
+
+ case this.tag === true: // everything
+ case typeof(this.tag) == 'object' && this.tag.indexOf(e.tagName) > -1: // array and it matches.
+ case typeof(this.tag) == 'string' && this.tag == e.tagName: // array and it matches.
+ if (this.replaceTag && false === this.replaceTag(e)) {
+ return;
+ }
+ if (e.hasChildNodes()) {
+ this.walk(e);
+ }
+ return;
+
+ default: // tags .. that do not match.
+ if (e.hasChildNodes()) {
+ this.walk(e);
+ }
+ }
+
+ }, this);
+
+ }
+};
+
+/**
+ * @class Roo.htmleditor.FilterAttributes
+ * clean attributes and styles including http:// etc.. in attribute
+ * @constructor
+* Run a new Attribute Filter
+* @param {Object} config Configuration options
+ */
+Roo.htmleditor.FilterAttributes = function(cfg)
+{
+ Roo.apply(this, cfg);
+ this.attrib_black = this.attrib_black || [];
+ this.attrib_white = this.attrib_white || [];
+
+ this.attrib_clean = this.attrib_clean || [];
+ this.style_white = this.style_white || [];
+ this.style_black = this.style_black || [];
+ this.walk(cfg.node);
+}
+
+Roo.extend(Roo.htmleditor.FilterAttributes, Roo.htmleditor.Filter,
+{
+ tag: true, // all tags
+
+ attrib_black : false, // array
+ attrib_clean : false,
+ attrib_white : false,
+
+ style_white : false,
+ style_black : false,
+
+
+ replaceTag : function(node)
+ {
+ if (!node.attributes || !node.attributes.length) {
+ return true;
+ }
+
+ for (var i = node.attributes.length-1; i > -1 ; i--) {
+ var a = node.attributes[i];
+ //console.log(a);
+ if (this.attrib_white.length && this.attrib_white.indexOf(a.name.toLowerCase()) < 0) {
+ node.removeAttribute(a.name);
+ continue;
+ }
+
+
+
+ if (a.name.toLowerCase().substr(0,2)=='on') {
+ node.removeAttribute(a.name);
+ continue;
+ }
+
+
+ if (this.attrib_black.indexOf(a.name.toLowerCase()) > -1) {
+ node.removeAttribute(a.name);
+ continue;
+ }
+ if (this.attrib_clean.indexOf(a.name.toLowerCase()) > -1) {
+ this.cleanAttr(node,a.name,a.value); // fixme..
+ continue;
+ }
+ if (a.name == 'style') {
+ this.cleanStyle(node,a.name,a.value);
+ continue;
+ }
+ /// clean up MS crap..
+ // tecnically this should be a list of valid class'es..
+
+
+ if (a.name == 'class') {
+ if (a.value.match(/^Mso/)) {
+ node.removeAttribute('class');
+ }
+
+ if (a.value.match(/^body$/)) {
+ node.removeAttribute('class');
+ }
+ continue;
+ }
+
+
+ // style cleanup!?
+ // class cleanup?
+
+ }
+ return true; // clean children
+ },
+
+ cleanAttr: function(node, n,v)
+ {
+
+ if (v.match(/^\./) || v.match(/^\//)) {
+ return;
+ }
+ if (v.match(/^(http|https):\/\//)
+ || v.match(/^mailto:/)
+ || v.match(/^ftp:/)
+ || v.match(/^data:/)
+ ) {
+ return;
+ }
+ if (v.match(/^#/)) {
+ return;
+ }
+ if (v.match(/^\{/)) { // allow template editing.
+ return;
+ }
+// Roo.log("(REMOVE TAG)"+ node.tagName +'.' + n + '=' + v);
+ node.removeAttribute(n);
+
+ },
+ cleanStyle : function(node, n,v)
+ {
+ if (v.match(/expression/)) { //XSS?? should we even bother..
+ node.removeAttribute(n);
+ return;
+ }
+
+ var parts = v.split(/;/);
+ var clean = [];
+
+ Roo.each(parts, function(p) {
+ p = p.replace(/^\s+/g,'').replace(/\s+$/g,'');
+ if (!p.length) {
+ return true;
+ }
+ var l = p.split(':').shift().replace(/\s+/g,'');
+ l = l.replace(/^\s+/g,'').replace(/\s+$/g,'');
+
+ if ( this.style_black.length && (this.style_black.indexOf(l) > -1 || this.style_black.indexOf(l.toLowerCase()) > -1)) {
+ return true;
+ }
+ //Roo.log()
+ // only allow 'c whitelisted system attributes'
+ if ( this.style_white.length && style_white.indexOf(l) < 0 && style_white.indexOf(l.toLowerCase()) < 0 ) {
+ return true;
+ }
+
+
+ clean.push(p);
+ return true;
+ },this);
+ if (clean.length) {
+ node.setAttribute(n, clean.join(';'));
+ } else {
+ node.removeAttribute(n);
+ }
+
+ }
+
+
+
+
+});/**
+ * @class Roo.htmleditor.FilterBlack
+ * remove blacklisted elements.
+ * @constructor
+ * Run a new Blacklisted Filter
+ * @param {Object} config Configuration options
+ */
+
+Roo.htmleditor.FilterBlack = function(cfg)
+{
+ Roo.apply(this, cfg);
+ this.walk(cfg.node);
+}
+
+Roo.extend(Roo.htmleditor.FilterBlack, Roo.htmleditor.Filter,
+{
+ tag : true, // all elements.
+
+ replaceTag : function(n)
+ {
+ n.parentNode.removeChild(n);
+ }
+});
+/**
+ * @class Roo.htmleditor.FilterComment
+ * remove comments.
+ * @constructor
+* Run a new Comments Filter
+* @param {Object} config Configuration options
+ */
+Roo.htmleditor.FilterComment = function(cfg)
+{
+ this.walk(cfg.node);
+}
+
+Roo.extend(Roo.htmleditor.FilterComment, Roo.htmleditor.Filter,
+{
+
+ replaceComment : function(n)
+ {
+ n.parentNode.removeChild(n);
+ }
+});/**
+ * @class Roo.htmleditor.FilterKeepChildren
+ * remove tags but keep children
+ * @constructor
+ * Run a new Keep Children Filter
+ * @param {Object} config Configuration options
+ */
+
+Roo.htmleditor.FilterKeepChildren = function(cfg)
+{
+ Roo.apply(this, cfg);
+ if (this.tag === false) {
+ return; // dont walk.. (you can use this to use this just to do a child removal on a single tag )
+ }
+ this.walk(cfg.node);
+}
+
+Roo.extend(Roo.htmleditor.FilterKeepChildren, Roo.htmleditor.FilterBlack,
+{
+
+
+ replaceTag : function(node)
+ {
+ // walk children...
+ //Roo.log(node);
+ var ar = Array.from(node.childNodes);
+ //remove first..
+ for (var i = 0; i < ar.length; i++) {
+ if (ar[i].nodeType == 1) {
+ if (
+ (typeof(this.tag) == 'object' && this.tag.indexOf(ar[i].tagName) > -1)
+ || // array and it matches
+ (typeof(this.tag) == 'string' && this.tag == ar[i].tagName)
+ ) {
+ this.replaceTag(ar[i]); // child is blacklisted as well...
+ continue;
+ }
+ }
+ }
+ ar = Array.from(node.childNodes);
+ for (var i = 0; i < ar.length; i++) {
+
+ node.removeChild(ar[i]);
+ // what if we need to walk these???
+ node.parentNode.insertBefore(ar[i], node);
+ if (this.tag !== false) {
+ this.walk(ar[i]);
+
+ }
+ }
+ node.parentNode.removeChild(node);
+ return false; // don't walk children
+
+
+ }
+});/**
+ * @class Roo.htmleditor.FilterParagraph
+ * paragraphs cause a nightmare for shared content - this filter is designed to be called ? at various points when editing
+ * like on 'push' to remove the <p> tags and replace them with line breaks.
+ * @constructor
+ * Run a new Paragraph Filter
+ * @param {Object} config Configuration options
+ */
+
+Roo.htmleditor.FilterParagraph = function(cfg)
+{
+ // no need to apply config.
+ this.walk(cfg.node);
+}
+
+Roo.extend(Roo.htmleditor.FilterParagraph, Roo.htmleditor.Filter,
+{
+
+
+ tag : 'P',
+
+
+ replaceTag : function(node)
+ {
+
+ if (node.childNodes.length == 1 &&
+ node.childNodes[0].nodeType == 3 &&
+ node.childNodes[0].textContent.trim().length < 1
+ ) {
+ // remove and replace with '<BR>';
+ node.parentNode.replaceChild(node.ownerDocument.createElement('BR'),node);
+ return false; // no need to walk..
+ }
+ var ar = Array.from(node.childNodes);
+ for (var i = 0; i < ar.length; i++) {
+ node.removeChild(ar[i]);
+ // what if we need to walk these???
+ node.parentNode.insertBefore(ar[i], node);
+ }
+ // now what about this?
+ // <p> </p>
+
+ // double BR.
+ node.parentNode.insertBefore(node.ownerDocument.createElement('BR'), node);
+ node.parentNode.insertBefore(node.ownerDocument.createElement('BR'), node);
+ node.parentNode.removeChild(node);
+
+ return false;
+
+ }
+
+});/**
+ * @class Roo.htmleditor.FilterSpan
+ * filter span's with no attributes out..
+ * @constructor
+ * Run a new Span Filter
+ * @param {Object} config Configuration options
+ */
+
+Roo.htmleditor.FilterSpan = function(cfg)
+{
+ // no need to apply config.
+ this.walk(cfg.node);
+}
+
+Roo.extend(Roo.htmleditor.FilterSpan, Roo.htmleditor.FilterKeepChildren,
+{
+
+ tag : 'SPAN',
+
+
+ replaceTag : function(node)
+ {
+ if (node.attributes && node.attributes.length > 0) {
+ return true; // walk if there are any.
+ }
+ Roo.htmleditor.FilterKeepChildren.prototype.replaceTag.call(this, node);
+ return false;
+
+ }
+
+});/**
+ * @class Roo.htmleditor.FilterTableWidth
+ try and remove table width data - as that frequently messes up other stuff.
+ *
+ * was cleanTableWidths.
+ *
+ * Quite often pasting from word etc.. results in tables with column and widths.
+ * This does not work well on fluid HTML layouts - like emails. - so this code should hunt an destroy them..
+ *
+ * @constructor
+ * Run a new Table Filter
+ * @param {Object} config Configuration options
+ */
+
+Roo.htmleditor.FilterTableWidth = function(cfg)
+{
+ // no need to apply config.
+ this.tag = ['TABLE', 'TD', 'TR', 'TH', 'THEAD', 'TBODY' ];
+ this.walk(cfg.node);
+}
+
+Roo.extend(Roo.htmleditor.FilterTableWidth, Roo.htmleditor.Filter,
+{
+
+
+
+ replaceTag: function(node) {
+
+
+
+ if (node.hasAttribute('width')) {
+ node.removeAttribute('width');
+ }
+
+
+ if (node.hasAttribute("style")) {
+ // pretty basic...
+
+ var styles = node.getAttribute("style").split(";");
+ var nstyle = [];
+ Roo.each(styles, function(s) {
+ if (!s.match(/:/)) {
+ return;
+ }
+ var kv = s.split(":");
+ if (kv[0].match(/^\s*(width|min-width)\s*$/)) {
+ return;
+ }
+ // what ever is left... we allow.
+ nstyle.push(s);
+ });
+ node.setAttribute("style", nstyle.length ? nstyle.join(';') : '');
+ if (!nstyle.length) {
+ node.removeAttribute('style');
+ }
+ }
+
+ return true; // continue doing children..
+ }
+});/**
+ * @class Roo.htmleditor.FilterWord
+ * try and clean up all the mess that Word generates.
+ *
+ * This is the 'nice version' - see 'Heavy' that white lists a very short list of elements, and multi-filters
+
+ * @constructor
+ * Run a new Span Filter
+ * @param {Object} config Configuration options
+ */
+
+Roo.htmleditor.FilterWord = function(cfg)
+{
+ // no need to apply config.
+ this.walk(cfg.node);
+}
+
+Roo.extend(Roo.htmleditor.FilterWord, Roo.htmleditor.Filter,
+{
+ tag: true,
+
+
+ /**
+ * Clean up MS wordisms...
+ */
+ replaceTag : function(node)
+ {
+
+ // no idea what this does - span with text, replaceds with just text.
+ if(
+ node.nodeName == 'SPAN' &&
+ !node.hasAttributes() &&
+ node.childNodes.length == 1 &&
+ node.firstChild.nodeName == "#text"
+ ) {
+ var textNode = node.firstChild;
+ node.removeChild(textNode);
+ if (node.getAttribute('lang') != 'zh-CN') { // do not space pad on chinese characters..
+ node.parentNode.insertBefore(node.ownerDocument.createTextNode(" "), node);
+ }
+ node.parentNode.insertBefore(textNode, node);
+ if (node.getAttribute('lang') != 'zh-CN') { // do not space pad on chinese characters..
+ node.parentNode.insertBefore(node.ownerDocument.createTextNode(" ") , node);
+ }
+
+ node.parentNode.removeChild(node);
+ return false; // dont do chidren - we have remove our node - so no need to do chdhilren?
+ }
+
+
+
+ if (node.tagName.toLowerCase().match(/^(style|script|applet|embed|noframes|noscript)$/)) {
+ node.parentNode.removeChild(node);
+ return false; // dont do chidlren
+ }
+ //Roo.log(node.tagName);
+ // remove - but keep children..
+ if (node.tagName.toLowerCase().match(/^(meta|link|\\?xml:|st1:|o:|v:|font)/)) {
+ //Roo.log('-- removed');
+ while (node.childNodes.length) {
+ var cn = node.childNodes[0];
+ node.removeChild(cn);
+ node.parentNode.insertBefore(cn, node);
+ // move node to parent - and clean it..
+ this.replaceTag(cn);
+ }
+ node.parentNode.removeChild(node);
+ /// no need to iterate chidlren = it's got none..
+ //this.iterateChildren(node, this.cleanWord);
+ return false; // no need to iterate children.
+ }
+ // clean styles
+ if (node.className.length) {
+
+ var cn = node.className.split(/\W+/);
+ var cna = [];
+ Roo.each(cn, function(cls) {
+ if (cls.match(/Mso[a-zA-Z]+/)) {
+ return;
+ }
+ cna.push(cls);
+ });
+ node.className = cna.length ? cna.join(' ') : '';
+ if (!cna.length) {
+ node.removeAttribute("class");
+ }
+ }
+
+ if (node.hasAttribute("lang")) {
+ node.removeAttribute("lang");
+ }
+
+ if (node.hasAttribute("style")) {
+
+ var styles = node.getAttribute("style").split(";");
+ var nstyle = [];
+ Roo.each(styles, function(s) {
+ if (!s.match(/:/)) {
+ return;
+ }
+ var kv = s.split(":");
+ if (kv[0].match(/^(mso-|line|font|background|margin|padding|color)/)) {
+ return;
+ }
+ // what ever is left... we allow.
+ nstyle.push(s);
+ });
+ node.setAttribute("style", nstyle.length ? nstyle.join(';') : '');
+ if (!nstyle.length) {
+ node.removeAttribute('style');
+ }
+ }
+ return true; // do children
+
+
+
+ }
+});
+/**
+ * @class Roo.htmleditor.FilterStyleToTag
+ * part of the word stuff... - certain 'styles' should be converted to tags.
+ * eg.
+ * font-weight: bold -> bold
+ * ?? super / subscrit etc..
+ *
+ * @constructor
+* Run a new style to tag filter.
+* @param {Object} config Configuration options
+ */
+Roo.htmleditor.FilterStyleToTag = function(cfg)
+{
+
+ this.tags = {
+ B : [ 'fontWeight' , 'bold'],
+ I : [ 'fontStyle' , 'italic'],
+ //pre : [ 'font-style' , 'italic'],
+ // h1.. h6 ?? font-size?
+ SUP : [ 'verticalAlign' , 'super' ],
+ SUB : [ 'verticalAlign' , 'sub' ]
+
+
+ };
+
+ Roo.apply(this, cfg);
+
+
+ this.walk(cfg.node);
+
+
+
+}
+
+
+Roo.extend(Roo.htmleditor.FilterStyleToTag, Roo.htmleditor.Filter,
+{
+ tag: true, // all tags
+
+ tags : false,
+
+
+ replaceTag : function(node)
+ {
+
+
+ if (node.getAttribute("style") === null) {
+ return true;
+ }
+ var inject = [];
+ for (var k in this.tags) {
+ if (node.style[this.tags[k][0]] == this.tags[k][1]) {
+ inject.push(k);
+ node.style.removeProperty(this.tags[k][0]);
+ }
+ }
+ if (!inject.length) {
+ return true;
+ }
+ var cn = Array.from(node.childNodes);
+ var nn = node;
+ Roo.each(inject, function(t) {
+ var nc = node.ownerDocument.createElement(t);
+ nn.appendChild(nc);
+ nn = nc;
+ });
+ for(var i = 0;i < cn.length;cn++) {
+ node.removeChild(cn[i]);
+ nn.appendChild(cn[i]);
+ }
+ return true /// iterate thru
+ }
+
+})/**
+ * @class Roo.htmleditor.FilterLongBr
+ * BR/BR/BR - keep a maximum of 2...
+ * @constructor
+ * Run a new Long BR Filter
+ * @param {Object} config Configuration options
+ */
+
+Roo.htmleditor.FilterLongBr = function(cfg)
+{
+ // no need to apply config.
+ this.walk(cfg.node);
+}
+
+Roo.extend(Roo.htmleditor.FilterLongBr, Roo.htmleditor.Filter,
+{
+
+
+ tag : 'BR',
+
+
+ replaceTag : function(node)
+ {
+
+ var ps = node.nextSibling;
+ while (ps && ps.nodeType == 3 && ps.nodeValue.trim().length < 1) {
+ ps = ps.nextSibling;
+ }
+
+ if (!ps && [ 'TD', 'TH', 'LI', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6' ].indexOf(node.parentNode.tagName) > -1) {
+ node.parentNode.removeChild(node); // remove last BR inside one fo these tags
+ return false;
+ }
+
+ if (!ps || ps.nodeType != 1) {
+ return false;
+ }
+
+ if (!ps || ps.tagName != 'BR') {
+
+ return false;
+ }
+
+
+
+
+
+ if (!node.previousSibling) {
+ return false;
+ }
+ var ps = node.previousSibling;
+
+ while (ps && ps.nodeType == 3 && ps.nodeValue.trim().length < 1) {
+ ps = ps.previousSibling;
+ }
+ if (!ps || ps.nodeType != 1) {
+ return false;
+ }
+ // if header or BR before.. then it's a candidate for removal.. - as we only want '2' of these..
+ if (!ps || [ 'BR', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6' ].indexOf(ps.tagName) < 0) {
+ return false;
+ }
+
+ node.parentNode.removeChild(node); // remove me...
+
+ return false; // no need to do children
+
+ }
+
+});
+
+/**
+ * @class Roo.htmleditor.FilterBlock
+ * removes id / data-block and contenteditable that are associated with blocks
+ * usage should be done on a cloned copy of the dom
+ * @constructor
+* Run a new Attribute Filter { node : xxxx }}
+* @param {Object} config Configuration options
+ */
+Roo.htmleditor.FilterBlock = function(cfg)
+{
+ Roo.apply(this, cfg);
+ var qa = cfg.node.querySelectorAll;
+ this.removeAttributes('data-block');
+ this.removeAttributes('contenteditable');
+ this.removeAttributes('id');
+
+}
+
+Roo.apply(Roo.htmleditor.FilterBlock.prototype,
+{
+ node: true, // all tags
+
+
+ removeAttributes : function(attr)
+ {
+ var ar = this.node.querySelectorAll('*[' + attr + ']');
+ for (var i =0;i<ar.length;i++) {
+ ar[i].removeAttribute(attr);
+ }
+ }
+
+
+
+
+});
+/**
+ * @class Roo.htmleditor.KeyEnter
+ * Handle Enter press..
+ * @cfg {Roo.HtmlEditorCore} core the editor.
+ * @constructor
+ * Create a new Filter.
+ * @param {Object} config Configuration options
+ */
+
+
+
+
+
+Roo.htmleditor.KeyEnter = function(cfg) {
+ Roo.apply(this, cfg);
+ // this does not actually call walk as it's really just a abstract class
+
+ Roo.get(this.core.doc.body).on('keypress', this.keypress, this);
+}
+
+//Roo.htmleditor.KeyEnter.i = 0;
+
+
+Roo.htmleditor.KeyEnter.prototype = {
+
+ core : false,
+
+ keypress : function(e)
+ {
+ if (e.charCode != 13 && e.charCode != 10) {
+ Roo.log([e.charCode,e]);
+ return true;
+ }
+ e.preventDefault();
+ // https://stackoverflow.com/questions/18552336/prevent-contenteditable-adding-div-on-enter-chrome
+ var doc = this.core.doc;
+ //add a new line
+
+
+ var sel = this.core.getSelection();
+ var range = sel.getRangeAt(0);
+ var n = range.commonAncestorContainer;
+ var pc = range.closest([ 'ol', 'ul']);
+ var pli = range.closest('li');
+ if (!pc || e.ctrlKey) {
+ sel.insertNode('br', 'after');
+
+ this.core.undoManager.addEvent();
+ this.core.fireEditorEvent(e);
+ return false;
+ }
+
+ // deal with <li> insetion
+ if (pli.innerText.trim() == '' &&
+ pli.previousSibling &&
+ pli.previousSibling.nodeName == 'LI' &&
+ pli.previousSibling.innerText.trim() == '') {
+ pli.parentNode.removeChild(pli.previousSibling);
+ sel.cursorAfter(pc);
+ this.core.undoManager.addEvent();
+ this.core.fireEditorEvent(e);
+ return false;
+ }
+
+ var li = doc.createElement('LI');
+ li.innerHTML = ' ';
+ if (!pli || !pli.firstSibling) {
+ pc.appendChild(li);
+ } else {
+ pli.parentNode.insertBefore(li, pli.firstSibling);
+ }
+ sel.cursorText (li.firstChild);
+
+ this.core.undoManager.addEvent();
+ this.core.fireEditorEvent(e);
+
+ return false;
+
+
+
+
+
+ }
+};
+
+/**
+ * @class Roo.htmleditor.Block
+ * Base class for html editor blocks - do not use it directly .. extend it..
+ * @cfg {DomElement} node The node to apply stuff to.
+ * @cfg {String} friendly_name the name that appears in the context bar about this block
+ * @cfg {Object} Context menu - see Roo.form.HtmlEditor.ToolbarContext
+
+ * @constructor
+ * Create a new Filter.
+ * @param {Object} config Configuration options
+ */
+
+Roo.htmleditor.Block = function(cfg)
+{
+ // do nothing .. should not be called really.
+}
+/**
+ * factory method to get the block from an element (using cache if necessary)
+ * @static
+ * @param {HtmlElement} the dom element
+ */
+Roo.htmleditor.Block.factory = function(node)
+{
+ var cc = Roo.htmleditor.Block.cache;
+ var id = Roo.get(node).id;
+ if (typeof(cc[id]) != 'undefined' && (!cc[id].node || cc[id].node.closest('body'))) {
+ Roo.htmleditor.Block.cache[id].readElement(node);
+ return Roo.htmleditor.Block.cache[id];
+ }
+ var db = node.getAttribute('data-block');
+ if (!db) {
+ db = node.nodeName.toLowerCase().toUpperCaseFirst();
+ }
+ var cls = Roo.htmleditor['Block' + db];
+ if (typeof(cls) == 'undefined') {
+ //Roo.log(node.getAttribute('data-block'));
+ Roo.log("OOps missing block : " + 'Block' + db);
+ return false;
+ }
+ Roo.htmleditor.Block.cache[id] = new cls({ node: node });
+ return Roo.htmleditor.Block.cache[id]; /// should trigger update element
+};
+
+/**
+ * initalize all Elements from content that are 'blockable'
+ * @static
+ * @param the body element
+ */
+Roo.htmleditor.Block.initAll = function(body, type)
+{
+ if (typeof(type) == 'undefined') {
+ var ia = Roo.htmleditor.Block.initAll;
+ ia(body,'table');
+ ia(body,'td');
+ ia(body,'figure');
+ return;
+ }
+ Roo.each(Roo.get(body).query(type), function(e) {
+ Roo.htmleditor.Block.factory(e);
+ },this);
+};
+// question goes here... do we need to clear out this cache sometimes?
+// or show we make it relivant to the htmleditor.
+Roo.htmleditor.Block.cache = {};
+
+Roo.htmleditor.Block.prototype = {
+
+ node : false,
+
+ // used by context menu
+ friendly_name : 'Based Block',
+
+ // text for button to delete this element
+ deleteTitle : false,
+
+ context : false,
+ /**
+ * Update a node with values from this object
+ * @param {DomElement} node
+ */
+ updateElement : function(node)
+ {
+ Roo.DomHelper.update(node === undefined ? this.node : node, this.toObject());
+ },
+ /**
+ * convert to plain HTML for calling insertAtCursor..
+ */
+ toHTML : function()
+ {
+ return Roo.DomHelper.markup(this.toObject());
+ },
+ /**
+ * used by readEleemnt to extract data from a node
+ * may need improving as it's pretty basic
+
+ * @param {DomElement} node
+ * @param {String} tag - tag to find, eg. IMG ?? might be better to use DomQuery ?
+ * @param {String} attribute (use html - for contents, style for using next param as style, or false to return the node)
+ * @param {String} style the style property - eg. text-align
+ */
+ getVal : function(node, tag, attr, style)
+ {
+ var n = node;
+ if (tag !== true && n.tagName != tag.toUpperCase()) {
+ // in theory we could do figure[3] << 3rd figure? or some more complex search..?
+ // but kiss for now.
+ n = node.getElementsByTagName(tag).item(0);
+ }
+ if (!n) {
+ return '';
+ }
+ if (attr === false) {
+ return n;
+ }
+ if (attr == 'html') {
+ return n.innerHTML;
+ }
+ if (attr == 'style') {
+ return n.style[style];
+ }
+
+ return n.hasAttribute(attr) ? n.getAttribute(attr) : '';
+
+ },
+ /**
+ * create a DomHelper friendly object - for use with
+ * Roo.DomHelper.markup / overwrite / etc..
+ * (override this)
+ */
+ toObject : function()
+ {
+ return {};
+ },
+ /**
+ * Read a node that has a 'data-block' property - and extract the values from it.
+ * @param {DomElement} node - the node
+ */
+ readElement : function(node)
+ {
+
+ }
+
+
+};
+
+
+
+/**
+ * @class Roo.htmleditor.BlockFigure
+ * Block that has an image and a figcaption
+ * @cfg {String} image_src the url for the image
+ * @cfg {String} align (left|right) alignment for the block default left
+ * @cfg {String} caption the text to appear below (and in the alt tag)
+ * @cfg {String} caption_display (block|none) display or not the caption
+ * @cfg {String|number} image_width the width of the image number or %?
+ * @cfg {String|number} image_height the height of the image number or %?
+ *
+ * @constructor
+ * Create a new Filter.
+ * @param {Object} config Configuration options
+ */
+
+Roo.htmleditor.BlockFigure = function(cfg)
+{
+ if (cfg.node) {
+ this.readElement(cfg.node);
+ this.updateElement(cfg.node);
+ }
+ Roo.apply(this, cfg);
+}
+Roo.extend(Roo.htmleditor.BlockFigure, Roo.htmleditor.Block, {
+
+
+ // setable values.
+ image_src: '',
+ align: 'center',
+ caption : '',
+ caption_display : 'block',
+ width : '100%',
+ cls : '',
+ href: '',
+ video_url : '',
+
+ // margin: '2%', not used
+
+ text_align: 'left', // (left|right) alignment for the text caption default left. - not used at present
+
+
+ // used by context menu
+ friendly_name : 'Image with caption',
+ deleteTitle : "Delete Image and Caption",
+
+ contextMenu : function(toolbar)
+ {
+
+ var block = function() {
+ return Roo.htmleditor.Block.factory(toolbar.tb.selectedNode);
+ };
+
+
+ var rooui = typeof(Roo.bootstrap) == 'undefined' ? Roo : Roo.bootstrap;
+
+ var syncValue = toolbar.editorcore.syncValue;
+
+ var fields = {};
+
+ return [
+ {
+ xtype : 'TextItem',
+ text : "Source: ",
+ xns : rooui.Toolbar //Boostrap?
+ },
+ {
+ xtype : 'Button',
+ text: 'Change Image URL',
+
+ listeners : {
+ click: function (btn, state)
+ {
+ var b = block();
+
+ Roo.MessageBox.show({
+ title : "Image Source URL",
+ msg : "Enter the url for the image",
+ buttons: Roo.MessageBox.OKCANCEL,
+ fn: function(btn, val){
+ if (btn != 'ok') {
+ return;
+ }
+ b.image_src = val;
+ b.updateElement();
+ syncValue();
+ toolbar.editorcore.onEditorEvent();
+ },
+ minWidth:250,
+ prompt:true,
+ //multiline: multiline,
+ modal : true,
+ value : b.image_src
+ });
+ }
+ },
+ xns : rooui.Toolbar
+ },
+
+ {
+ xtype : 'Button',
+ text: 'Change Link URL',
+
+ listeners : {
+ click: function (btn, state)
+ {
+ var b = block();
+
+ Roo.MessageBox.show({
+ title : "Link URL",
+ msg : "Enter the url for the link - leave blank to have no link",
+ buttons: Roo.MessageBox.OKCANCEL,
+ fn: function(btn, val){
+ if (btn != 'ok') {
+ return;
+ }
+ b.href = val;
+ b.updateElement();
+ syncValue();
+ toolbar.editorcore.onEditorEvent();
+ },
+ minWidth:250,
+ prompt:true,
+ //multiline: multiline,
+ modal : true,
+ value : b.href
+ });
+ }
+ },
+ xns : rooui.Toolbar
+ },
+ {
+ xtype : 'Button',
+ text: 'Show Video URL',
+
+ listeners : {
+ click: function (btn, state)
+ {
+ Roo.MessageBox.alert("Video URL",
+ block().video_url == '' ? 'This image is not linked ot a video' :
+ 'The image is linked to: <a target="_new" href="' + block().video_url + '">' + block().video_url + '</a>');
+ }
+ },
+ xns : rooui.Toolbar
+ },
+
+
+ {
+ xtype : 'TextItem',
+ text : "Width: ",
+ xns : rooui.Toolbar //Boostrap?
+ },
+ {
+ xtype : 'ComboBox',
+ allowBlank : false,
+ displayField : 'val',
+ editable : true,
+ listWidth : 100,
+ triggerAction : 'all',
+ typeAhead : true,
+ valueField : 'val',
+ width : 70,
+ name : 'width',
+ listeners : {
+ select : function (combo, r, index)
+ {
+ toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+ var b = block();
+ b.width = r.get('val');
+ b.updateElement();
+ syncValue();
+ toolbar.editorcore.onEditorEvent();
+ }
+ },
+ xns : rooui.form,
+ store : {
+ xtype : 'SimpleStore',
+ data : [
+ ['50%'],
+ ['80%'],
+ ['100%']
+ ],
+ fields : [ 'val'],
+ xns : Roo.data
+ }
+ },
+ {
+ xtype : 'TextItem',
+ text : "Align: ",
+ xns : rooui.Toolbar //Boostrap?
+ },
+ {
+ xtype : 'ComboBox',
+ allowBlank : false,
+ displayField : 'val',
+ editable : true,
+ listWidth : 100,
+ triggerAction : 'all',
+ typeAhead : true,
+ valueField : 'val',
+ width : 70,
+ name : 'align',
+ listeners : {
+ select : function (combo, r, index)
+ {
+ toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+ var b = block();
+ b.align = r.get('val');
+ b.updateElement();
+ syncValue();
+ toolbar.editorcore.onEditorEvent();
+ }
+ },
+ xns : rooui.form,
+ store : {
+ xtype : 'SimpleStore',
+ data : [
+ ['left'],
+ ['right'],
+ ['center']
+ ],
+ fields : [ 'val'],
+ xns : Roo.data
+ }
+ },
+
+
+ {
+ xtype : 'Button',
+ text: 'Hide Caption',
+ name : 'caption_display',
+ pressed : false,
+ enableToggle : true,
+ setValue : function(v) {
+ // this trigger toggle.
+
+ this.setText(v ? "Hide Caption" : "Show Caption");
+ this.setPressed(v != 'block');
+ },
+ listeners : {
+ toggle: function (btn, state)
+ {
+ var b = block();
+ b.caption_display = b.caption_display == 'block' ? 'none' : 'block';
+ this.setText(b.caption_display == 'block' ? "Hide Caption" : "Show Caption");
+ b.updateElement();
+ syncValue();
+ toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+ toolbar.editorcore.onEditorEvent();
+ }
+ },
+ xns : rooui.Toolbar
+ }
+ ];
+
+ },
+ /**
+ * create a DomHelper friendly object - for use with
+ * Roo.DomHelper.markup / overwrite / etc..
+ */
+ toObject : function()
+ {
+ var d = document.createElement('div');
+ d.innerHTML = this.caption;
+
+ var m = this.width != '100%' && this.align == 'center' ? '0 auto' : 0;
+
+ var iw = this.align == 'center' ? this.width : '100%';
+ var img = {
+ tag : 'img',
+ contenteditable : 'false',
+ src : this.image_src,
+ alt : d.innerText.replace(/\n/g, " ").replace(/\s+/g, ' ').trim(), // removeHTML and reduce spaces..
+ style: {
+ width : iw,
+ maxWidth : iw + ' !important', // this is not getting rendered?
+ margin : m
+
+ }
+ };
+ /*
+ '<div class="{0}" width="420" height="315" src="{1}" frameborder="0" allowfullscreen>' +
+ '<a href="{2}">' +
+ '<img class="{0}-thumbnail" src="{3}/Images/{4}/{5}#image-{4}" />' +
+ '</a>' +
+ '</div>',
+ */
+
+ if (this.href.length > 0) {
+ img = {
+ tag : 'a',
+ href: this.href,
+ contenteditable : 'true',
+ cn : [
+ img
+ ]
+ };
+ }
+
+
+ if (this.video_url.length > 0) {
+ img = {
+ tag : 'div',
+ cls : this.cls,
+ frameborder : 0,
+ allowfullscreen : true,
+ width : 420, // these are for video tricks - that we replace the outer
+ height : 315,
+ src : this.video_url,
+ cn : [
+ img
+ ]
+ };
+ }
+ // we remove caption totally if its hidden... - will delete data.. but otherwise we end up with fake caption
+ var captionhtml = this.caption_display == 'none' ? '' : (this.caption.length ? this.caption : "Caption");
+
+
+ var ret = {
+ tag: 'figure',
+ 'data-block' : 'Figure',
+ 'data-width' : this.width,
+ contenteditable : 'false',
+
+ style : {
+ display: 'block',
+ float : this.align ,
+ maxWidth : this.align == 'center' ? '100% !important' : (this.width + ' !important'),
+ width : this.align == 'center' ? '100%' : this.width,
+ margin: '0px',
+ padding: this.align == 'center' ? '0' : '0 10px' ,
+ textAlign : this.align // seems to work for email..
+
+ },
+
+
+ align : this.align,
+ cn : [
+ img,
+
+ {
+ tag: 'figcaption',
+ 'data-display' : this.caption_display,
+ style : {
+ textAlign : 'left',
+ fontSize : '16px',
+ lineHeight : '24px',
+ display : this.caption_display,
+ maxWidth : (this.align == 'center' ? this.width : '100%' ) + ' !important',
+ margin: m,
+ width: this.align == 'center' ? this.width : '100%'
+
+
+ },
+ cls : this.cls.length > 0 ? (this.cls + '-thumbnail' ) : '',
+ cn : [
+ {
+ tag: 'div',
+ style : {
+ marginTop : '16px',
+ textAlign : 'left'
+ },
+ align: 'left',
+ cn : [
+ {
+ // we can not rely on yahoo syndication to use CSS elements - so have to use '<i>' to encase stuff.
+ tag : 'i',
+ contenteditable : true,
+ html : captionhtml
+ }
+
+ ]
+ }
+
+ ]
+
+ }
+ ]
+ };
+ return ret;
+
+ },
+
+ readElement : function(node)
+ {
+ // this should not really come from the link...
+ this.video_url = this.getVal(node, 'div', 'src');
+ this.cls = this.getVal(node, 'div', 'class');
+ this.href = this.getVal(node, 'a', 'href');
+
+
+ this.image_src = this.getVal(node, 'img', 'src');
+
+ this.align = this.getVal(node, 'figure', 'align');
+ var figcaption = this.getVal(node, 'figcaption', false);
+ if (figcaption !== '') {
+ this.caption = this.getVal(figcaption, 'i', 'html');
+ }
+
+
+ this.caption_display = this.getVal(node, 'figcaption', 'data-display');
+ //this.text_align = this.getVal(node, 'figcaption', 'style','text-align');
+ this.width = this.getVal(node, true, 'data-width');
+ //this.margin = this.getVal(node, 'figure', 'style', 'margin');
+
+ },
+ removeNode : function()
+ {
+ return this.node;
+ }
+
+
+
+
+
+
+
+
+})
+
+
+
+/**
+ * @class Roo.htmleditor.BlockTable
+ * Block that manages a table
+ *
+ * @constructor
+ * Create a new Filter.
+ * @param {Object} config Configuration options
+ */
+
+Roo.htmleditor.BlockTable = function(cfg)
+{
+ if (cfg.node) {
+ this.readElement(cfg.node);
+ this.updateElement(cfg.node);
+ }
+ Roo.apply(this, cfg);
+ if (!cfg.node) {
+ this.rows = [];
+ for(var r = 0; r < this.no_row; r++) {
+ this.rows[r] = [];
+ for(var c = 0; c < this.no_col; c++) {
+ this.rows[r][c] = this.emptyCell();
+ }
+ }
+ }
+
+
+}
+Roo.extend(Roo.htmleditor.BlockTable, Roo.htmleditor.Block, {
+
+ rows : false,
+ no_col : 1,
+ no_row : 1,
+
+
+ width: '100%',
+
+ // used by context menu
+ friendly_name : 'Table',
+ deleteTitle : 'Delete Table',
+ // context menu is drawn once..
+
+ contextMenu : function(toolbar)
+ {
+
+ var block = function() {
+ return Roo.htmleditor.Block.factory(toolbar.tb.selectedNode);
+ };
+
+
+ var rooui = typeof(Roo.bootstrap) == 'undefined' ? Roo : Roo.bootstrap;
+
+ var syncValue = toolbar.editorcore.syncValue;
+
+ var fields = {};
+
+ return [
+ {
+ xtype : 'TextItem',
+ text : "Width: ",
+ xns : rooui.Toolbar //Boostrap?
+ },
+ {
+ xtype : 'ComboBox',
+ allowBlank : false,
+ displayField : 'val',
+ editable : true,
+ listWidth : 100,
+ triggerAction : 'all',
+ typeAhead : true,
+ valueField : 'val',
+ width : 100,
+ name : 'width',
+ listeners : {
+ select : function (combo, r, index)
+ {
+ toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+ var b = block();
+ b.width = r.get('val');
+ b.updateElement();
+ syncValue();
+ toolbar.editorcore.onEditorEvent();
+ }
+ },
+ xns : rooui.form,
+ store : {
+ xtype : 'SimpleStore',
+ data : [
+ ['100%'],
+ ['auto']
+ ],
+ fields : [ 'val'],
+ xns : Roo.data
+ }
+ },
+ // -------- Cols
+
+ {
+ xtype : 'TextItem',
+ text : "Columns: ",
+ xns : rooui.Toolbar //Boostrap?
+ },
+
+ {
+ xtype : 'Button',
+ text: '-',
+ listeners : {
+ click : function (_self, e)
+ {
+ toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+ block().removeColumn();
+ syncValue();
+ toolbar.editorcore.onEditorEvent();
+ }
+ },
+ xns : rooui.Toolbar
+ },
+ {
+ xtype : 'Button',
+ text: '+',
+ listeners : {
+ click : function (_self, e)
+ {
+ toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+ block().addColumn();
+ syncValue();
+ toolbar.editorcore.onEditorEvent();
+ }
+ },
+ xns : rooui.Toolbar
+ },
+ // -------- ROWS
+ {
+ xtype : 'TextItem',
+ text : "Rows: ",
+ xns : rooui.Toolbar //Boostrap?
+ },
+
+ {
+ xtype : 'Button',
+ text: '-',
+ listeners : {
+ click : function (_self, e)
+ {
+ toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+ block().removeRow();
+ syncValue();
+ toolbar.editorcore.onEditorEvent();
+ }
+ },
+ xns : rooui.Toolbar
+ },
+ {
+ xtype : 'Button',
+ text: '+',
+ listeners : {
+ click : function (_self, e)
+ {
+ block().addRow();
+ syncValue();
+ toolbar.editorcore.onEditorEvent();
+ }
+ },
+ xns : rooui.Toolbar
+ },
+ // -------- ROWS
+ {
+ xtype : 'Button',
+ text: 'Reset Column Widths',
+ listeners : {
+
+ click : function (_self, e)
+ {
+ block().resetWidths();
+ syncValue();
+ toolbar.editorcore.onEditorEvent();
+ }
+ },
+ xns : rooui.Toolbar
+ }
+
+
+
+ ];
+
+ },
+
+
+ /**
+ * create a DomHelper friendly object - for use with
+ * Roo.DomHelper.markup / overwrite / etc..
+ * ?? should it be called with option to hide all editing features?
+ */
+ toObject : function()
+ {
+
+ var ret = {
+ tag : 'table',
+ contenteditable : 'false', // this stops cell selection from picking the table.
+ 'data-block' : 'Table',
+ style : {
+ width: this.width,
+ border : 'solid 1px #000', // ??? hard coded?
+ 'border-collapse' : 'collapse'
+ },
+ cn : [
+ { tag : 'tbody' , cn : [] }
+ ]
+ };
+
+ // do we have a head = not really
+ var ncols = 0;
+ Roo.each(this.rows, function( row ) {
+ var tr = {
+ tag: 'tr',
+ style : {
+ margin: '6px',
+ border : 'solid 1px #000',
+ textAlign : 'left'
+ },
+ cn : [ ]
+ };
+
+ ret.cn[0].cn.push(tr);
+ // does the row have any properties? ?? height?
+ var nc = 0;
+ Roo.each(row, function( cell ) {
+
+ var td = {
+ tag : 'td',
+ contenteditable : 'true',
+ 'data-block' : 'Td',
+ html : cell.html,
+ style : cell.style
+ };
+ if (cell.colspan > 1) {
+ td.colspan = cell.colspan ;
+ nc += cell.colspan;
+ } else {
+ nc++;
+ }
+ if (cell.rowspan > 1) {
+ td.rowspan = cell.rowspan ;
+ }
+
+
+ // widths ?
+ tr.cn.push(td);
+
+
+ }, this);
+ ncols = Math.max(nc, ncols);
+
+
+ }, this);
+ // add the header row..
+
+ ncols++;
+
+
+ return ret;
+
+ },
+
+ readElement : function(node)
+ {
+ node = node ? node : this.node ;
+ this.width = this.getVal(node, true, 'style', 'width') || '100%';
+
+ this.rows = [];
+ this.no_row = 0;
+ var trs = Array.from(node.rows);
+ trs.forEach(function(tr) {
+ var row = [];
+ this.rows.push(row);
+
+ this.no_row++;
+ var no_column = 0;
+ Array.from(tr.cells).forEach(function(td) {
+
+ var add = {
+ colspan : td.hasAttribute('colspan') ? td.getAttribute('colspan')*1 : 1,
+ rowspan : td.hasAttribute('rowspan') ? td.getAttribute('rowspan')*1 : 1,
+ style : td.hasAttribute('style') ? td.getAttribute('style') : '',
+ html : td.innerHTML
+ };
+ no_column += add.colspan;
+
+
+ row.push(add);
+
+
+ },this);
+ this.no_col = Math.max(this.no_col, no_column);
+
+
+ },this);
+
+
+ },
+ normalizeRows: function()
+ {
+ var ret= [];
+ var rid = -1;
+ this.rows.forEach(function(row) {
+ rid++;
+ ret[rid] = [];
+ row = this.normalizeRow(row);
+ var cid = 0;
+ row.forEach(function(c) {
+ while (typeof(ret[rid][cid]) != 'undefined') {
+ cid++;
+ }
+ if (typeof(ret[rid]) == 'undefined') {
+ ret[rid] = [];
+ }
+ ret[rid][cid] = c;
+ c.row = rid;
+ c.col = cid;
+ if (c.rowspan < 2) {
+ return;
+ }
+
+ for(var i = 1 ;i < c.rowspan; i++) {
+ if (typeof(ret[rid+i]) == 'undefined') {
+ ret[rid+i] = [];
+ }
+ ret[rid+i][cid] = c;
+ }
+ });
+ }, this);
+ return ret;
+
+ },
+
+ normalizeRow: function(row)
+ {
+ var ret= [];
+ row.forEach(function(c) {
+ if (c.colspan < 2) {
+ ret.push(c);
+ return;
+ }
+ for(var i =0 ;i < c.colspan; i++) {
+ ret.push(c);
+ }
+ });
+ return ret;
+
+ },
+
+ deleteColumn : function(sel)
+ {
+ if (!sel || sel.type != 'col') {
+ return;
+ }
+ if (this.no_col < 2) {
+ return;
+ }
+
+ this.rows.forEach(function(row) {
+ var cols = this.normalizeRow(row);
+ var col = cols[sel.col];
+ if (col.colspan > 1) {
+ col.colspan --;
+ } else {
+ row.remove(col);
+ }
+
+ }, this);
+ this.no_col--;
+
+ },
+ removeColumn : function()
+ {
+ this.deleteColumn({
+ type: 'col',
+ col : this.no_col-1
+ });
+ this.updateElement();
+ },
+
+
+ addColumn : function()
+ {
+
+ this.rows.forEach(function(row) {
+ row.push(this.emptyCell());
+
+ }, this);
+ this.updateElement();
+ },
+
+ deleteRow : function(sel)
+ {
+ if (!sel || sel.type != 'row') {
+ return;
+ }
+
+ if (this.no_row < 2) {
+ return;
+ }
+
+ var rows = this.normalizeRows();
+
+
+ rows[sel.row].forEach(function(col) {
+ if (col.rowspan > 1) {
+ col.rowspan--;
+ } else {
+ col.remove = 1; // flage it as removed.
+ }
+
+ }, this);
+ var newrows = [];
+ this.rows.forEach(function(row) {
+ newrow = [];
+ row.forEach(function(c) {
+ if (typeof(c.remove) == 'undefined') {
+ newrow.push(c);
+ }
+
+ });
+ if (newrow.length > 0) {
+ newrows.push(row);
+ }
+ });
+ this.rows = newrows;
+
+
+
+ this.no_row--;
+ this.updateElement();
+
+ },
+ removeRow : function()
+ {
+ this.deleteRow({
+ type: 'row',
+ row : this.no_row-1
+ });
+
+ },
+
+
+ addRow : function()
+ {
+
+ var row = [];
+ for (var i = 0; i < this.no_col; i++ ) {
+
+ row.push(this.emptyCell());
+
+ }
+ this.rows.push(row);
+ this.updateElement();
+
+ },
+
+ // the default cell object... at present...
+ emptyCell : function() {
+ return (new Roo.htmleditor.BlockTd({})).toObject();
+
+
+ },
+
+ removeNode : function()
+ {
+ return this.node;
+ },
+
+
+
+ resetWidths : function()
+ {
+ Array.from(this.node.getElementsByTagName('td')).forEach(function(n) {
+ var nn = Roo.htmleditor.Block.factory(n);
+ nn.width = '';
+ nn.updateElement(n);
+ });
+ }
+
+
+
+
+})
+
+/**
+ *
+ * editing a TD?
+ *
+ * since selections really work on the table cell, then editing really should work from there
+ *
+ * The original plan was to support merging etc... - but that may not be needed yet..
+ *
+ * So this simple version will support:
+ * add/remove cols
+ * adjust the width +/-
+ * reset the width...
+ *
+ *
+ */
+
+
+
+
+/**
+ * @class Roo.htmleditor.BlockTable
+ * Block that manages a table
+ *
+ * @constructor
+ * Create a new Filter.
+ * @param {Object} config Configuration options
+ */
+
+Roo.htmleditor.BlockTd = function(cfg)
+{
+ if (cfg.node) {
+ this.readElement(cfg.node);
+ this.updateElement(cfg.node);
+ }
+ Roo.apply(this, cfg);
+
+
+
+}
+Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
+
+ node : false,
+
+ width: '',
+ textAlign : 'left',
+ valign : 'top',
+
+ colspan : 1,
+ rowspan : 1,
+
+
+ // used by context menu
+ friendly_name : 'Table Cell',
+ deleteTitle : false, // use our customer delete
+
+ // context menu is drawn once..
+
+ contextMenu : function(toolbar)
+ {
+
+ var cell = function() {
+ return Roo.htmleditor.Block.factory(toolbar.tb.selectedNode);
+ };
+
+ var table = function() {
+ return Roo.htmleditor.Block.factory(toolbar.tb.selectedNode.closest('table'));
+ };
+
+ var lr = false;
+ var saveSel = function()
+ {
+ lr = toolbar.editorcore.getSelection().getRangeAt(0);
+ }
+ var restoreSel = function()
+ {
+ if (lr) {
+ (function() {
+ toolbar.editorcore.focus();
+ var cr = toolbar.editorcore.getSelection();
+ cr.removeAllRanges();
+ cr.addRange(lr);
+ toolbar.editorcore.onEditorEvent();
+ }).defer(10, this);
+
+
+ }
+ }
+
+ var rooui = typeof(Roo.bootstrap) == 'undefined' ? Roo : Roo.bootstrap;
+
+ var syncValue = toolbar.editorcore.syncValue;
+
+ var fields = {};
+
+ return [
+ {
+ xtype : 'Button',
+ text : 'Edit Table',
+ listeners : {
+ click : function() {
+ var t = toolbar.tb.selectedNode.closest('table');
+ toolbar.editorcore.selectNode(t);
+ toolbar.editorcore.onEditorEvent();
+ }
+ }
+
+ },
+
+
+
+ {
+ xtype : 'TextItem',
+ text : "Column Width: ",
+ xns : rooui.Toolbar
+
+ },
+ {
+ xtype : 'Button',
+ text: '-',
+ listeners : {
+ click : function (_self, e)
+ {
+ toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+ cell().shrinkColumn();
+ syncValue();
+ toolbar.editorcore.onEditorEvent();
+ }
+ },
+ xns : rooui.Toolbar
+ },
+ {
+ xtype : 'Button',
+ text: '+',
+ listeners : {
+ click : function (_self, e)
+ {
+ toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+ cell().growColumn();
+ syncValue();
+ toolbar.editorcore.onEditorEvent();
+ }
+ },
+ xns : rooui.Toolbar
+ },
+
+ {
+ xtype : 'TextItem',
+ text : "Vertical Align: ",
+ xns : rooui.Toolbar //Boostrap?
+ },
+ {
+ xtype : 'ComboBox',
+ allowBlank : false,
+ displayField : 'val',
+ editable : true,
+ listWidth : 100,
+ triggerAction : 'all',
+ typeAhead : true,
+ valueField : 'val',
+ width : 100,
+ name : 'valign',
+ listeners : {
+ select : function (combo, r, index)
+ {
+ toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+ var b = cell();
+ b.valign = r.get('val');
+ b.updateElement();
+ syncValue();
+ toolbar.editorcore.onEditorEvent();
+ }
+ },
+ xns : rooui.form,
+ store : {
+ xtype : 'SimpleStore',
+ data : [
+ ['top'],
+ ['middle'],
+ ['bottom'] // there are afew more...
+ ],
+ fields : [ 'val'],
+ xns : Roo.data
+ }
+ },
+
+ {
+ xtype : 'TextItem',
+ text : "Merge Cells: ",
+ xns : rooui.Toolbar
+
+ },
+
+
+ {
+ xtype : 'Button',
+ text: 'Right',
+ listeners : {
+ click : function (_self, e)
+ {
+ toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+ cell().mergeRight();
+ //block().growColumn();
+ syncValue();
+ toolbar.editorcore.onEditorEvent();
+ }
+ },
+ xns : rooui.Toolbar
+ },
+
+ {
+ xtype : 'Button',
+ text: 'Below',
+ listeners : {
+ click : function (_self, e)
+ {
+ toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+ cell().mergeBelow();
+ //block().growColumn();
+ syncValue();
+ toolbar.editorcore.onEditorEvent();
+ }
+ },
+ xns : rooui.Toolbar
+ },
+ {
+ xtype : 'TextItem',
+ text : "| ",
+ xns : rooui.Toolbar
+
+ },
+
+ {
+ xtype : 'Button',
+ text: 'Split',
+ listeners : {
+ click : function (_self, e)
+ {
+ //toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+ cell().split();
+ syncValue();
+ toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+ toolbar.editorcore.onEditorEvent();
+
+ }
+ },
+ xns : rooui.Toolbar
+ },
+ {
+ xtype : 'Fill',
+ xns : rooui.Toolbar
+
+ },
+
+
+ {
+ xtype : 'Button',
+ text: 'Delete',
+
+ xns : rooui.Toolbar,
+ menu : {
+ xtype : 'Menu',
+ xns : rooui.menu,
+ items : [
+ {
+ xtype : 'Item',
+ html: 'Column',
+ listeners : {
+ click : function (_self, e)
+ {
+ var t = table();
+
+ cell().deleteColumn();
+ syncValue();
+ toolbar.editorcore.selectNode(t.node);
+ toolbar.editorcore.onEditorEvent();
+ }
+ },
+ xns : rooui.menu
+ },
+ {
+ xtype : 'Item',
+ html: 'Row',
+ listeners : {
+ click : function (_self, e)
+ {
+ var t = table();
+ cell().deleteRow();
+ syncValue();
+
+ toolbar.editorcore.selectNode(t.node);
+ toolbar.editorcore.onEditorEvent();
+
+ }
+ },
+ xns : rooui.menu
+ },
+ {
+ xtype : 'Separator',
+ xns : rooui.menu
+ },
+ {
+ xtype : 'Item',
+ html: 'Table',
+ listeners : {
+ click : function (_self, e)
+ {
+ var t = table();
+ var nn = t.node.nextSibling || t.node.previousSibling;
+ t.node.parentNode.removeChild(t.node);
+ if (nn) {
+ toolbar.editorcore.selectNode(nn, true);
+ }
+ toolbar.editorcore.onEditorEvent();
+
+ }
+ },
+ xns : rooui.menu
+ }
+ ]
+ }
+ }
+
+ // align... << fixme
+
+ ];
+
+ },
+
- getAutoCreate : function()
+ /**
+ * create a DomHelper friendly object - for use with
+ * Roo.DomHelper.markup / overwrite / etc..
+ * ?? should it be called with option to hide all editing features?
+ */
+ /**
+ * create a DomHelper friendly object - for use with
+ * Roo.DomHelper.markup / overwrite / etc..
+ * ?? should it be called with option to hide all editing features?
+ */
+ toObject : function()
{
- var cfg = {
- tag : 'div',
- cls : 'form-group radio',
- cn : [
- {
- tag : 'label',
- cls : 'box-label',
- html : this.boxLabel
- }
- ]
+
+ var ret = {
+ tag : 'td',
+ contenteditable : 'true', // this stops cell selection from picking the table.
+ 'data-block' : 'Td',
+ valign : this.valign,
+ style : {
+ 'text-align' : this.textAlign,
+ border : 'solid 1px rgb(0, 0, 0)', // ??? hard coded?
+ 'border-collapse' : 'collapse',
+ padding : '6px', // 8 for desktop / 4 for mobile
+ 'vertical-align': this.valign
+ },
+ html : this.html
};
+ if (this.width != '') {
+ ret.width = this.width;
+ ret.style.width = this.width;
+ }
- return cfg;
+
+ if (this.colspan > 1) {
+ ret.colspan = this.colspan ;
+ }
+ if (this.rowspan > 1) {
+ ret.rowspan = this.rowspan ;
+ }
+
+
+
+ return ret;
+
},
- initEvents : function()
+ readElement : function(node)
{
- this.parent().register(this);
+ node = node ? node : this.node ;
+ this.width = node.style.width;
+ this.colspan = Math.max(1,1*node.getAttribute('colspan'));
+ this.rowspan = Math.max(1,1*node.getAttribute('rowspan'));
+ this.html = node.innerHTML;
- this.el.on('click', this.onClick, this);
},
-
- onClick : function(e)
- {
- if(this.parent().fireEvent('click', this.parent(), this, e) !== false){
- this.setChecked(true);
- }
+
+ // the default cell object... at present...
+ emptyCell : function() {
+ return {
+ colspan : 1,
+ rowspan : 1,
+ textAlign : 'left',
+ html : " " // is this going to be editable now?
+ };
+
},
- setChecked : function(state, suppressEvent)
+ removeNode : function()
{
- this.parent().setValue(this.value, suppressEvent);
-
+ return this.node.closest('table');
+
},
- setBoxLabel : function(v)
+ cellData : false,
+
+ colWidths : false,
+
+ toTableArray : function()
{
- this.boxLabel = v;
+ var ret = [];
+ var tab = this.node.closest('tr').closest('table');
+ Array.from(tab.rows).forEach(function(r, ri){
+ ret[ri] = [];
+ });
+ var rn = 0;
+ this.colWidths = [];
+ var all_auto = true;
+ Array.from(tab.rows).forEach(function(r, ri){
+
+ var cn = 0;
+ Array.from(r.cells).forEach(function(ce, ci){
+ var c = {
+ cell : ce,
+ row : rn,
+ col: cn,
+ colspan : ce.colSpan,
+ rowspan : ce.rowSpan
+ };
+ if (ce.isEqualNode(this.node)) {
+ this.cellData = c;
+ }
+ // if we have been filled up by a row?
+ if (typeof(ret[rn][cn]) != 'undefined') {
+ while(typeof(ret[rn][cn]) != 'undefined') {
+ cn++;
+ }
+ c.col = cn;
+ }
+
+ if (typeof(this.colWidths[cn]) == 'undefined') {
+ this.colWidths[cn] = ce.style.width;
+ if (this.colWidths[cn] != '') {
+ all_auto = false;
+ }
+ }
+
+
+ if (c.colspan < 2 && c.rowspan < 2 ) {
+ ret[rn][cn] = c;
+ cn++;
+ return;
+ }
+ for(var j = 0; j < c.rowspan; j++) {
+ if (typeof(ret[rn+j]) == 'undefined') {
+ continue; // we have a problem..
+ }
+ ret[rn+j][cn] = c;
+ for(var i = 0; i < c.colspan; i++) {
+ ret[rn+j][cn+i] = c;
+ }
+ }
+
+ cn += c.colspan;
+ }, this);
+ rn++;
+ }, this);
- if(this.rendered){
- this.el.select('label.box-label',true).first().dom.innerHTML = (v === null || v === undefined ? '' : v);
+ // initalize widths.?
+ // either all widths or no widths..
+ if (all_auto) {
+ this.colWidths[0] = false; // no widths flag.
}
- }
-
-});
-
-
- /*
- * - LGPL
- *
- * Input
- *
- */
-
-/**
- * @class Roo.bootstrap.SecurePass
- * @extends Roo.bootstrap.Input
- * Bootstrap SecurePass class
- *
- *
- * @constructor
- * Create a new SecurePass
- * @param {Object} config The config object
- */
-
-Roo.bootstrap.SecurePass = function (config) {
- // these go here, so the translation tool can replace them..
- this.errors = {
- PwdEmpty: "Please type a password, and then retype it to confirm.",
- PwdShort: "Your password must be at least 6 characters long. Please type a different password.",
- PwdLong: "Your password can't contain more than 16 characters. Please type a different password.",
- PwdBadChar: "The password contains characters that aren't allowed. Please type a different password.",
- IDInPwd: "Your password can't include the part of your ID. Please type a different password.",
- FNInPwd: "Your password can't contain your first name. Please type a different password.",
- LNInPwd: "Your password can't contain your last name. Please type a different password.",
- TooWeak: "Your password is Too Weak."
+
+
+ return ret;
+
},
- this.meterLabel = "Password strength:";
- this.pwdStrengths = ["Too Weak", "Weak", "Medium", "Strong"];
- this.meterClass = [
- "roo-password-meter-tooweak",
- "roo-password-meter-weak",
- "roo-password-meter-medium",
- "roo-password-meter-strong",
- "roo-password-meter-grey"
- ];
- this.errors = {};
- Roo.bootstrap.SecurePass.superclass.constructor.call(this, config);
-}
-
-Roo.extend(Roo.bootstrap.SecurePass, Roo.bootstrap.Input, {
- /**
- * @cfg {String/Object} errors A Error spec, or true for a default spec (defaults to
- * {
- * PwdEmpty: "Please type a password, and then retype it to confirm.",
- * PwdShort: "Your password must be at least 6 characters long. Please type a different password.",
- * PwdLong: "Your password can't contain more than 16 characters. Please type a different password.",
- * PwdBadChar: "The password contains characters that aren't allowed. Please type a different password.",
- * IDInPwd: "Your password can't include the part of your ID. Please type a different password.",
- * FNInPwd: "Your password can't contain your first name. Please type a different password.",
- * LNInPwd: "Your password can't contain your last name. Please type a different password."
- * })
- */
- // private
- meterWidth: 300,
- errorMsg :'',
- errors: false,
- imageRoot: '/',
- /**
- * @cfg {String/Object} Label for the strength meter (defaults to
- * 'Password strength:')
- */
- // private
- meterLabel: '',
- /**
- * @cfg {String/Object} pwdStrengths A pwdStrengths spec, or true for a default spec (defaults to
- * ['Weak', 'Medium', 'Strong'])
- */
- // private
- pwdStrengths: false,
- // private
- strength: 0,
- // private
- _lastPwd: null,
- // private
- kCapitalLetter: 0,
- kSmallLetter: 1,
- kDigit: 2,
- kPunctuation: 3,
- insecure: false,
- // private
- initEvents: function ()
- {
- Roo.bootstrap.SecurePass.superclass.initEvents.call(this);
-
- if (this.el.is('input[type=password]') && Roo.isSafari) {
- this.el.on('keydown', this.SafariOnKeyDown, this);
- }
-
- this.el.on('keyup', this.checkStrength, this, {buffer: 50});
- },
- // private
- onRender: function (ct, position)
+ mergeRight: function()
{
- Roo.bootstrap.SecurePass.superclass.onRender.call(this, ct, position);
- this.wrap = this.el.wrap({cls: 'x-form-field-wrap'});
- this.trigger = this.wrap.createChild({tag: 'div', cls: 'StrengthMeter ' + this.triggerClass});
-
- this.trigger.createChild({
- cn: [
- {
- //id: 'PwdMeter',
- tag: 'div',
- cls: 'roo-password-meter-grey col-xs-12',
- style: {
- //width: 0,
- //width: this.meterWidth + 'px'
- }
- },
- {
- cls: 'roo-password-meter-text'
- }
- ]
- });
-
- if (this.hideTrigger) {
- this.trigger.setDisplayed(false);
- }
- this.setSize(this.width || '', this.height || '');
- },
- // private
- onDestroy: function ()
- {
- if (this.trigger) {
- this.trigger.removeAllListeners();
- this.trigger.remove();
+ // get the contents of the next cell along..
+ var tr = this.node.closest('tr');
+ var i = Array.prototype.indexOf.call(tr.childNodes, this.node);
+ if (i >= tr.childNodes.length - 1) {
+ return; // no cells on right to merge with.
}
- if (this.wrap) {
- this.wrap.remove();
- }
- Roo.bootstrap.TriggerField.superclass.onDestroy.call(this);
- },
- // private
- checkStrength: function ()
- {
- var pwd = this.inputEl().getValue();
- if (pwd == this._lastPwd) {
- return;
+ var table = this.toTableArray();
+
+ if (typeof(table[this.cellData.row][this.cellData.col+this.cellData.colspan]) == 'undefined') {
+ return; // nothing right?
}
-
- var strength;
- if (this.ClientSideStrongPassword(pwd)) {
- strength = 3;
- } else if (this.ClientSideMediumPassword(pwd)) {
- strength = 2;
- } else if (this.ClientSideWeakPassword(pwd)) {
- strength = 1;
- } else {
- strength = 0;
+ var rc = table[this.cellData.row][this.cellData.col+this.cellData.colspan];
+ // right cell - must be same rowspan and on the same row.
+ if (rc.rowspan != this.cellData.rowspan || rc.row != this.cellData.row) {
+ return; // right hand side is not same rowspan.
}
- Roo.log('strength1: ' + strength);
-
- //var pm = this.trigger.child('div/div/div').dom;
- var pm = this.trigger.child('div/div');
- pm.removeClass(this.meterClass);
- pm.addClass(this.meterClass[strength]);
-
-
- var pt = this.trigger.child('/div').child('>*[class=roo-password-meter-text]').dom;
-
- pt.innerHTML = this.meterLabel + ' ' + this.pwdStrengths[strength];
-
- this._lastPwd = pwd;
- },
- reset: function ()
- {
- Roo.bootstrap.SecurePass.superclass.reset.call(this);
-
- this._lastPwd = '';
-
- var pm = this.trigger.child('div/div');
- pm.removeClass(this.meterClass);
- pm.addClass('roo-password-meter-grey');
-
- var pt = this.trigger.child('/div').child('>*[class=roo-password-meter-text]').dom;
- pt.innerHTML = '';
- this.inputEl().dom.type='password';
+ this.node.innerHTML += ' ' + rc.cell.innerHTML;
+ tr.removeChild(rc.cell);
+ this.colspan += rc.colspan;
+ this.node.setAttribute('colspan', this.colspan);
+
},
- // private
- validateValue: function (value)
+
+
+ mergeBelow : function()
{
- if (!Roo.bootstrap.SecurePass.superclass.validateValue.call(this, value)) {
- return false;
- }
- if (value.length == 0) {
- if (this.allowBlank) {
- this.clearInvalid();
- return true;
- }
-
- this.markInvalid(this.errors.PwdEmpty);
- this.errorMsg = this.errors.PwdEmpty;
- return false;
+ var table = this.toTableArray();
+ if (typeof(table[this.cellData.row+this.cellData.rowspan]) == 'undefined') {
+ return; // no row below
}
-
- if(this.insecure){
- return true;
+ if (typeof(table[this.cellData.row+this.cellData.rowspan][this.cellData.col]) == 'undefined') {
+ return; // nothing right?
}
+ var rc = table[this.cellData.row+this.cellData.rowspan][this.cellData.col];
- if (!value.match(/[\x21-\x7e]+/)) {
- this.markInvalid(this.errors.PwdBadChar);
- this.errorMsg = this.errors.PwdBadChar;
- return false;
- }
- if (value.length < 6) {
- this.markInvalid(this.errors.PwdShort);
- this.errorMsg = this.errors.PwdShort;
- return false;
- }
- if (value.length > 16) {
- this.markInvalid(this.errors.PwdLong);
- this.errorMsg = this.errors.PwdLong;
- return false;
+ if (rc.colspan != this.cellData.colspan || rc.col != this.cellData.col) {
+ return; // right hand side is not same rowspan.
}
- var strength;
- if (this.ClientSideStrongPassword(value)) {
- strength = 3;
- } else if (this.ClientSideMediumPassword(value)) {
- strength = 2;
- } else if (this.ClientSideWeakPassword(value)) {
- strength = 1;
- } else {
- strength = 0;
+ this.node.innerHTML = this.node.innerHTML + rc.cell.innerHTML ;
+ rc.cell.parentNode.removeChild(rc.cell);
+ this.rowspan += rc.rowspan;
+ this.node.setAttribute('rowspan', this.rowspan);
+ },
+
+ split: function()
+ {
+ if (this.node.rowSpan < 2 && this.node.colSpan < 2) {
+ return;
}
-
+ var table = this.toTableArray();
+ var cd = this.cellData;
+ this.rowspan = 1;
+ this.colspan = 1;
- if (strength < 2) {
- //this.markInvalid(this.errors.TooWeak);
- this.errorMsg = this.errors.TooWeak;
- //return false;
+ for(var r = cd.row; r < cd.row + cd.rowspan; r++) {
+
+
+
+ for(var c = cd.col; c < cd.col + cd.colspan; c++) {
+ if (r == cd.row && c == cd.col) {
+ this.node.removeAttribute('rowspan');
+ this.node.removeAttribute('colspan');
+ continue;
+ }
+
+ var ntd = this.node.cloneNode(); // which col/row should be 0..
+ ntd.removeAttribute('id'); //
+ //ntd.style.width = '';
+ ntd.innerHTML = '';
+ table[r][c] = { cell : ntd, col : c, row: r , colspan : 1 , rowspan : 1 };
+ }
+
}
+ this.redrawAllCells(table);
+
- console.log('strength2: ' + strength);
-
- //var pm = this.trigger.child('div/div/div').dom;
-
- var pm = this.trigger.child('div/div');
- pm.removeClass(this.meterClass);
- pm.addClass(this.meterClass[strength]);
-
- var pt = this.trigger.child('/div').child('>*[class=roo-password-meter-text]').dom;
-
- pt.innerHTML = this.meterLabel + ' ' + this.pwdStrengths[strength];
-
- this.errorMsg = '';
- return true;
- },
- // private
- CharacterSetChecks: function (type)
- {
- this.type = type;
- this.fResult = false;
},
- // private
- isctype: function (character, type)
+
+
+
+ redrawAllCells: function(table)
{
- switch (type) {
- case this.kCapitalLetter:
- if (character >= 'A' && character <= 'Z') {
- return true;
- }
- break;
-
- case this.kSmallLetter:
- if (character >= 'a' && character <= 'z') {
- return true;
- }
- break;
+
+
+ var tab = this.node.closest('tr').closest('table');
+ var ctr = tab.rows[0].parentNode;
+ Array.from(tab.rows).forEach(function(r, ri){
- case this.kDigit:
- if (character >= '0' && character <= '9') {
- return true;
- }
- break;
+ Array.from(r.cells).forEach(function(ce, ci){
+ ce.parentNode.removeChild(ce);
+ });
+ r.parentNode.removeChild(r);
+ });
+ for(var r = 0 ; r < table.length; r++) {
+ var re = tab.rows[r];
- case this.kPunctuation:
- if ('!@#$%^&*()_+-=\'";:[{]}|.>,</?`~'.indexOf(character) >= 0) {
- return true;
+ var re = tab.ownerDocument.createElement('tr');
+ ctr.appendChild(re);
+ for(var c = 0 ; c < table[r].length; c++) {
+ if (table[r][c].cell === false) {
+ continue;
}
- break;
-
- default:
- return false;
+
+ re.appendChild(table[r][c].cell);
+
+ table[r][c].cell = false;
+ }
}
-
+
},
- // private
- IsLongEnough: function (pwd, size)
+ updateWidths : function(table)
{
- return !(pwd == null || isNaN(size) || pwd.length < size);
+ for(var r = 0 ; r < table.length; r++) {
+
+ for(var c = 0 ; c < table[r].length; c++) {
+ if (table[r][c].cell === false) {
+ continue;
+ }
+
+ if (this.colWidths[0] != false && table[r][c].colspan < 2) {
+ var el = Roo.htmleditor.Block.factory(table[r][c].cell);
+ el.width = Math.floor(this.colWidths[c]) +'%';
+ el.updateElement(el.node);
+ }
+ table[r][c].cell = false; // done
+ }
+ }
},
- // private
- SpansEnoughCharacterSets: function (word, nb)
+ normalizeWidths : function(table)
{
- if (!this.IsLongEnough(word, nb))
- {
- return false;
+
+ if (this.colWidths[0] === false) {
+ var nw = 100.0 / this.colWidths.length;
+ this.colWidths.forEach(function(w,i) {
+ this.colWidths[i] = nw;
+ },this);
+ return;
}
-
- var characterSetChecks = new Array(
- new this.CharacterSetChecks(this.kCapitalLetter), new this.CharacterSetChecks(this.kSmallLetter),
- new this.CharacterSetChecks(this.kDigit), new this.CharacterSetChecks(this.kPunctuation)
- );
+
+ var t = 0, missing = [];
- for (var index = 0; index < word.length; ++index) {
- for (var nCharSet = 0; nCharSet < characterSetChecks.length; ++nCharSet) {
- if (!characterSetChecks[nCharSet].fResult && this.isctype(word.charAt(index), characterSetChecks[nCharSet].type)) {
- characterSetChecks[nCharSet].fResult = true;
- break;
- }
- }
- }
-
- var nCharSets = 0;
- for (var nCharSet = 0; nCharSet < characterSetChecks.length; ++nCharSet) {
- if (characterSetChecks[nCharSet].fResult) {
- ++nCharSets;
+ this.colWidths.forEach(function(w,i) {
+ //if you mix % and
+ this.colWidths[i] = this.colWidths[i] == '' ? 0 : (this.colWidths[i]+'').replace(/[^0-9]+/g,'')*1;
+ var add = this.colWidths[i];
+ if (add > 0) {
+ t+=add;
+ return;
}
+ missing.push(i);
+
+
+ },this);
+ var nc = this.colWidths.length;
+ if (missing.length) {
+ var mult = (nc - missing.length) / (1.0 * nc);
+ var t = mult * t;
+ var ew = (100 -t) / (1.0 * missing.length);
+ this.colWidths.forEach(function(w,i) {
+ if (w > 0) {
+ this.colWidths[i] = w * mult;
+ return;
+ }
+
+ this.colWidths[i] = ew;
+ }, this);
+ // have to make up numbers..
+
}
-
- if (nCharSets < nb) {
- return false;
+ // now we should have all the widths..
+
+
+ },
+
+ shrinkColumn : function()
+ {
+ var table = this.toTableArray();
+ this.normalizeWidths(table);
+ var col = this.cellData.col;
+ var nw = this.colWidths[col] * 0.8;
+ if (nw < 5) {
+ return;
}
- return true;
+ var otherAdd = (this.colWidths[col] * 0.2) / (this.colWidths.length -1);
+ this.colWidths.forEach(function(w,i) {
+ if (i == col) {
+ this.colWidths[i] = nw;
+ return;
+ }
+ this.colWidths[i] += otherAdd
+ }, this);
+ this.updateWidths(table);
+
},
- // private
- ClientSideStrongPassword: function (pwd)
+ growColumn : function()
{
- return this.IsLongEnough(pwd, 8) && this.SpansEnoughCharacterSets(pwd, 3);
+ var table = this.toTableArray();
+ this.normalizeWidths(table);
+ var col = this.cellData.col;
+ var nw = this.colWidths[col] * 1.2;
+ if (nw > 90) {
+ return;
+ }
+ var otherSub = (this.colWidths[col] * 0.2) / (this.colWidths.length -1);
+ this.colWidths.forEach(function(w,i) {
+ if (i == col) {
+ this.colWidths[i] = nw;
+ return;
+ }
+ this.colWidths[i] -= otherSub
+ }, this);
+ this.updateWidths(table);
+
},
- // private
- ClientSideMediumPassword: function (pwd)
+ deleteRow : function()
{
- return this.IsLongEnough(pwd, 7) && this.SpansEnoughCharacterSets(pwd, 2);
+ // delete this rows 'tr'
+ // if any of the cells in this row have a rowspan > 1 && row!= this row..
+ // then reduce the rowspan.
+ var table = this.toTableArray();
+ // this.cellData.row;
+ for (var i =0;i< table[this.cellData.row].length ; i++) {
+ var c = table[this.cellData.row][i];
+ if (c.row != this.cellData.row) {
+
+ c.rowspan--;
+ c.cell.setAttribute('rowspan', c.rowspan);
+ continue;
+ }
+ if (c.rowspan > 1) {
+ c.rowspan--;
+ c.cell.setAttribute('rowspan', c.rowspan);
+ }
+ }
+ table.splice(this.cellData.row,1);
+ this.redrawAllCells(table);
+
},
- // private
- ClientSideWeakPassword: function (pwd)
+ deleteColumn : function()
{
- return this.IsLongEnough(pwd, 6) || !this.IsLongEnough(pwd, 0);
+ var table = this.toTableArray();
+
+ for (var i =0;i< table.length ; i++) {
+ var c = table[i][this.cellData.col];
+ if (c.col != this.cellData.col) {
+ table[i][this.cellData.col].colspan--;
+ } else if (c.colspan > 1) {
+ c.colspan--;
+ c.cell.setAttribute('colspan', c.colspan);
+ }
+ table[i].splice(this.cellData.col,1);
+ }
+
+ this.redrawAllCells(table);
}
-
-})//<script type="text/javascript">
+
+
+
+
+})
+
+//<script type="text/javascript">
/*
* Based Ext JS Library 1.1.1
* Fires when on any editor (mouse up/down cursor movement etc.) - used for toolbar hooks.
* @param {Roo.HtmlEditorCore} this
*/
- editorevent: true
+ editorevent: true
+
});
* @cfg {Number} width (in pixels)
*/
width: 500,
+ /**
+ * @cfg {boolean} autoClean - default true - loading and saving will remove quite a bit of formating,
+ * if you are doing an email editor, this probably needs disabling, it's designed
+ */
+ autoClean: true,
+ /**
+ * @cfg {boolean} enableBlocks - default true - if the block editor (table and figure should be enabled)
+ */
+ enableBlocks : true,
/**
* @cfg {Array} stylesheets url of stylesheets. set to [] to disable stylesheets.
*
*/
stylesheets: false,
+ /**
+ * @cfg {String} language default en - language of text (usefull for rtl languages)
+ *
+ */
+ language: 'en',
+ /**
+ * @cfg {boolean} allowComments - default false - allow comments in HTML source
+ * - by default they are stripped - if you are editing email you may need this.
+ */
+ allowComments: false,
// id of frame..
frameId: false,
bodyCls : '',
+
+ undoManager : false,
/**
* Protected method that will not generally be called directly. It
* is called when the editor initializes the iframe with HTML contents. Override this method if you
'body{border:0;margin:0;padding:3px;height:98%;cursor:text;}' +
'</style>';
} else {
- for (var i in this.stylesheets) {
+ for (var i in this.stylesheets) {
+ if (typeof(this.stylesheets[i]) != 'string') {
+ continue;
+ }
st += '<link rel="stylesheet" href="' + this.stylesheets[i] +'" type="text/css">';
}
st += '<style type="text/css">' +
'IMG { cursor: pointer } ' +
'</style>';
-
- var cls = 'roo-htmleditor-body';
+
+ st += '<meta name="google" content="notranslate">';
+
+ var cls = 'notranslate roo-htmleditor-body';
if(this.bodyCls.length){
cls += ' ' + this.bodyCls;
}
- return '<html><head>' + st +
+ return '<html class="notranslate" translate="no"><head>' + st +
//<style type="text/css">' +
//'body{border:0;margin:0;padding:3px;height:98%;cursor:text;}' +
//'</style>' +
this.iframe = iframe.dom;
- this.assignDocWin();
+ this.assignDocWin();
this.doc.designMode = 'on';
if(this.doc.body || this.doc.readyState == 'complete'){
try {
this.doc.designMode="on";
+
} catch (e) {
return;
}
if(this.sourceEditMode){
- Roo.get(this.iframe).addClass(['x-hidden','hide']); //FIXME - what's the BS styles for these
+ Roo.get(this.iframe).addClass(['x-hidden','hide', 'd-none']); //FIXME - what's the BS styles for these
}else{
- Roo.get(this.iframe).removeClass(['x-hidden','hide']);
+ Roo.get(this.iframe).removeClass(['x-hidden','hide', 'd-none']);
//this.iframe.className = '';
this.deferFocus();
}
* @param {String} html The HTML to be cleaned
* return {String} The cleaned HTML
*/
- cleanHtml : function(html){
+ cleanHtml : function(html)
+ {
html = String(html);
if(html.length > 5){
if(Roo.isSafari){ // strip safari nonsense
* Protected method that will not generally be called directly. Syncs the contents
* of the editor iframe with the textarea.
*/
- syncValue : function(){
+ syncValue : function()
+ {
+ //Roo.log("HtmlEditorCore:syncValue (EDITOR->TEXT)");
if(this.initialized){
+
+ if (this.undoManager) {
+ this.undoManager.addEvent();
+ }
+
+
var bd = (this.doc.body || this.doc.documentElement);
- //this.cleanUpPaste(); -- this is done else where and causes havoc..
- var html = bd.innerHTML;
+
+
+ var sel = this.win.getSelection();
+
+ var div = document.createElement('div');
+ div.innerHTML = bd.innerHTML;
+ var gtx = div.getElementsByClassName('gtx-trans-icon'); // google translate - really annoying and difficult to get rid of.
+ if (gtx.length > 0) {
+ var rm = gtx.item(0).parentNode;
+ rm.parentNode.removeChild(rm);
+ }
+
+
+ if (this.enableBlocks) {
+ new Roo.htmleditor.FilterBlock({ node : div });
+ }
+ //?? tidy?
+ var tidy = new Roo.htmleditor.TidySerializer({
+ inner: true
+ });
+ var html = tidy.serialize(div);
+
+
if(Roo.isSafari){
var bs = bd.getAttribute('style'); // Safari puts text-align styles on the body element!
var m = bs ? bs.match(/text-align:(.*?);/i) : false;
},
/**
+ * TEXTAREA -> EDITABLE
* Protected method that will not generally be called directly. Pushes the value of the textarea
* into the iframe editor.
*/
- pushValue : function(){
+ pushValue : function()
+ {
+ //Roo.log("HtmlEditorCore:pushValue (TEXT->EDITOR)");
if(this.initialized){
var v = this.el.dom.value.trim();
-// if(v.length < 1){
-// v = ' ';
-// }
if(this.owner.fireEvent('beforepush', this, v) !== false){
var d = (this.doc.body || this.doc.documentElement);
d.innerHTML = v;
- this.cleanUpPaste();
+
this.el.dom.value = d.innerHTML;
this.owner.fireEvent('push', this, v);
}
+ if (this.autoClean) {
+ new Roo.htmleditor.FilterParagraph({node : this.doc.body}); // paragraphs
+ new Roo.htmleditor.FilterSpan({node : this.doc.body}); // empty spans
+ }
+ if (this.enableBlocks) {
+ Roo.htmleditor.Block.initAll(this.doc.body);
+ }
+
+ this.updateLanguage();
+
+ var lc = this.doc.body.lastChild;
+ if (lc && lc.nodeType == 1 && lc.getAttribute("contenteditable") == "false") {
+ // add an extra line at the end.
+ this.doc.body.appendChild(this.doc.createElement('br'));
+ }
+
+
}
},
//var ss = this.el.getStyles( 'background-image', 'background-repeat');
//ss['background-attachment'] = 'fixed'; // w3c
dbody.bgProperties = 'fixed'; // ie
+ dbody.setAttribute("translate", "no");
+
//Roo.DomHelper.applyStyles(dbody, ss);
Roo.EventManager.on(this.doc, {
- //'mousedown': this.onEditorEvent,
+
'mouseup': this.onEditorEvent,
'dblclick': this.onEditorEvent,
'click': this.onEditorEvent,
'keyup': this.onEditorEvent,
+
buffer:100,
scope: this
});
+ Roo.EventManager.on(this.doc, {
+ 'paste': this.onPasteEvent,
+ scope : this
+ });
if(Roo.isGecko){
Roo.EventManager.on(this.doc, 'keypress', this.mozKeyPress, this);
}
+ //??? needed???
if(Roo.isIE || Roo.isSafari || Roo.isOpera){
Roo.EventManager.on(this.doc, 'keydown', this.fixKeys, this);
}
this.initialized = true;
+
+ // initialize special key events - enter
+ new Roo.htmleditor.KeyEnter({core : this});
+
+
+
this.owner.fireEvent('initialize', this);
this.pushValue();
},
-
+ // this is to prevent a href clicks resulting in a redirect?
+
+ onPasteEvent : function(e,v)
+ {
+ // I think we better assume paste is going to be a dirty load of rubish from word..
+
+ // even pasting into a 'email version' of this widget will have to clean up that mess.
+ var cd = (e.browserEvent.clipboardData || window.clipboardData);
+
+ // check what type of paste - if it's an image, then handle it differently.
+ if (cd.files && cd.files.length > 0) {
+ // pasting images?
+ var urlAPI = (window.createObjectURL && window) ||
+ (window.URL && URL.revokeObjectURL && URL) ||
+ (window.webkitURL && webkitURL);
+
+ var url = urlAPI.createObjectURL( cd.files[0]);
+ this.insertAtCursor('<img src=" + url + ">');
+ return false;
+ }
+ if (cd.types.indexOf('text/html') < 0 ) {
+ return false;
+ }
+ var images = [];
+ var html = cd.getData('text/html'); // clipboard event
+ if (cd.types.indexOf('text/rtf') > -1) {
+ var parser = new Roo.rtf.Parser(cd.getData('text/rtf'));
+ images = parser.doc ? parser.doc.getElementsByType('pict') : [];
+ }
+ //Roo.log(images);
+ //Roo.log(imgs);
+ // fixme..
+ images = images.filter(function(g) { return !g.path.match(/^rtf\/(head|pgdsctbl|listtable|footerf)/); }) // ignore headers/footers etc.
+ .map(function(g) { return g.toDataURL(); })
+ .filter(function(g) { return g != 'about:blank'; });
+
+
+ html = this.cleanWordChars(html);
+
+ var d = (new DOMParser().parseFromString(html, 'text/html')).body;
+
+
+ var sn = this.getParentElement();
+ // check if d contains a table, and prevent nesting??
+ //Roo.log(d.getElementsByTagName('table'));
+ //Roo.log(sn);
+ //Roo.log(sn.closest('table'));
+ if (d.getElementsByTagName('table').length && sn && sn.closest('table')) {
+ e.preventDefault();
+ this.insertAtCursor("You can not nest tables");
+ //Roo.log("prevent?"); // fixme -
+ return false;
+ }
+
+ if (images.length > 0) {
+ Roo.each(d.getElementsByTagName('img'), function(img, i) {
+ img.setAttribute('src', images[i]);
+ });
+ }
+ if (this.autoClean) {
+ new Roo.htmleditor.FilterStyleToTag({ node : d });
+ new Roo.htmleditor.FilterAttributes({
+ node : d,
+ attrib_white : ['href', 'src', 'name', 'align', 'colspan', 'rowspan', 'data-display', 'data-width'],
+ attrib_clean : ['href', 'src' ]
+ });
+ new Roo.htmleditor.FilterBlack({ node : d, tag : this.black});
+ // should be fonts..
+ new Roo.htmleditor.FilterKeepChildren({node : d, tag : [ 'FONT', 'O:P' ]} );
+ new Roo.htmleditor.FilterParagraph({ node : d });
+ new Roo.htmleditor.FilterSpan({ node : d });
+ new Roo.htmleditor.FilterLongBr({ node : d });
+ new Roo.htmleditor.FilterComment({ node : d });
+
+
+ }
+ if (this.enableBlocks) {
+
+ Array.from(d.getElementsByTagName('img')).forEach(function(img) {
+ if (img.closest('figure')) { // assume!! that it's aready
+ return;
+ }
+ var fig = new Roo.htmleditor.BlockFigure({
+ image_src : img.src
+ });
+ fig.updateElement(img); // replace it..
+
+ });
+ }
+
+
+ this.insertAtCursor(d.innerHTML.replace(/ /g,' '));
+ if (this.enableBlocks) {
+ Roo.htmleditor.Block.initAll(this.doc.body);
+ }
+
+
+ e.preventDefault();
+ return false;
+ // default behaveiour should be our local cleanup paste? (optional?)
+ // for simple editor - we want to hammer the paste and get rid of everything... - so over-rideable..
+ //this.owner.fireEvent('paste', e, v);
+ },
// private
onDestroy : function(){
onFirstFocus : function(){
this.assignDocWin();
-
+ this.undoManager = new Roo.lib.UndoManager(100,(this.doc.body || this.doc.documentElement));
this.activated = true;
onEditorEvent : function(e)
{
- this.owner.fireEvent('editorevent', this, e);
+
+
+ if (e && (e.ctrlKey || e.metaKey) && e.keyCode === 90) {
+ return; // we do not handle this.. (undo manager does..)
+ }
+ // in theory this detects if the last element is not a br, then we try and do that.
+ // its so clicking in space at bottom triggers adding a br and moving the cursor.
+ if (e &&
+ e.target.nodeName == 'BODY' &&
+ e.type == "mouseup" &&
+ this.doc.body.lastChild
+ ) {
+ var lc = this.doc.body.lastChild;
+ // gtx-trans is google translate plugin adding crap.
+ while ((lc.nodeType == 3 && lc.nodeValue == '') || lc.id == 'gtx-trans') {
+ lc = lc.previousSibling;
+ }
+ if (lc.nodeType == 1 && lc.nodeName != 'BR') {
+ // if last element is <BR> - then dont do anything.
+
+ var ns = this.doc.createElement('br');
+ this.doc.body.appendChild(ns);
+ range = this.doc.createRange();
+ range.setStartAfter(ns);
+ range.collapse(true);
+ var sel = this.win.getSelection();
+ sel.removeAllRanges();
+ sel.addRange(range);
+ }
+ }
+
+
+
+ this.fireEditorEvent(e);
// this.updateToolbar();
this.syncValue(); //we can not sync so often.. sync cleans, so this breaks stuff
},
+
+ fireEditorEvent: function(e)
+ {
+ this.owner.fireEvent('editorevent', this, e);
+ },
insertTag : function(tg)
{
}
this.execCmd("formatblock", tg);
-
+ this.undoManager.addEvent();
},
insertText : function(txt)
//alert(Sender.getAttribute('label'));
range.insertNode(this.doc.createTextNode(txt));
+ this.undoManager.addEvent();
} ,
* @param {String} cmd The Midas command
* @param {String/Boolean} value (optional) The value to pass to the command (defaults to null)
*/
- relayCmd : function(cmd, value){
+ relayCmd : function(cmd, value)
+ {
+
+ switch (cmd) {
+ case 'justifyleft':
+ case 'justifyright':
+ case 'justifycenter':
+ // if we are in a cell, then we will adjust the
+ var n = this.getParentElement();
+ var td = n.closest('td');
+ if (td) {
+ var bl = Roo.htmleditor.Block.factory(td);
+ bl.textAlign = cmd.replace('justify','');
+ bl.updateElement();
+ this.owner.fireEvent('editorevent', this);
+ return;
+ }
+ this.execCmd('styleWithCSS', true); //
+ break;
+ case 'bold':
+ case 'italic':
+ // if there is no selection, then we insert, and set the curson inside it..
+ this.execCmd('styleWithCSS', false);
+ break;
+
+
+ default:
+ break;
+ }
+
+
this.win.focus();
this.execCmd(cmd, value);
this.owner.fireEvent('editorevent', this);
if(!this.activated){
return;
}
- /*
- if(Roo.isIE){
- this.win.focus();
- var r = this.doc.selection.createRange();
- if(r){
- r.collapse(true);
- r.pasteHTML(text);
- this.syncValue();
- this.deferFocus();
-
- }
- return;
- }
- */
+
if(Roo.isGecko || Roo.isOpera || Roo.isSafari){
this.win.focus();
var win = this.win;
if (win.getSelection && win.getSelection().getRangeAt) {
+
+ // delete the existing?
+
+ this.createRange(this.getSelection()).deleteContents();
range = win.getSelection().getRangeAt(0);
node = typeof(text) == 'string' ? range.createContextualFragment(text) : text;
range.insertNode(node);
+ range = range.cloneRange();
+ range.collapse(false);
+
+ win.getSelection().removeAllRanges();
+ win.getSelection().addRange(range);
+
+
+
} else if (win.document.selection && win.document.selection.createRange) {
// no firefox support
var txt = typeof(text) == 'string' ? text : text.outerHTML;
win.document.selection.createRange().pasteHTML(txt);
+
} else {
// no firefox support
var txt = typeof(text) == 'string' ? text : text.outerHTML;
this.execCmd('InsertHTML', txt);
}
-
this.syncValue();
this.deferFocus();
cmd = 'underline';
break;
- case 'v':
- this.cleanUpPaste.defer(100, this);
- return;
+ //case 'v':
+ // this.cleanUpPaste.defer(100, this);
+ // return;
}
if(cmd){
- this.win.focus();
- this.execCmd(cmd);
- this.deferFocus();
+
+ this.relayCmd(cmd);
+ //this.win.focus();
+ //this.execCmd(cmd);
+ //this.deferFocus();
e.preventDefault();
}
// private
fixKeys : function(){ // load time branching for fastest keydown performance
+
+
if(Roo.isIE){
return function(e){
var k = e.getKey(), r;
}
return;
}
-
+ /// this is handled by Roo.htmleditor.KeyEnter
+ /*
if(k == e.ENTER){
r = this.doc.selection.createRange();
if(r){
var target = r.parentElement();
if(!target || target.tagName.toLowerCase() != 'li'){
e.stopEvent();
- r.pasteHTML('<br />');
+ r.pasteHTML('<br/>');
r.collapse(false);
r.select();
}
}
}
- if (String.fromCharCode(k).toLowerCase() == 'v') { // paste
- this.cleanUpPaste.defer(100, this);
- return;
- }
+ */
+ //if (String.fromCharCode(k).toLowerCase() == 'v') { // paste
+ // this.cleanUpPaste.defer(100, this);
+ // return;
+ //}
};
this.execCmd('InsertHTML','    ');
this.deferFocus();
}
- if (String.fromCharCode(k).toLowerCase() == 'v') { // paste
- this.cleanUpPaste.defer(100, this);
- return;
- }
+
+ //if (String.fromCharCode(k).toLowerCase() == 'v') { // paste
+ // this.cleanUpPaste.defer(100, this);
+ // return;
+ //}
};
}else if(Roo.isSafari){
this.deferFocus();
return;
}
- if (String.fromCharCode(k).toLowerCase() == 'v') { // paste
- this.cleanUpPaste.defer(100, this);
- return;
- }
+ this.mozKeyPress(e);
+
+ //if (String.fromCharCode(k).toLowerCase() == 'v') { // paste
+ // this.cleanUpPaste.defer(100, this);
+ // return;
+ // }
};
}
getSelection : function()
{
this.assignDocWin();
- return Roo.isIE ? this.doc.selection : this.win.getSelection();
+ return Roo.lib.Selection.wrap(Roo.isIE ? this.doc.selection : this.win.getSelection(), this.doc);
+ },
+ /**
+ * Select a dom node
+ * @param {DomElement} node the node to select
+ */
+ selectNode : function(node, collapse)
+ {
+ var nodeRange = node.ownerDocument.createRange();
+ try {
+ nodeRange.selectNode(node);
+ } catch (e) {
+ nodeRange.selectNodeContents(node);
+ }
+ if (collapse === true) {
+ nodeRange.collapse(true);
+ }
+ //
+ var s = this.win.getSelection();
+ s.removeAllRanges();
+ s.addRange(nodeRange);
},
getSelectedNode: function()
// should we cache this!!!!
-
-
+
var range = this.createRange(this.getSelection()).cloneRange();
return nodes[0];
},
+
+
createRange: function(sel)
{
// this has strange effects when using with
// fully contined.
return 3;
},
-
- // private? - in a new class?
- cleanUpPaste : function()
- {
- // cleans up the whole document..
- Roo.log('cleanuppaste');
-
- this.cleanUpChildren(this.doc.body);
- var clean = this.cleanWordChars(this.doc.body.innerHTML);
- if (clean != this.doc.body.innerHTML) {
- this.doc.body.innerHTML = clean;
- }
-
- },
-
+
cleanWordChars : function(input) {// change the chars to hex code
- var he = Roo.HtmlEditorCore;
+ var swapCodes = [
+ [ 8211, "–" ],
+ [ 8212, "—" ],
+ [ 8216, "'" ],
+ [ 8217, "'" ],
+ [ 8220, '"' ],
+ [ 8221, '"' ],
+ [ 8226, "*" ],
+ [ 8230, "..." ]
+ ];
var output = input;
- Roo.each(he.swapCodes, function(sw) {
+ Roo.each(swapCodes, function(sw) {
var swapper = new RegExp("\\u" + sw[0].toString(16), "g"); // hex codes
output = output.replace(swapper, sw[1]);
return output;
},
-
- cleanUpChildren : function (n)
- {
- if (!n.childNodes.length) {
- return;
- }
- for (var i = n.childNodes.length-1; i > -1 ; i--) {
- this.cleanUpChild(n.childNodes[i]);
- }
- },
-
+
cleanUpChild : function (node)
{
- var ed = this;
- //console.log(node);
- if (node.nodeName == "#text") {
- // clean up silly Windows -- stuff?
- return;
- }
- if (node.nodeName == "#comment") {
- node.parentNode.removeChild(node);
- // clean up silly Windows -- stuff?
- return;
- }
- var lcname = node.tagName.toLowerCase();
- // we ignore whitelists... ?? = not really the way to go, but we probably have not got a full
- // whitelist of tags..
-
- if (this.black.indexOf(lcname) > -1 && this.clearUp ) {
- // remove node.
- node.parentNode.removeChild(node);
- return;
-
- }
-
- var remove_keep_children= Roo.HtmlEditorCore.remove.indexOf(node.tagName.toLowerCase()) > -1;
-
- // spans with no attributes - just remove them..
- if ((!node.attributes || !node.attributes.length) && lcname == 'span') {
- remove_keep_children = true;
- }
-
- // remove <a name=....> as rendering on yahoo mailer is borked with this.
- // this will have to be flaged elsewhere - perhaps ablack=name... on the mailer..
-
- //if (node.tagName.toLowerCase() == 'a' && !node.hasAttribute('href')) {
- // remove_keep_children = true;
- //}
-
- if (remove_keep_children) {
- this.cleanUpChildren(node);
- // inserts everything just before this node...
- while (node.childNodes.length) {
- var cn = node.childNodes[0];
- node.removeChild(cn);
- node.parentNode.insertBefore(cn, node);
- }
- node.parentNode.removeChild(node);
- return;
- }
-
- if (!node.attributes || !node.attributes.length) {
-
-
-
-
- this.cleanUpChildren(node);
- return;
- }
-
- function cleanAttr(n,v)
- {
-
- if (v.match(/^\./) || v.match(/^\//)) {
- return;
- }
- if (v.match(/^(http|https):\/\//) || v.match(/^mailto:/) || v.match(/^ftp:/)) {
- return;
- }
- if (v.match(/^#/)) {
- return;
- }
- if (v.match(/^\{/)) { // allow template editing.
- return;
- }
-// Roo.log("(REMOVE TAG)"+ node.tagName +'.' + n + '=' + v);
- node.removeAttribute(n);
-
- }
-
- var cwhite = this.cwhite;
- var cblack = this.cblack;
-
- function cleanStyle(n,v)
- {
- if (v.match(/expression/)) { //XSS?? should we even bother..
- node.removeAttribute(n);
- return;
- }
-
- var parts = v.split(/;/);
- var clean = [];
-
- Roo.each(parts, function(p) {
- p = p.replace(/^\s+/g,'').replace(/\s+$/g,'');
- if (!p.length) {
- return true;
- }
- var l = p.split(':').shift().replace(/\s+/g,'');
- l = l.replace(/^\s+/g,'').replace(/\s+$/g,'');
-
- if ( cwhite.length && cblack.indexOf(l) > -1) {
-// Roo.log('(REMOVE CSS)' + node.tagName +'.' + n + ':'+l + '=' + v);
- //node.removeAttribute(n);
- return true;
- }
- //Roo.log()
- // only allow 'c whitelisted system attributes'
- if ( cwhite.length && cwhite.indexOf(l) < 0) {
-// Roo.log('(REMOVE CSS)' + node.tagName +'.' + n + ':'+l + '=' + v);
- //node.removeAttribute(n);
- return true;
- }
-
-
-
-
- clean.push(p);
- return true;
- });
- if (clean.length) {
- node.setAttribute(n, clean.join(';'));
- } else {
- node.removeAttribute(n);
- }
-
- }
-
-
- for (var i = node.attributes.length-1; i > -1 ; i--) {
- var a = node.attributes[i];
- //console.log(a);
-
- if (a.name.toLowerCase().substr(0,2)=='on') {
- node.removeAttribute(a.name);
- continue;
- }
- if (Roo.HtmlEditorCore.ablack.indexOf(a.name.toLowerCase()) > -1) {
- node.removeAttribute(a.name);
- continue;
- }
- if (Roo.HtmlEditorCore.aclean.indexOf(a.name.toLowerCase()) > -1) {
- cleanAttr(a.name,a.value); // fixme..
- continue;
- }
- if (a.name == 'style') {
- cleanStyle(a.name,a.value);
- continue;
- }
- /// clean up MS crap..
- // tecnically this should be a list of valid class'es..
-
-
- if (a.name == 'class') {
- if (a.value.match(/^Mso/)) {
- node.removeAttribute('class');
- }
-
- if (a.value.match(/^body$/)) {
- node.removeAttribute('class');
- }
- continue;
- }
-
- // style cleanup!?
- // class cleanup?
-
- }
-
-
- this.cleanUpChildren(node);
+ new Roo.htmleditor.FilterComment({node : node});
+ new Roo.htmleditor.FilterAttributes({
+ node : node,
+ attrib_black : this.ablack,
+ attrib_clean : this.aclean,
+ style_white : this.cwhite,
+ style_black : this.cblack
+ });
+ new Roo.htmleditor.FilterBlack({ node : node, tag : this.black});
+ new Roo.htmleditor.FilterKeepChildren({node : node, tag : this.tag_remove} );
+
},
/**
* Clean up MS wordisms...
+ * @deprecated - use filter directly
*/
cleanWord : function(node)
{
- if (!node) {
- this.cleanWord(this.doc.body);
- return;
- }
-
- if(
- node.nodeName == 'SPAN' &&
- !node.hasAttributes() &&
- node.childNodes.length == 1 &&
- node.firstChild.nodeName == "#text"
- ) {
- var textNode = node.firstChild;
- node.removeChild(textNode);
- if (node.getAttribute('lang') != 'zh-CN') { // do not space pad on chinese characters..
- node.parentNode.insertBefore(node.ownerDocument.createTextNode(" "), node);
- }
- node.parentNode.insertBefore(textNode, node);
- if (node.getAttribute('lang') != 'zh-CN') { // do not space pad on chinese characters..
- node.parentNode.insertBefore(node.ownerDocument.createTextNode(" ") , node);
- }
- node.parentNode.removeChild(node);
- }
-
- if (node.nodeName == "#text") {
- // clean up silly Windows -- stuff?
- return;
- }
- if (node.nodeName == "#comment") {
- node.parentNode.removeChild(node);
- // clean up silly Windows -- stuff?
- return;
- }
-
- if (node.tagName.toLowerCase().match(/^(style|script|applet|embed|noframes|noscript)$/)) {
- node.parentNode.removeChild(node);
- return;
- }
- //Roo.log(node.tagName);
- // remove - but keep children..
- if (node.tagName.toLowerCase().match(/^(meta|link|\\?xml:|st1:|o:|v:|font)/)) {
- //Roo.log('-- removed');
- while (node.childNodes.length) {
- var cn = node.childNodes[0];
- node.removeChild(cn);
- node.parentNode.insertBefore(cn, node);
- // move node to parent - and clean it..
- this.cleanWord(cn);
- }
- node.parentNode.removeChild(node);
- /// no need to iterate chidlren = it's got none..
- //this.iterateChildren(node, this.cleanWord);
- return;
- }
- // clean styles
- if (node.className.length) {
-
- var cn = node.className.split(/\W+/);
- var cna = [];
- Roo.each(cn, function(cls) {
- if (cls.match(/Mso[a-zA-Z]+/)) {
- return;
- }
- cna.push(cls);
- });
- node.className = cna.length ? cna.join(' ') : '';
- if (!cna.length) {
- node.removeAttribute("class");
- }
- }
-
- if (node.hasAttribute("lang")) {
- node.removeAttribute("lang");
- }
-
- if (node.hasAttribute("style")) {
-
- var styles = node.getAttribute("style").split(";");
- var nstyle = [];
- Roo.each(styles, function(s) {
- if (!s.match(/:/)) {
- return;
- }
- var kv = s.split(":");
- if (kv[0].match(/^(mso-|line|font|background|margin|padding|color)/)) {
- return;
- }
- // what ever is left... we allow.
- nstyle.push(s);
- });
- node.setAttribute("style", nstyle.length ? nstyle.join(';') : '');
- if (!nstyle.length) {
- node.removeAttribute('style');
- }
- }
- this.iterateChildren(node, this.cleanWord);
-
-
+ new Roo.htmleditor.FilterWord({ node : node ? node : this.doc.body });
},
- /**
- * iterateChildren of a Node, calling fn each time, using this as the scole..
- * @param {DomNode} node node to iterate children of.
- * @param {Function} fn method of this class to call on each item.
- */
- iterateChildren : function(node, fn)
- {
- if (!node.childNodes.length) {
- return;
- }
- for (var i = node.childNodes.length-1; i > -1 ; i--) {
- fn.call(this, node.childNodes[i])
- }
- },
-
+
/**
- * cleanTableWidths.
- *
- * Quite often pasting from word etc.. results in tables with column and widths.
- * This does not work well on fluid HTML layouts - like emails. - so this code should hunt an destroy them..
- *
+
+ * @deprecated - use filters
*/
cleanTableWidths : function(node)
{
-
-
- if (!node) {
- this.cleanTableWidths(this.doc.body);
- return;
- }
-
- // ignore list...
- if (node.nodeName == "#text" || node.nodeName == "#comment") {
- return;
- }
- Roo.log(node.tagName);
- if (!node.tagName.toLowerCase().match(/^(table|td|tr)$/)) {
- this.iterateChildren(node, this.cleanTableWidths);
- return;
- }
- if (node.hasAttribute('width')) {
- node.removeAttribute('width');
- }
-
-
- if (node.hasAttribute("style")) {
- // pretty basic...
-
- var styles = node.getAttribute("style").split(";");
- var nstyle = [];
- Roo.each(styles, function(s) {
- if (!s.match(/:/)) {
- return;
- }
- var kv = s.split(":");
- if (kv[0].match(/^\s*(width|min-width)\s*$/)) {
- return;
- }
- // what ever is left... we allow.
- nstyle.push(s);
- });
- node.setAttribute("style", nstyle.length ? nstyle.join(';') : '');
- if (!nstyle.length) {
- node.removeAttribute('style');
- }
- }
-
- this.iterateChildren(node, this.cleanTableWidths);
-
+ new Roo.htmleditor.FilterTableWidth({ node : node ? node : this.doc.body});
+
},
-
-
-
- domToHTML : function(currentElement, depth, nopadtext) {
-
- depth = depth || 0;
- nopadtext = nopadtext || false;
-
- if (!currentElement) {
- return this.domToHTML(this.doc.body);
- }
-
- //Roo.log(currentElement);
- var j;
- var allText = false;
- var nodeName = currentElement.nodeName;
- var tagName = Roo.util.Format.htmlEncode(currentElement.tagName);
-
- if (nodeName == '#text') {
-
- return nopadtext ? currentElement.nodeValue : currentElement.nodeValue.trim();
- }
-
-
- var ret = '';
- if (nodeName != 'BODY') {
-
- var i = 0;
- // Prints the node tagName, such as <A>, <IMG>, etc
- if (tagName) {
- var attr = [];
- for(i = 0; i < currentElement.attributes.length;i++) {
- // quoting?
- var aname = currentElement.attributes.item(i).name;
- if (!currentElement.attributes.item(i).value.length) {
- continue;
- }
- attr.push(aname + '="' + Roo.util.Format.htmlEncode(currentElement.attributes.item(i).value) + '"' );
- }
-
- ret = "<"+currentElement.tagName+ ( attr.length ? (' ' + attr.join(' ') ) : '') + ">";
- }
- else {
-
- // eack
- }
- } else {
- tagName = false;
- }
- if (['IMG', 'BR', 'HR', 'INPUT'].indexOf(tagName) > -1) {
- return ret;
- }
- if (['PRE', 'TEXTAREA', 'TD', 'A', 'SPAN'].indexOf(tagName) > -1) { // or code?
- nopadtext = true;
- }
-
-
- // Traverse the tree
- i = 0;
- var currentElementChild = currentElement.childNodes.item(i);
- var allText = true;
- var innerHTML = '';
- lastnode = '';
- while (currentElementChild) {
- // Formatting code (indent the tree so it looks nice on the screen)
- var nopad = nopadtext;
- if (lastnode == 'SPAN') {
- nopad = true;
- }
- // text
- if (currentElementChild.nodeName == '#text') {
- var toadd = Roo.util.Format.htmlEncode(currentElementChild.nodeValue);
- toadd = nopadtext ? toadd : toadd.trim();
- if (!nopad && toadd.length > 80) {
- innerHTML += "\n" + (new Array( depth + 1 )).join( " " );
- }
- innerHTML += toadd;
-
- i++;
- currentElementChild = currentElement.childNodes.item(i);
- lastNode = '';
- continue;
- }
- allText = false;
-
- innerHTML += nopad ? '' : "\n" + (new Array( depth + 1 )).join( " " );
-
- // Recursively traverse the tree structure of the child node
- innerHTML += this.domToHTML(currentElementChild, depth+1, nopadtext);
- lastnode = currentElementChild.nodeName;
- i++;
- currentElementChild=currentElement.childNodes.item(i);
- }
-
- ret += innerHTML;
-
- if (!allText) {
- // The remaining code is mostly for formatting the tree
- ret+= nopadtext ? '' : "\n" + (new Array( depth )).join( " " );
- }
-
-
- if (tagName) {
- ret+= "</"+tagName+">";
- }
- return ret;
-
- },
+
applyBlacklists : function()
{
var w = typeof(this.owner.white) != 'undefined' && this.owner.white ? this.owner.white : [];
var b = typeof(this.owner.black) != 'undefined' && this.owner.black ? this.owner.black : [];
+ this.aclean = typeof(this.owner.aclean) != 'undefined' && this.owner.aclean ? this.owner.aclean : Roo.HtmlEditorCore.aclean;
+ this.ablack = typeof(this.owner.ablack) != 'undefined' && this.owner.ablack ? this.owner.ablack : Roo.HtmlEditorCore.ablack;
+ this.tag_remove = typeof(this.owner.tag_remove) != 'undefined' && this.owner.tag_remove ? this.owner.tag_remove : Roo.HtmlEditorCore.tag_remove;
+
this.white = [];
this.black = [];
Roo.each(Roo.HtmlEditorCore.white, function(tag) {
},
+
+ updateLanguage : function()
+ {
+ if (!this.iframe || !this.iframe.contentDocument) {
+ return;
+ }
+ Roo.get(this.iframe.contentDocument.body).attr("lang", this.language);
+ },
+
+
removeStylesheets : function()
{
var _this = this;
});
Roo.HtmlEditorCore.white = [
- 'area', 'br', 'img', 'input', 'hr', 'wbr',
+ 'AREA', 'BR', 'IMG', 'INPUT', 'HR', 'WBR',
- 'address', 'blockquote', 'center', 'dd', 'dir', 'div',
- 'dl', 'dt', 'h1', 'h2', 'h3', 'h4',
- 'h5', 'h6', 'hr', 'isindex', 'listing', 'marquee',
- 'menu', 'multicol', 'ol', 'p', 'plaintext', 'pre',
- 'table', 'ul', 'xmp',
+ 'ADDRESS', 'BLOCKQUOTE', 'CENTER', 'DD', 'DIR', 'DIV',
+ 'DL', 'DT', 'H1', 'H2', 'H3', 'H4',
+ 'H5', 'H6', 'HR', 'ISINDEX', 'LISTING', 'MARQUEE',
+ 'MENU', 'MULTICOL', 'OL', 'P', 'PLAINTEXT', 'PRE',
+ 'TABLE', 'UL', 'XMP',
- 'caption', 'col', 'colgroup', 'tbody', 'td', 'tfoot', 'th',
- 'thead', 'tr',
+ 'CAPTION', 'COL', 'COLGROUP', 'TBODY', 'TD', 'TFOOT', 'TH',
+ 'THEAD', 'TR',
- 'dir', 'menu', 'ol', 'ul', 'dl',
+ 'DIR', 'MENU', 'OL', 'UL', 'DL',
- 'embed', 'object'
+ 'EMBED', 'OBJECT'
];
Roo.HtmlEditorCore.black = [
// 'embed', 'object', // enable - backend responsiblity to clean thiese
- 'applet', //
- 'base', 'basefont', 'bgsound', 'blink', 'body',
- 'frame', 'frameset', 'head', 'html', 'ilayer',
- 'iframe', 'layer', 'link', 'meta', 'object',
- 'script', 'style' ,'title', 'xml' // clean later..
+ 'APPLET', //
+ 'BASE', 'BASEFONT', 'BGSOUND', 'BLINK', 'BODY',
+ 'FRAME', 'FRAMESET', 'HEAD', 'HTML', 'ILAYER',
+ 'IFRAME', 'LAYER', 'LINK', 'META', 'OBJECT',
+ 'SCRIPT', 'STYLE' ,'TITLE', 'XML',
+ //'FONT' // CLEAN LATER..
+ 'COLGROUP', 'COL' // messy tables.
+
+
];
-Roo.HtmlEditorCore.clean = [
- 'script', 'style', 'title', 'xml'
+Roo.HtmlEditorCore.clean = [ // ?? needed???
+ 'SCRIPT', 'STYLE', 'TITLE', 'XML'
];
-Roo.HtmlEditorCore.remove = [
- 'font'
+Roo.HtmlEditorCore.tag_remove = [
+ 'FONT', 'TBODY'
];
// attributes..
];
-Roo.HtmlEditorCore.swapCodes =[
- [ 8211, "–" ],
- [ 8212, "—" ],
- [ 8216, "'" ],
- [ 8217, "'" ],
- [ 8220, '"' ],
- [ 8221, '"' ],
- [ 8226, "*" ],
- [ 8230, "..." ]
-];
+
/*
* - LGPL
*/
/**
- * @class Roo.bootstrap.HtmlEditor
- * @extends Roo.bootstrap.TextArea
+ * @class Roo.bootstrap.form.HtmlEditor
+ * @extends Roo.bootstrap.form.TextArea
* Bootstrap HtmlEditor class
* @constructor
* @param {Object} config The config object
*/
-Roo.bootstrap.HtmlEditor = function(config){
- Roo.bootstrap.HtmlEditor.superclass.constructor.call(this, config);
+Roo.bootstrap.form.HtmlEditor = function(config){
+ Roo.bootstrap.form.HtmlEditor.superclass.constructor.call(this, config);
if (!this.toolbars) {
this.toolbars = [];
}
};
-Roo.extend(Roo.bootstrap.HtmlEditor, Roo.bootstrap.TextArea, {
+Roo.extend(Roo.bootstrap.form.HtmlEditor, Roo.bootstrap.form.TextArea, {
/**
Roo.log('renewing');
Roo.log("create toolbars");
- this.toolbars = [ new Roo.bootstrap.htmleditor.ToolbarStandard({editor: this} ) ];
+ this.toolbars = [ new Roo.bootstrap.form.HtmlEditorToolbarStandard({editor: this} ) ];
this.toolbars[0].render(this.toolbarContainer());
return;
// if (!editor.toolbars || !editor.toolbars.length) {
-// editor.toolbars = [ new Roo.bootstrap.HtmlEditor.ToolbarStandard() ]; // can be empty?
+// editor.toolbars = [ new Roo.bootstrap.form.HtmlEditorToolbarStandard() ]; // can be empty?
// }
//
// for (var i =0 ; i < editor.toolbars.length;i++) {
// editor.toolbars[i] = Roo.factory(
// typeof(editor.toolbars[i]) == 'string' ?
// { xtype: editor.toolbars[i]} : editor.toolbars[i],
-// Roo.bootstrap.HtmlEditor);
+// Roo.bootstrap.form.HtmlEditor);
// editor.toolbars[i].init(editor);
// }
},
{
// Roo.log("Call onRender: " + this.xtype);
var _t = this;
- Roo.bootstrap.HtmlEditor.superclass.onRender.call(this, ct, position);
+ Roo.bootstrap.form.HtmlEditor.superclass.onRender.call(this, ct, position);
this.wrap = this.inputEl().wrap({
cls:'x-html-editor-wrap', cn:{cls:'x-html-editor-tb'}
onResize : function(w, h)
{
Roo.log('resize: ' +w + ',' + h );
- Roo.bootstrap.HtmlEditor.superclass.onResize.apply(this, arguments);
+ Roo.bootstrap.form.HtmlEditor.superclass.onResize.apply(this, arguments);
var ew = false;
var eh = false;
// clearInvalid : Roo.emptyFn,
setValue : function(v){
- Roo.bootstrap.HtmlEditor.superclass.setValue.call(this, v);
+ Roo.bootstrap.form.HtmlEditor.superclass.setValue.call(this, v);
this.editorcore.pushValue();
},
-Roo.namespace('Roo.bootstrap.htmleditor');
+Roo.namespace('Roo.bootstrap.form.HtmlEditor');
/**
- * @class Roo.bootstrap.HtmlEditorToolbar1
+ * @class Roo.bootstrap.form.HtmlEditorToolbarStandard
+ * @parent Roo.bootstrap.form.HtmlEditor
+ * @extends Roo.bootstrap.nav.Simplebar
* Basic Toolbar
*
* @example
* Usage:
*
- new Roo.bootstrap.HtmlEditor({
+ new Roo.bootstrap.form.HtmlEditor({
....
toolbars : [
- new Roo.bootstrap.HtmlEditorToolbar1({
+ new Roo.bootstrap.form.HtmlEditorToolbarStandard({
disable : { fonts: 1 , format: 1, ..., ... , ...],
btns : [ .... ]
})
* .x-html-editor-tb .x-edit-none .x-btn-text { background: none; }
*/
-Roo.bootstrap.htmleditor.ToolbarStandard = function(config)
+Roo.bootstrap.form.HtmlEditorToolbarStandard = function(config)
{
Roo.apply(this, config);
colors : true,
specialElements : true
});
- Roo.bootstrap.htmleditor.ToolbarStandard.superclass.constructor.call(this, config);
+ Roo.bootstrap.form.HtmlEditorToolbarStandard.superclass.constructor.call(this, config);
this.editor = config.editor;
this.editorcore = config.editor.editorcore;
//Roo.form.HtmlEditorToolbar1.superclass.constructor.call(this, editor.wrap.dom.firstChild, [], config);
// dont call parent... till later.
}
-Roo.extend(Roo.bootstrap.htmleditor.ToolbarStandard, Roo.bootstrap.NavSimplebar, {
+Roo.extend(Roo.bootstrap.form.HtmlEditorToolbarStandard, Roo.bootstrap.nav.Simplebar, {
bar : true,
{
// Roo.log("Call onRender: " + this.xtype);
- Roo.bootstrap.htmleditor.ToolbarStandard.superclass.onRender.call(this, ct, position);
+ Roo.bootstrap.form.HtmlEditorToolbarStandard.superclass.onRender.call(this, ct, position);
Roo.log(this.el);
this.el.dom.style.marginBottom = '0';
var _this = this;
// hides menus... - so this cant be on a menu...
Roo.bootstrap.MenuMgr.hideAll();
*/
- Roo.bootstrap.MenuMgr.hideAll();
+ Roo.bootstrap.menu.Manager.hideAll();
//this.editorsyncValue();
},
onFirstFocus: function() {
*/
/**
- * @class Roo.bootstrap.Markdown
- * @extends Roo.bootstrap.TextArea
+ * @class Roo.bootstrap.form.Markdown
+ * @extends Roo.bootstrap.form.TextArea
* Bootstrap Showdown editable area
* @cfg {string} content
*
* Create a new Showdown
*/
-Roo.bootstrap.Markdown = function(config){
- Roo.bootstrap.Markdown.superclass.constructor.call(this, config);
+Roo.bootstrap.form.Markdown = function(config){
+ Roo.bootstrap.form.Markdown.superclass.constructor.call(this, config);
};
-Roo.extend(Roo.bootstrap.Markdown, Roo.bootstrap.TextArea, {
+Roo.extend(Roo.bootstrap.form.Markdown, Roo.bootstrap.form.TextArea, {
editing :false,
initEvents : function()
{
- Roo.bootstrap.TextArea.prototype.initEvents.call(this);
+ Roo.bootstrap.form.TextArea.prototype.initEvents.call(this);
this.markdownEl = this.el.createChild({
cls : 'roo-markdown-area'
});
},
setValue : function(val)
{
- Roo.bootstrap.TextArea.prototype.setValue.call(this,val);
+ Roo.bootstrap.form.TextArea.prototype.setValue.call(this,val);
if (!this.editing) {
this.updateMarkdown();
}
}
-});
-/**
- * @class Roo.bootstrap.Table.AbstractSelectionModel
- * @extends Roo.util.Observable
- * Abstract base class for grid SelectionModels. It provides the interface that should be
- * implemented by descendant classes. This class should not be directly instantiated.
- * @constructor
- */
-Roo.bootstrap.Table.AbstractSelectionModel = function(){
- this.locked = false;
- Roo.bootstrap.Table.AbstractSelectionModel.superclass.constructor.call(this);
-};
-
-
-Roo.extend(Roo.bootstrap.Table.AbstractSelectionModel, Roo.util.Observable, {
- /** @ignore Called by the grid automatically. Do not call directly. */
- init : function(grid){
- this.grid = grid;
- this.initEvents();
- },
-
- /**
- * Locks the selections.
- */
- lock : function(){
- this.locked = true;
- },
-
- /**
- * Unlocks the selections.
- */
- unlock : function(){
- this.locked = false;
- },
-
- /**
- * Returns true if the selections are locked.
- * @return {Boolean}
- */
- isLocked : function(){
- return this.locked;
- },
-
-
- initEvents : function ()
- {
-
- }
-});
-/**
- * @extends Roo.bootstrap.Table.AbstractSelectionModel
- * @class Roo.bootstrap.Table.RowSelectionModel
- * The default SelectionModel used by {@link Roo.bootstrap.Table}.
- * It supports multiple selections and keyboard selection/navigation.
- * @constructor
- * @param {Object} config
- */
-
-Roo.bootstrap.Table.RowSelectionModel = function(config){
- Roo.apply(this, config);
- this.selections = new Roo.util.MixedCollection(false, function(o){
- return o.id;
- });
-
- this.last = false;
- this.lastActive = false;
-
- this.addEvents({
- /**
- * @event selectionchange
- * Fires when the selection changes
- * @param {SelectionModel} this
- */
- "selectionchange" : true,
- /**
- * @event afterselectionchange
- * Fires after the selection changes (eg. by key press or clicking)
- * @param {SelectionModel} this
- */
- "afterselectionchange" : true,
- /**
- * @event beforerowselect
- * Fires when a row is selected being selected, return false to cancel.
- * @param {SelectionModel} this
- * @param {Number} rowIndex The selected index
- * @param {Boolean} keepExisting False if other selections will be cleared
- */
- "beforerowselect" : true,
- /**
- * @event rowselect
- * Fires when a row is selected.
- * @param {SelectionModel} this
- * @param {Number} rowIndex The selected index
- * @param {Roo.data.Record} r The record
- */
- "rowselect" : true,
- /**
- * @event rowdeselect
- * Fires when a row is deselected.
- * @param {SelectionModel} this
- * @param {Number} rowIndex The selected index
- */
- "rowdeselect" : true
- });
- Roo.bootstrap.Table.RowSelectionModel.superclass.constructor.call(this);
- this.locked = false;
- };
-
-Roo.extend(Roo.bootstrap.Table.RowSelectionModel, Roo.bootstrap.Table.AbstractSelectionModel, {
- /**
- * @cfg {Boolean} singleSelect
- * True to allow selection of only one row at a time (defaults to false)
- */
- singleSelect : false,
-
- // private
- initEvents : function()
- {
-
- //if(!this.grid.enableDragDrop && !this.grid.enableDrag){
- // this.growclickrid.on("mousedown", this.handleMouseDown, this);
- //}else{ // allow click to work like normal
- // this.grid.on("rowclick", this.handleDragableRowClick, this);
- //}
- //this.grid.on("rowdblclick", this.handleMouseDBClick, this);
- this.grid.on("rowclick", this.handleMouseDown, this);
-
- this.rowNav = new Roo.KeyNav(this.grid.getGridEl(), {
- "up" : function(e){
- if(!e.shiftKey){
- this.selectPrevious(e.shiftKey);
- }else if(this.last !== false && this.lastActive !== false){
- var last = this.last;
- this.selectRange(this.last, this.lastActive-1);
- this.grid.getView().focusRow(this.lastActive);
- if(last !== false){
- this.last = last;
- }
- }else{
- this.selectFirstRow();
- }
- this.fireEvent("afterselectionchange", this);
- },
- "down" : function(e){
- if(!e.shiftKey){
- this.selectNext(e.shiftKey);
- }else if(this.last !== false && this.lastActive !== false){
- var last = this.last;
- this.selectRange(this.last, this.lastActive+1);
- this.grid.getView().focusRow(this.lastActive);
- if(last !== false){
- this.last = last;
- }
- }else{
- this.selectFirstRow();
- }
- this.fireEvent("afterselectionchange", this);
- },
- scope: this
- });
- this.grid.store.on('load', function(){
- this.selections.clear();
- },this);
- /*
- var view = this.grid.view;
- view.on("refresh", this.onRefresh, this);
- view.on("rowupdated", this.onRowUpdated, this);
- view.on("rowremoved", this.onRemove, this);
- */
- },
-
- // private
- onRefresh : function()
- {
- var ds = this.grid.store, i, v = this.grid.view;
- var s = this.selections;
- s.each(function(r){
- if((i = ds.indexOfId(r.id)) != -1){
- v.onRowSelect(i);
- }else{
- s.remove(r);
- }
- });
- },
-
- // private
- onRemove : function(v, index, r){
- this.selections.remove(r);
- },
-
- // private
- onRowUpdated : function(v, index, r){
- if(this.isSelected(r)){
- v.onRowSelect(index);
- }
- },
-
- /**
- * Select records.
- * @param {Array} records The records to select
- * @param {Boolean} keepExisting (optional) True to keep existing selections
- */
- selectRecords : function(records, keepExisting)
- {
- if(!keepExisting){
- this.clearSelections();
- }
- var ds = this.grid.store;
- for(var i = 0, len = records.length; i < len; i++){
- this.selectRow(ds.indexOf(records[i]), true);
- }
- },
-
- /**
- * Gets the number of selected rows.
- * @return {Number}
- */
- getCount : function(){
- return this.selections.length;
- },
-
- /**
- * Selects the first row in the grid.
- */
- selectFirstRow : function(){
- this.selectRow(0);
- },
-
- /**
- * Select the last row.
- * @param {Boolean} keepExisting (optional) True to keep existing selections
- */
- selectLastRow : function(keepExisting){
- //this.selectRow(this.grid.dataSource.getCount() - 1, keepExisting);
- this.selectRow(this.grid.store.getCount() - 1, keepExisting);
- },
-
- /**
- * Selects the row immediately following the last selected row.
- * @param {Boolean} keepExisting (optional) True to keep existing selections
- */
- selectNext : function(keepExisting)
- {
- if(this.last !== false && (this.last+1) < this.grid.store.getCount()){
- this.selectRow(this.last+1, keepExisting);
- this.grid.getView().focusRow(this.last);
- }
- },
-
- /**
- * Selects the row that precedes the last selected row.
- * @param {Boolean} keepExisting (optional) True to keep existing selections
- */
- selectPrevious : function(keepExisting){
- if(this.last){
- this.selectRow(this.last-1, keepExisting);
- this.grid.getView().focusRow(this.last);
- }
- },
-
- /**
- * Returns the selected records
- * @return {Array} Array of selected records
- */
- getSelections : function(){
- return [].concat(this.selections.items);
- },
-
- /**
- * Returns the first selected record.
- * @return {Record}
- */
- getSelected : function(){
- return this.selections.itemAt(0);
- },
-
-
- /**
- * Clears all selections.
- */
- clearSelections : function(fast)
- {
- if(this.locked) {
- return;
- }
- if(fast !== true){
- var ds = this.grid.store;
- var s = this.selections;
- s.each(function(r){
- this.deselectRow(ds.indexOfId(r.id));
- }, this);
- s.clear();
- }else{
- this.selections.clear();
- }
- this.last = false;
- },
-
-
- /**
- * Selects all rows.
- */
- selectAll : function(){
- if(this.locked) {
- return;
- }
- this.selections.clear();
- for(var i = 0, len = this.grid.store.getCount(); i < len; i++){
- this.selectRow(i, true);
- }
- },
-
- /**
- * Returns True if there is a selection.
- * @return {Boolean}
- */
- hasSelection : function(){
- return this.selections.length > 0;
- },
-
- /**
- * Returns True if the specified row is selected.
- * @param {Number/Record} record The record or index of the record to check
- * @return {Boolean}
- */
- isSelected : function(index){
- var r = typeof index == "number" ? this.grid.store.getAt(index) : index;
- return (r && this.selections.key(r.id) ? true : false);
- },
-
- /**
- * Returns True if the specified record id is selected.
- * @param {String} id The id of record to check
- * @return {Boolean}
- */
- isIdSelected : function(id){
- return (this.selections.key(id) ? true : false);
- },
-
-
- // private
- handleMouseDBClick : function(e, t){
-
- },
- // private
- handleMouseDown : function(e, t)
- {
- var rowIndex = this.grid.headerShow ? t.dom.rowIndex - 1 : t.dom.rowIndex ; // first row is header???
- if(this.isLocked() || rowIndex < 0 ){
- return;
- };
- if(e.shiftKey && this.last !== false){
- var last = this.last;
- this.selectRange(last, rowIndex, e.ctrlKey);
- this.last = last; // reset the last
- t.focus();
-
- }else{
- var isSelected = this.isSelected(rowIndex);
- //Roo.log("select row:" + rowIndex);
- if(isSelected){
- this.deselectRow(rowIndex);
- } else {
- this.selectRow(rowIndex, true);
- }
-
- /*
- if(e.button !== 0 && isSelected){
- alert('rowIndex 2: ' + rowIndex);
- view.focusRow(rowIndex);
- }else if(e.ctrlKey && isSelected){
- this.deselectRow(rowIndex);
- }else if(!isSelected){
- this.selectRow(rowIndex, e.button === 0 && (e.ctrlKey || e.shiftKey));
- view.focusRow(rowIndex);
- }
- */
- }
- this.fireEvent("afterselectionchange", this);
- },
- // private
- handleDragableRowClick : function(grid, rowIndex, e)
- {
- if(e.button === 0 && !e.shiftKey && !e.ctrlKey) {
- this.selectRow(rowIndex, false);
- grid.view.focusRow(rowIndex);
- this.fireEvent("afterselectionchange", this);
- }
- },
-
- /**
- * Selects multiple rows.
- * @param {Array} rows Array of the indexes of the row to select
- * @param {Boolean} keepExisting (optional) True to keep existing selections
- */
- selectRows : function(rows, keepExisting){
- if(!keepExisting){
- this.clearSelections();
- }
- for(var i = 0, len = rows.length; i < len; i++){
- this.selectRow(rows[i], true);
- }
- },
-
- /**
- * Selects a range of rows. All rows in between startRow and endRow are also selected.
- * @param {Number} startRow The index of the first row in the range
- * @param {Number} endRow The index of the last row in the range
- * @param {Boolean} keepExisting (optional) True to retain existing selections
- */
- selectRange : function(startRow, endRow, keepExisting){
- if(this.locked) {
- return;
- }
- if(!keepExisting){
- this.clearSelections();
- }
- if(startRow <= endRow){
- for(var i = startRow; i <= endRow; i++){
- this.selectRow(i, true);
- }
- }else{
- for(var i = startRow; i >= endRow; i--){
- this.selectRow(i, true);
- }
- }
- },
-
- /**
- * Deselects a range of rows. All rows in between startRow and endRow are also deselected.
- * @param {Number} startRow The index of the first row in the range
- * @param {Number} endRow The index of the last row in the range
- */
- deselectRange : function(startRow, endRow, preventViewNotify){
- if(this.locked) {
- return;
- }
- for(var i = startRow; i <= endRow; i++){
- this.deselectRow(i, preventViewNotify);
- }
- },
-
- /**
- * Selects a row.
- * @param {Number} row The index of the row to select
- * @param {Boolean} keepExisting (optional) True to keep existing selections
- */
- selectRow : function(index, keepExisting, preventViewNotify)
- {
- if(this.locked || (index < 0 || index > this.grid.store.getCount())) {
- return;
- }
- if(this.fireEvent("beforerowselect", this, index, keepExisting) !== false){
- if(!keepExisting || this.singleSelect){
- this.clearSelections();
- }
-
- var r = this.grid.store.getAt(index);
- //console.log('selectRow - record id :' + r.id);
-
- this.selections.add(r);
- this.last = this.lastActive = index;
- if(!preventViewNotify){
- var proxy = new Roo.Element(
- this.grid.getRowDom(index)
- );
- proxy.addClass('bg-info info');
- }
- this.fireEvent("rowselect", this, index, r);
- this.fireEvent("selectionchange", this);
- }
- },
-
- /**
- * Deselects a row.
- * @param {Number} row The index of the row to deselect
- */
- deselectRow : function(index, preventViewNotify)
- {
- if(this.locked) {
- return;
- }
- if(this.last == index){
- this.last = false;
- }
- if(this.lastActive == index){
- this.lastActive = false;
- }
-
- var r = this.grid.store.getAt(index);
- if (!r) {
- return;
- }
-
- this.selections.remove(r);
- //.console.log('deselectRow - record id :' + r.id);
- if(!preventViewNotify){
-
- var proxy = new Roo.Element(
- this.grid.getRowDom(index)
- );
- proxy.removeClass('bg-info info');
- }
- this.fireEvent("rowdeselect", this, index);
- this.fireEvent("selectionchange", this);
- },
-
- // private
- restoreLast : function(){
- if(this._last){
- this.last = this._last;
- }
- },
-
- // private
- acceptsNav : function(row, col, cm){
- return !cm.isHidden(col) && cm.isCellEditable(col, row);
- },
-
- // private
- onEditorKey : function(field, e){
- var k = e.getKey(), newCell, g = this.grid, ed = g.activeEditor;
- if(k == e.TAB){
- e.stopEvent();
- ed.completeEdit();
- if(e.shiftKey){
- newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);
- }else{
- newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
- }
- }else if(k == e.ENTER && !e.ctrlKey){
- e.stopEvent();
- ed.completeEdit();
- if(e.shiftKey){
- newCell = g.walkCells(ed.row-1, ed.col, -1, this.acceptsNav, this);
- }else{
- newCell = g.walkCells(ed.row+1, ed.col, 1, this.acceptsNav, this);
- }
- }else if(k == e.ESC){
- ed.cancelEdit();
- }
- if(newCell){
- g.startEditing(newCell[0], newCell[1]);
- }
- }
-});
-/*
+});/*
* Based on:
* Ext JS Library 1.1.1
* Copyright(c) 2006-2007, Ext JS, LLC.
/**
* @class Roo.bootstrap.PagingToolbar
- * @extends Roo.bootstrap.NavSimplebar
+ * @extends Roo.bootstrap.nav.Simplebar
* A specialized toolbar that is bound to a {@link Roo.data.Store} and provides automatic paging controls.
* @constructor
* Create a new PagingToolbar
if (Roo.bootstrap.version == 4) {
this.navgroup = new Roo.bootstrap.ButtonGroup({ cls: 'pagination' });
} else {
- this.navgroup = new Roo.bootstrap.NavGroup({ cls: 'pagination' });
+ this.navgroup = new Roo.bootstrap.nav.Group({ cls: 'pagination' });
}
};
-Roo.extend(Roo.bootstrap.PagingToolbar, Roo.bootstrap.NavSimplebar, {
+Roo.extend(Roo.bootstrap.PagingToolbar, Roo.bootstrap.nav.Simplebar, {
/**
- * @cfg {Roo.data.Store} dataSource
+ * @cfg {Roo.bootstrap.Button} buttons[]
+ * Buttons for the toolbar
+ */
+ /**
+ * @cfg {Roo.data.Store} store
* The underlying data store providing the paged data
*/
/**
},
// private
- onLoadError : function(){
+ onLoadError : function(proxy, o){
this.loading.enable();
+ if (this.ds.events.loadexception.listeners.length < 2) {
+ // nothing has been assigned to loadexception except this...
+ // so
+ Roo.MessageBox.alert("Error loading",o.raw.errorMsg);
+
+ }
},
// private
});
-/*
+Roo.bootstrap.dash = {};/*
* - LGPL
*
* numberBox
/**
* @class Roo.bootstrap.dash.TabBox
* @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.dash.TabPane
* Bootstrap TabBox class
* @cfg {String} title Title of the TabBox
* @cfg {String} icon Icon of the TabBox
/**
* @class Roo.bootstrap.TabPane
* @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.Graph Roo.bootstrap.Column
* Bootstrap TabPane class
* @cfg {Boolean} active (false | true) Default false
* @cfg {String} title title of panel
- /*
- * - LGPL
- *
- * menu
- *
- */
-Roo.bootstrap.menu = Roo.bootstrap.menu || {};
-
-/**
- * @class Roo.bootstrap.menu.Menu
- * @extends Roo.bootstrap.Component
- * Bootstrap Menu class - container for Menu
- * @cfg {String} html Text of the menu
- * @cfg {String} weight (default | primary | success | info | warning | danger | inverse)
- * @cfg {String} icon Font awesome icon
- * @cfg {String} pos Menu align to (top | bottom) default bottom
- *
- *
- * @constructor
- * Create a new Menu
- * @param {Object} config The config object
- */
-
-
-Roo.bootstrap.menu.Menu = function(config){
- Roo.bootstrap.menu.Menu.superclass.constructor.call(this, config);
-
- this.addEvents({
- /**
- * @event beforeshow
- * Fires before this menu is displayed
- * @param {Roo.bootstrap.menu.Menu} this
- */
- beforeshow : true,
- /**
- * @event beforehide
- * Fires before this menu is hidden
- * @param {Roo.bootstrap.menu.Menu} this
- */
- beforehide : true,
- /**
- * @event show
- * Fires after this menu is displayed
- * @param {Roo.bootstrap.menu.Menu} this
- */
- show : true,
- /**
- * @event hide
- * Fires after this menu is hidden
- * @param {Roo.bootstrap.menu.Menu} this
- */
- hide : true,
- /**
- * @event click
- * Fires when this menu is clicked (or when the enter key is pressed while it is active)
- * @param {Roo.bootstrap.menu.Menu} this
- * @param {Roo.EventObject} e
- */
- click : true
- });
-
-};
-
-Roo.extend(Roo.bootstrap.menu.Menu, Roo.bootstrap.Component, {
-
- submenu : false,
- html : '',
- weight : 'default',
- icon : false,
- pos : 'bottom',
-
-
- getChildContainer : function() {
- if(this.isSubMenu){
- return this.el;
- }
-
- return this.el.select('ul.dropdown-menu', true).first();
- },
-
- getAutoCreate : function()
- {
- var text = [
- {
- tag : 'span',
- cls : 'roo-menu-text',
- html : this.html
- }
- ];
-
- if(this.icon){
- text.unshift({
- tag : 'i',
- cls : 'fa ' + this.icon
- })
- }
-
-
- var cfg = {
- tag : 'div',
- cls : 'btn-group',
- cn : [
- {
- tag : 'button',
- cls : 'dropdown-button btn btn-' + this.weight,
- cn : text
- },
- {
- tag : 'button',
- cls : 'dropdown-toggle btn btn-' + this.weight,
- cn : [
- {
- tag : 'span',
- cls : 'caret'
- }
- ]
- },
- {
- tag : 'ul',
- cls : 'dropdown-menu'
- }
- ]
-
- };
-
- if(this.pos == 'top'){
- cfg.cls += ' dropup';
- }
-
- if(this.isSubMenu){
- cfg = {
- tag : 'ul',
- cls : 'dropdown-menu'
- }
- }
-
- return cfg;
- },
-
- onRender : function(ct, position)
- {
- this.isSubMenu = ct.hasClass('dropdown-submenu');
-
- Roo.bootstrap.menu.Menu.superclass.onRender.call(this, ct, position);
- },
-
- initEvents : function()
- {
- if(this.isSubMenu){
- return;
- }
-
- this.hidden = true;
-
- this.triggerEl = this.el.select('button.dropdown-toggle', true).first();
- this.triggerEl.on('click', this.onTriggerPress, this);
-
- this.buttonEl = this.el.select('button.dropdown-button', true).first();
- this.buttonEl.on('click', this.onClick, this);
-
- },
-
- list : function()
- {
- if(this.isSubMenu){
- return this.el;
- }
-
- return this.el.select('ul.dropdown-menu', true).first();
- },
-
- onClick : function(e)
- {
- this.fireEvent("click", this, e);
- },
-
- onTriggerPress : function(e)
- {
- if (this.isVisible()) {
- this.hide();
- } else {
- this.show();
- }
- },
-
- isVisible : function(){
- return !this.hidden;
- },
-
- show : function()
- {
- this.fireEvent("beforeshow", this);
-
- this.hidden = false;
- this.el.addClass('open');
-
- Roo.get(document).on("mouseup", this.onMouseUp, this);
-
- this.fireEvent("show", this);
-
-
- },
-
- hide : function()
- {
- this.fireEvent("beforehide", this);
-
- this.hidden = true;
- this.el.removeClass('open');
-
- Roo.get(document).un("mouseup", this.onMouseUp);
-
- this.fireEvent("hide", this);
- },
-
- onMouseUp : function()
- {
- this.hide();
- }
-
-});
-
-
- /*
- * - LGPL
- *
- * menu item
- *
- */
-Roo.bootstrap.menu = Roo.bootstrap.menu || {};
-
-/**
- * @class Roo.bootstrap.menu.Item
- * @extends Roo.bootstrap.Component
- * Bootstrap MenuItem class
- * @cfg {Boolean} submenu (true | false) default false
- * @cfg {String} html text of the item
- * @cfg {String} href the link
- * @cfg {Boolean} disable (true | false) default false
- * @cfg {Boolean} preventDefault (true | false) default true
- * @cfg {String} icon Font awesome icon
- * @cfg {String} pos Submenu align to (left | right) default right
- *
- *
- * @constructor
- * Create a new Item
- * @param {Object} config The config object
- */
-
-
-Roo.bootstrap.menu.Item = function(config){
- Roo.bootstrap.menu.Item.superclass.constructor.call(this, config);
- this.addEvents({
- /**
- * @event mouseover
- * Fires when the mouse is hovering over this menu
- * @param {Roo.bootstrap.menu.Item} this
- * @param {Roo.EventObject} e
- */
- mouseover : true,
- /**
- * @event mouseout
- * Fires when the mouse exits this menu
- * @param {Roo.bootstrap.menu.Item} this
- * @param {Roo.EventObject} e
- */
- mouseout : true,
- // raw events
- /**
- * @event click
- * The raw click event for the entire grid.
- * @param {Roo.EventObject} e
- */
- click : true
- });
-};
-
-Roo.extend(Roo.bootstrap.menu.Item, Roo.bootstrap.Component, {
-
- submenu : false,
- href : '',
- html : '',
- preventDefault: true,
- disable : false,
- icon : false,
- pos : 'right',
-
- getAutoCreate : function()
- {
- var text = [
- {
- tag : 'span',
- cls : 'roo-menu-item-text',
- html : this.html
- }
- ];
-
- if(this.icon){
- text.unshift({
- tag : 'i',
- cls : 'fa ' + this.icon
- })
- }
-
- var cfg = {
- tag : 'li',
- cn : [
- {
- tag : 'a',
- href : this.href || '#',
- cn : text
- }
- ]
- };
-
- if(this.disable){
- cfg.cls = (typeof(cfg.cls) == 'undefined') ? 'disabled' : (cfg.cls + ' disabled');
- }
-
- if(this.submenu){
- cfg.cls = (typeof(cfg.cls) == 'undefined') ? 'dropdown-submenu' : (cfg.cls + ' dropdown-submenu');
-
- if(this.pos == 'left'){
- cfg.cls = (typeof(cfg.cls) == 'undefined') ? 'pull-left' : (cfg.cls + ' pull-left');
- }
- }
-
- return cfg;
- },
-
- initEvents : function()
- {
- this.el.on('mouseover', this.onMouseOver, this);
- this.el.on('mouseout', this.onMouseOut, this);
-
- this.el.select('a', true).first().on('click', this.onClick, this);
-
- },
-
- onClick : function(e)
- {
- if(this.preventDefault){
- e.preventDefault();
- }
-
- this.fireEvent("click", this, e);
- },
-
- onMouseOver : function(e)
- {
- if(this.submenu && this.pos == 'left'){
- this.el.select('ul.dropdown-menu', true).first().setLeft(this.el.select('ul.dropdown-menu', true).first().getWidth() * -1);
- }
-
- this.fireEvent("mouseover", this, e);
- },
-
- onMouseOut : function(e)
- {
- this.fireEvent("mouseout", this, e);
- }
-});
-
-
-
- /*
- * - LGPL
- *
- * menu separator
- *
- */
-Roo.bootstrap.menu = Roo.bootstrap.menu || {};
-
-/**
- * @class Roo.bootstrap.menu.Separator
- * @extends Roo.bootstrap.Component
- * Bootstrap Separator class
- *
- * @constructor
- * Create a new Separator
- * @param {Object} config The config object
- */
-
-
-Roo.bootstrap.menu.Separator = function(config){
- Roo.bootstrap.menu.Separator.superclass.constructor.call(this, config);
-};
-
-Roo.extend(Roo.bootstrap.menu.Separator, Roo.bootstrap.Component, {
-
- getAutoCreate : function(){
- var cfg = {
- tag : 'li',
- cls: 'dropdown-divider divider'
- };
-
- return cfg;
- }
-
-});
-
-
-
/*
* - LGPL
*
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;
}
//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();
}
+ 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],
* @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
title: '',
html: '',
weight: false,
- faicon: false,
+ fa: false,
+ faicon: false, // BC
+ close : false,
+
getAutoCreate : function()
{
tag : 'div',
cls : 'alert',
cn : [
+ {
+ tag: 'button',
+ type : "button",
+ cls: "close",
+ html : '×',
+ style : this.close ? '' : 'display:none'
+ },
{
tag : 'i',
cls : 'roo-alert-icon'
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;
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();
});
/*
- * - LGPL
- *
- * nav progress bar
- *
- */
-
-/**
- * @class Roo.bootstrap.NavProgressBar
- * @extends Roo.bootstrap.Component
- * Bootstrap NavProgressBar class
- *
- * @constructor
- * Create a new nav progress bar
- * @param {Object} config The config object
- */
-
-Roo.bootstrap.NavProgressBar = function(config){
- Roo.bootstrap.NavProgressBar.superclass.constructor.call(this, config);
-
- this.bullets = this.bullets || [];
-
-// Roo.bootstrap.NavProgressBar.register(this);
- this.addEvents({
- /**
- * @event changed
- * Fires when the active item changes
- * @param {Roo.bootstrap.NavProgressBar} this
- * @param {Roo.bootstrap.NavProgressItem} selected The item selected
- * @param {Roo.bootstrap.NavProgressItem} prev The previously selected item
- */
- 'changed': true
- });
-
-};
-
-Roo.extend(Roo.bootstrap.NavProgressBar, Roo.bootstrap.Component, {
-
- bullets : [],
- barItems : [],
-
- getAutoCreate : function()
- {
- var cfg = Roo.apply({}, Roo.bootstrap.NavProgressBar.superclass.getAutoCreate.call(this));
-
- cfg = {
- tag : 'div',
- cls : 'roo-navigation-bar-group',
- cn : [
- {
- tag : 'div',
- cls : 'roo-navigation-top-bar'
- },
- {
- tag : 'div',
- cls : 'roo-navigation-bullets-bar',
- cn : [
- {
- tag : 'ul',
- cls : 'roo-navigation-bar'
- }
- ]
- },
-
- {
- tag : 'div',
- cls : 'roo-navigation-bottom-bar'
- }
- ]
-
- };
-
- return cfg;
-
- },
-
- initEvents: function()
- {
-
- },
-
- onRender : function(ct, position)
- {
- Roo.bootstrap.NavProgressBar.superclass.onRender.call(this, ct, position);
-
- if(this.bullets.length){
- Roo.each(this.bullets, function(b){
- this.addItem(b);
- }, this);
- }
-
- this.format();
-
- },
-
- addItem : function(cfg)
- {
- var item = new Roo.bootstrap.NavProgressItem(cfg);
-
- item.parentId = this.id;
- item.render(this.el.select('.roo-navigation-bar', true).first(), null);
-
- if(cfg.html){
- var top = new Roo.bootstrap.Element({
- tag : 'div',
- cls : 'roo-navigation-bar-text'
- });
-
- var bottom = new Roo.bootstrap.Element({
- tag : 'div',
- cls : 'roo-navigation-bar-text'
- });
-
- top.onRender(this.el.select('.roo-navigation-top-bar', true).first(), null);
- bottom.onRender(this.el.select('.roo-navigation-bottom-bar', true).first(), null);
-
- var topText = new Roo.bootstrap.Element({
- tag : 'span',
- html : (typeof(cfg.position) != 'undefined' && cfg.position == 'top') ? cfg.html : ''
- });
-
- var bottomText = new Roo.bootstrap.Element({
- tag : 'span',
- html : (typeof(cfg.position) != 'undefined' && cfg.position == 'top') ? '' : cfg.html
- });
-
- topText.onRender(top.el, null);
- bottomText.onRender(bottom.el, null);
-
- item.topEl = top;
- item.bottomEl = bottom;
- }
-
- this.barItems.push(item);
-
- return item;
- },
-
- getActive : function()
- {
- var active = false;
-
- Roo.each(this.barItems, function(v){
-
- if (!v.isActive()) {
- return;
- }
-
- active = v;
- return false;
-
- });
-
- return active;
- },
-
- setActiveItem : function(item)
- {
- var prev = false;
-
- Roo.each(this.barItems, function(v){
- if (v.rid == item.rid) {
- return ;
- }
-
- if (v.isActive()) {
- v.setActive(false);
- prev = v;
- }
- });
-
- item.setActive(true);
-
- this.fireEvent('changed', this, item, prev);
- },
-
- getBarItem: function(rid)
- {
- var ret = false;
-
- Roo.each(this.barItems, function(e) {
- if (e.rid != rid) {
- return;
- }
-
- ret = e;
- return false;
- });
-
- return ret;
- },
-
- indexOfItem : function(item)
- {
- var index = false;
-
- Roo.each(this.barItems, function(v, i){
-
- if (v.rid != item.rid) {
- return;
- }
-
- index = i;
- return false
- });
-
- return index;
- },
-
- setActiveNext : function()
- {
- var i = this.indexOfItem(this.getActive());
-
- if (i > this.barItems.length) {
- return;
- }
-
- this.setActiveItem(this.barItems[i+1]);
- },
-
- setActivePrev : function()
- {
- var i = this.indexOfItem(this.getActive());
-
- if (i < 1) {
- return;
- }
-
- this.setActiveItem(this.barItems[i-1]);
- },
-
- format : function()
- {
- if(!this.barItems.length){
- return;
- }
-
- var width = 100 / this.barItems.length;
-
- Roo.each(this.barItems, function(i){
- i.el.setStyle('width', width + '%');
- i.topEl.el.setStyle('width', width + '%');
- i.bottomEl.el.setStyle('width', width + '%');
- }, this);
-
- }
-
-});
-/*
- * - LGPL
- *
- * Nav Progress Item
- *
- */
-
-/**
- * @class Roo.bootstrap.NavProgressItem
- * @extends Roo.bootstrap.Component
- * Bootstrap NavProgressItem class
- * @cfg {String} rid the reference id
- * @cfg {Boolean} active (true|false) Is item active default false
- * @cfg {Boolean} disabled (true|false) Is item active default false
- * @cfg {String} html
- * @cfg {String} position (top|bottom) text position default bottom
- * @cfg {String} icon show icon instead of number
- *
- * @constructor
- * Create a new NavProgressItem
- * @param {Object} config The config object
- */
-Roo.bootstrap.NavProgressItem = function(config){
- Roo.bootstrap.NavProgressItem.superclass.constructor.call(this, config);
- this.addEvents({
- // raw events
- /**
- * @event click
- * The raw click event for the entire grid.
- * @param {Roo.bootstrap.NavProgressItem} this
- * @param {Roo.EventObject} e
- */
- "click" : true
- });
-
-};
-
-Roo.extend(Roo.bootstrap.NavProgressItem, Roo.bootstrap.Component, {
-
- rid : '',
- active : false,
- disabled : false,
- html : '',
- position : 'bottom',
- icon : false,
-
- getAutoCreate : function()
- {
- var iconCls = 'roo-navigation-bar-item-icon';
-
- iconCls += ((this.icon) ? (' ' + this.icon) : (' step-number')) ;
-
- var cfg = {
- tag: 'li',
- cls: 'roo-navigation-bar-item',
- cn : [
- {
- tag : 'i',
- cls : iconCls
- }
- ]
- };
-
- if(this.active){
- cfg.cls += ' active';
- }
- if(this.disabled){
- cfg.cls += ' disabled';
- }
-
- return cfg;
- },
-
- disable : function()
- {
- this.setDisabled(true);
- },
-
- enable : function()
- {
- this.setDisabled(false);
- },
-
- initEvents: function()
- {
- this.iconEl = this.el.select('.roo-navigation-bar-item-icon', true).first();
-
- this.iconEl.on('click', this.onClick, this);
- },
-
- onClick : function(e)
- {
- e.preventDefault();
-
- if(this.disabled){
- return;
- }
-
- if(this.fireEvent('click', this, e) === false){
- return;
- };
-
- this.parent().setActiveItem(this);
- },
-
- isActive: function ()
- {
- return this.active;
- },
-
- setActive : function(state)
- {
- if(this.active == state){
- return;
- }
-
- this.active = state;
-
- if (state) {
- this.el.addClass('active');
- return;
- }
-
- this.el.removeClass('active');
-
- return;
- },
-
- setDisabled : function(state)
- {
- if(this.disabled == state){
- return;
- }
-
- this.disabled = state;
-
- if (state) {
- this.el.addClass('disabled');
- return;
- }
-
- this.el.removeClass('disabled');
- },
-
- tooltipEl : function()
- {
- return this.el.select('.roo-navigation-bar-item-icon', true).first();;
- }
-});
-
-
- /*
* - LGPL
*
* FieldLabel
*/
/**
- * @class Roo.bootstrap.FieldLabel
+ * @class Roo.bootstrap.form.FieldLabel
* @extends Roo.bootstrap.Component
* Bootstrap FieldLabel class
* @cfg {String} html contents of the element
* @param {Object} config The config object
*/
-Roo.bootstrap.FieldLabel = function(config){
+Roo.bootstrap.form.FieldLabel = function(config){
Roo.bootstrap.Element.superclass.constructor.call(this, config);
this.addEvents({
});
};
-Roo.extend(Roo.bootstrap.FieldLabel, Roo.bootstrap.Component, {
+Roo.extend(Roo.bootstrap.form.FieldLabel, Roo.bootstrap.Component, {
tag: 'label',
cls: '',
this.indicator.addClass('invisible');
}
- Roo.bootstrap.FieldLabel.register(this);
+ Roo.bootstrap.form.FieldLabel.register(this);
},
indicatorEl : function()
});
-Roo.apply(Roo.bootstrap.FieldLabel, {
+Roo.apply(Roo.bootstrap.form.FieldLabel, {
groups: {},
/**
* register a FieldLabel Group
- * @param {Roo.bootstrap.FieldLabel} the FieldLabel to add
+ * @param {Roo.bootstrap.form.FieldLabel} the FieldLabel to add
*/
register : function(label)
{
/**
* fetch a FieldLabel Group based on the target
* @param {string} target
- * @returns {Roo.bootstrap.FieldLabel} the CheckBox group
+ * @returns {Roo.bootstrap.form.FieldLabel} the CheckBox group
*/
get: function(target) {
if (typeof(this.groups[target]) == 'undefined') {
/**
- * @class Roo.bootstrap.DateSplitField
+ * @class Roo.bootstrap.form.DateSplitField
* @extends Roo.bootstrap.Component
* Bootstrap DateSplitField class
* @cfg {string} fieldLabel - the label associated
* @param {Object} config The config object
*/
-Roo.bootstrap.DateSplitField = function(config){
- Roo.bootstrap.DateSplitField.superclass.constructor.call(this, config);
+Roo.bootstrap.form.DateSplitField = function(config){
+ Roo.bootstrap.form.DateSplitField.superclass.constructor.call(this, config);
this.addEvents({
// raw events
/**
* @event years
* getting the data of years
- * @param {Roo.bootstrap.DateSplitField} this
+ * @param {Roo.bootstrap.form.DateSplitField} this
* @param {Object} years
*/
"years" : true,
/**
* @event days
* getting the data of days
- * @param {Roo.bootstrap.DateSplitField} this
+ * @param {Roo.bootstrap.form.DateSplitField} this
* @param {Object} days
*/
"days" : true,
});
};
-Roo.extend(Roo.bootstrap.DateSplitField, Roo.bootstrap.Component, {
+Roo.extend(Roo.bootstrap.form.DateSplitField, Roo.bootstrap.Component, {
fieldLabel : '',
labelAlign : 'top',
{
var _this = this;
- Roo.bootstrap.NavProgressBar.superclass.onRender.call(this, ct, position);
+ Roo.bootstrap.DateSplitFiel.superclass.onRender.call(this, ct, position);
this.inputEl = this.el.select('.roo-date-split-field-group-value', true).first();
- this.dayField = new Roo.bootstrap.ComboBox({
+ this.dayField = new Roo.bootstrap.form.ComboBox({
allowBlank : this.dayAllowBlank,
alwaysQuery : true,
displayField : 'value',
this.dayField.render(this.el.select('.roo-date-split-field-day', true).first(), null);
- this.monthField = new Roo.bootstrap.MonthField({
+ this.monthField = new Roo.bootstrap.form.MonthField({
after : '<i class=\"fa fa-calendar\"></i>',
allowBlank : this.monthAllowBlank,
placeholder : this.monthPlaceholder,
this.monthField.render(this.el.select('.roo-date-split-field-month', true).first(), null);
- this.yearField = new Roo.bootstrap.ComboBox({
+ this.yearField = new Roo.bootstrap.form.ComboBox({
allowBlank : this.yearAllowBlank,
alwaysQuery : true,
displayField : 'value',
});
- /**
+
+
+/**
+ * @class Roo.bootstrap.LayoutMasonry
+ * @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.Element Roo.bootstrap.Img Roo.bootstrap.MasonryBrick
+ * Bootstrap Layout Masonry class
*
* This is based on
* http://masonry.desandro.com
* The idea is to render all the bricks based on vertical width...
*
* The original code extends 'outlayer' - we might need to use that....
- *
- */
-
-/**
- * @class Roo.bootstrap.LayoutMasonry
- * @extends Roo.bootstrap.Component
- * Bootstrap Layout Masonry class
- *
* @constructor
* Create a new Element
* @param {Object} config The config object
*/
/**
- * @class Roo.bootstrap.NumberField
- * @extends Roo.bootstrap.Input
+ * @class Roo.bootstrap.form.NumberField
+ * @extends Roo.bootstrap.form.Input
* Bootstrap NumberField class
*
*
* @param {Object} config The config object
*/
-Roo.bootstrap.NumberField = function(config){
- Roo.bootstrap.NumberField.superclass.constructor.call(this, config);
+Roo.bootstrap.form.NumberField = function(config){
+ Roo.bootstrap.form.NumberField.superclass.constructor.call(this, config);
};
-Roo.extend(Roo.bootstrap.NumberField, Roo.bootstrap.Input, {
+Roo.extend(Roo.bootstrap.form.NumberField, Roo.bootstrap.form.Input, {
/**
* @cfg {Boolean} allowDecimals False to disallow decimal values (defaults to true)
this.name = '';
- var cfg = Roo.bootstrap.NumberField.superclass.getAutoCreate.call(this);
+ var cfg = Roo.bootstrap.form.NumberField.superclass.getAutoCreate.call(this);
this.name = hiddenInput.name;
// private
initEvents : function()
{
- Roo.bootstrap.NumberField.superclass.initEvents.call(this);
+ Roo.bootstrap.form.NumberField.superclass.initEvents.call(this);
var allowed = "0123456789";
validateValue : function(value)
{
- if(!Roo.bootstrap.NumberField.superclass.validateValue.call(this, value)){
+ if(!Roo.bootstrap.form.NumberField.superclass.validateValue.call(this, value)){
return false;
}
*/
/**
- * @class Roo.bootstrap.RadioSet
- * @extends Roo.bootstrap.Input
+ * @class Roo.bootstrap.form.RadioSet
+ * @extends Roo.bootstrap.form.Input
+ * @children Roo.bootstrap.form.Radio
* Bootstrap RadioSet class
* @cfg {String} indicatorpos (left|right) default left
* @cfg {Boolean} inline (true|false) inline the element (default true)
* @param {Object} config The config object
*/
-Roo.bootstrap.RadioSet = function(config){
+Roo.bootstrap.form.RadioSet = function(config){
- Roo.bootstrap.RadioSet.superclass.constructor.call(this, config);
+ Roo.bootstrap.form.RadioSet.superclass.constructor.call(this, config);
this.radioes = [];
- Roo.bootstrap.RadioSet.register(this);
+ Roo.bootstrap.form.RadioSet.register(this);
this.addEvents({
/**
* @event check
* Fires when the element is checked or unchecked.
- * @param {Roo.bootstrap.RadioSet} this This radio
- * @param {Roo.bootstrap.Radio} item The checked item
+ * @param {Roo.bootstrap.form.RadioSet} this This radio
+ * @param {Roo.bootstrap.form.Radio} item The checked item
*/
check : true,
/**
* @event click
* Fires when the element is click.
- * @param {Roo.bootstrap.RadioSet} this This radio set
- * @param {Roo.bootstrap.Radio} item The checked item
+ * @param {Roo.bootstrap.form.RadioSet} this This radio set
+ * @param {Roo.bootstrap.form.Radio} item The checked item
* @param {Roo.EventObject} e The event object
*/
click : true
};
-Roo.extend(Roo.bootstrap.RadioSet, Roo.bootstrap.Input, {
+Roo.extend(Roo.bootstrap.form.RadioSet, Roo.bootstrap.form.Input, {
radioes : false,
});
-Roo.apply(Roo.bootstrap.RadioSet, {
+Roo.apply(Roo.bootstrap.form.RadioSet, {
groups: {},
* @type Number
*/
Roo.bootstrap.SplitBar.BOTTOM = 4;
-Roo.namespace("Roo.bootstrap.layout");/*
+/*
* Based on:
* Ext JS Library 1.1.1
* Copyright(c) 2006-2007, Ext JS, LLC.
/**
* @class Roo.bootstrap.layout.Manager
* @extends Roo.bootstrap.Component
+ * @abstract
* Base class for layout managers.
*/
Roo.bootstrap.layout.Manager = function(config)
{
+ this.monitorWindowResize = true; // do this before we apply configuration.
+
Roo.bootstrap.layout.Manager.superclass.constructor.call(this,config);
/** false to disable window resize monitoring @type Boolean */
- this.monitorWindowResize = true;
+
this.regions = {};
this.addEvents({
/**
/**
* @class Roo.bootstrap.layout.Border
* @extends Roo.bootstrap.layout.Manager
+ * @children Roo.bootstrap.panel.Content Roo.bootstrap.panel.Nest Roo.bootstrap.panel.Grid
+ * @parent builder Roo.bootstrap.panel.Nest Roo.bootstrap.panel.Nest Roo.bootstrap.Modal
* This class represents a common layout manager used in desktop applications. For screenshots and more details,
* please see: examples/bootstrap/nested.html<br><br>
Roo.extend(Roo.bootstrap.layout.Border, Roo.bootstrap.layout.Manager, {
+ /**
+ * @cfg {Roo.bootstrap.layout.Region} center region to go in center
+ */
+ /**
+ * @cfg {Roo.bootstrap.layout.Region} west region to go in west
+ */
+ /**
+ * @cfg {Roo.bootstrap.layout.Region} east region to go in east
+ */
+ /**
+ * @cfg {Roo.bootstrap.layout.Region} south region to go in south
+ */
+ /**
+ * @cfg {Roo.bootstrap.layout.Region} north region to go in north
+ */
+
+
+
+
parent : false, // this might point to a 'nest' or a ???
/**
}
Roo.bootstrap.layout.Region.prototype.updateBox.call(this, box);
}
-});Roo.namespace("Roo.bootstrap.panel");/*
+});/*
* Based on:
* Ext JS Library 1.1.1
* Copyright(c) 2006-2007, Ext JS, LLC.
* <script type="text/javascript">
*/
/**
- * @class Roo.ContentPanel
+ * @class Roo.bootstrap.paenl.Content
* @extends Roo.util.Observable
- * A basic ContentPanel element.
+ * @children Roo.bootstrap.Component
+ * @parent builder Roo.bootstrap.layout.Border
+ * A basic ContentPanel element. - a panel that contain any content (eg. forms etc.)
* @cfg {Boolean} fitToFrame True for this panel to adjust its size to fit when the region resizes (defaults to false)
* @cfg {Boolean} fitContainer When using {@link #fitToFrame} and {@link #resizeEl}, you can also fit the parent container (defaults to false)
* @cfg {Boolean/Object} autoCreate True to auto generate the DOM element for this panel, or a {@link Roo.DomHelper} config of the element to create
* @cfg {String} title The title for this panel
* @cfg {Array} adjustments Values to <b>add</b> to the width/height when doing a {@link #fitToFrame} (default is [0, 0])
* @cfg {String} url Calls {@link #setUrl} with this value
- * @cfg {String} region (center|north|south|east|west) which region to put this panel on (when used with xtype constructors)
+ * @cfg {String} region [required] (center|north|south|east|west) which region to put this panel on (when used with xtype constructors)
* @cfg {String/Object} params When used with {@link #url}, calls {@link #setUrl} with this value
* @cfg {Boolean} loadOnce When used with {@link #url}, calls {@link #setUrl} with this value
* @cfg {String} content Raw content to fill content panel with (uses setContent on construction.)
* @cfg {Boolean} badges render the badges
* @cfg {String} cls extra classes to use
* @cfg {String} background (primary|secondary|success|info|warning|danger|light|dark)
-
+
* @constructor
* Create a new ContentPanel.
- * @param {String/HTMLElement/Roo.Element} el The container element for this panel
* @param {String/Object} config A string to set only the title or a config object
- * @param {String} content (optional) Set the HTML content for this panel
- * @param {String} region (optional) Used by xtype constructors to add to regions. (values center,east,west,south,north)
+
*/
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
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() {
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);
this.el.update(content, loadScripts);
},
- ignoreResize : function(w, h){
+ ignoreResize : function(w, h)
+ {
+ //return false; // always resize?
if(this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
return true;
}else{
getChildContainer: function () {
return this.getEl();
+ },
+
+
+ onScroll : function(e)
+ {
+ this.fireEvent('scroll', this, e);
}
* @constructor
* Create a new GridPanel.
* @cfg {Roo.bootstrap.Table} grid The grid for this panel
+ * @cfg {Roo.bootstrap.nav.Simplebar} toolbar the toolbar at the top of the grid.
* @param {Object} config A the config object
*/
};
-Roo.extend(Roo.bootstrap.panel.Grid, Roo.bootstrap.panel.Content, {
+Roo.extend(Roo.bootstrap.panel.Grid, Roo.bootstrap.panel.Content,
+{
+
getId : function(){
return this.grid.id;
},
return this.grid;
},
- setSize : function(width, height){
- if(!this.ignoreResize(width, height)){
+ setSize : function(width, height)
+ {
+
+ //if(!this.ignoreResize(width, height)){
var grid = this.grid;
var size = this.adjustForComponents(width, height);
// tfoot is not a footer?
//}
grid.autoSize();
- }
+ //}
+
},
* Create a new Panel, that can contain a layout.Border.
*
*
- * @param {Roo.BorderLayout} layout The layout for this panel
* @param {String/Object} config A string to set only the title or a config object
*/
Roo.bootstrap.panel.Nest = function(config)
};
Roo.extend(Roo.bootstrap.panel.Nest, Roo.bootstrap.panel.Content, {
+ /**
+ * @cfg {Roo.BorderLayout} layout The layout for this panel
+ */
+ layout : false,
setSize : function(width, height){
if(!this.ignoreResize(width, height)){
* Availability: https://github.com/jackocnr/intl-tel-input.git
**/
-Roo.bootstrap.PhoneInputData = function() {
+Roo.bootstrap.form.PhoneInputData = function() {
var d = [
[
"Afghanistan (افغانستان)",
**/
/**
- * @class Roo.bootstrap.PhoneInput
- * @extends Roo.bootstrap.TriggerField
+ * @class Roo.bootstrap.form.PhoneInput
+ * @extends Roo.bootstrap.form.TriggerField
* An input with International dial-code selection
* @cfg {String} defaultDialCode default '+852'
* @param {Object} config Configuration options
*/
-Roo.bootstrap.PhoneInput = function(config) {
- Roo.bootstrap.PhoneInput.superclass.constructor.call(this, config);
+Roo.bootstrap.form.PhoneInput = function(config) {
+ Roo.bootstrap.form.PhoneInput.superclass.constructor.call(this, config);
};
-Roo.extend(Roo.bootstrap.PhoneInput, Roo.bootstrap.TriggerField, {
-
+Roo.extend(Roo.bootstrap.form.PhoneInput, Roo.bootstrap.form.TriggerField, {
+ /**
+ * @cfg {Roo.data.Store} store [required] The data store to which this combo is bound (defaults to undefined)
+ */
listWidth: undefined,
selectedClass: 'active',
getAutoCreate : function()
{
- var data = Roo.bootstrap.PhoneInputData();
+ var data = Roo.bootstrap.form.PhoneInputData();
var align = this.labelAlign || this.parentLabelAlign();
var id = Roo.id();
initEvents : function()
{
this.createList();
- Roo.bootstrap.PhoneInput.superclass.initEvents.call(this);
+ Roo.bootstrap.form.PhoneInput.superclass.initEvents.call(this);
this.indicator = this.indicatorEl();
this.flag = this.flagEl();
});
/**
- * @class Roo.bootstrap.MoneyField
- * @extends Roo.bootstrap.ComboBox
+ * @class Roo.bootstrap.form.MoneyField
+ * @extends Roo.bootstrap.form.ComboBox
* Bootstrap MoneyField class
*
* @constructor
* @param {Object} config Configuration options
*/
-Roo.bootstrap.MoneyField = function(config) {
+Roo.bootstrap.form.MoneyField = function(config) {
- Roo.bootstrap.MoneyField.superclass.constructor.call(this, config);
+ Roo.bootstrap.form.MoneyField.superclass.constructor.call(this, config);
};
-Roo.extend(Roo.bootstrap.MoneyField, Roo.bootstrap.ComboBox, {
+Roo.extend(Roo.bootstrap.form.MoneyField, Roo.bootstrap.form.ComboBox, {
/**
* @cfg {Boolean} allowDecimals False to disallow decimal values (defaults to true)
inputmd : 9,
inputsm : 9,
inputxs : 6,
-
+ /**
+ * @cfg {Roo.data.Store} store Store to lookup currency??
+ */
store : false,
getAutoCreate : function()
validateValue : function(value)
{
- if(!Roo.bootstrap.MoneyField.superclass.validateValue.call(this, value)){
+ if(!Roo.bootstrap.form.MoneyField.superclass.validateValue.call(this, value)){
return false;
}
-
\ No newline at end of file
+ // old names for form elements
+Roo.bootstrap.Form = Roo.bootstrap.form.Form;
+Roo.bootstrap.Input = Roo.bootstrap.form.Input;
+Roo.bootstrap.TextArea = Roo.bootstrap.form.TextArea;
+Roo.bootstrap.TriggerField = Roo.bootstrap.form.TriggerField;
+Roo.bootstrap.ComboBox = Roo.bootstrap.form.ComboBox;
+Roo.bootstrap.DateField = Roo.bootstrap.form.DateField;
+Roo.bootstrap.TimeField = Roo.bootstrap.form.TimeField;
+Roo.bootstrap.MonthField = Roo.bootstrap.form.MonthField;
+Roo.bootstrap.CheckBox = Roo.bootstrap.form.CheckBox;
+Roo.bootstrap.Radio = Roo.bootstrap.form.Radio;
+Roo.bootstrap.RadioSet = Roo.bootstrap.form.RadioSet;
+Roo.bootstrap.SecurePass = Roo.bootstrap.form.SecurePass;
+Roo.bootstrap.FieldLabel = Roo.bootstrap.form.FieldLabel;
+Roo.bootstrap.DateSplitField= Roo.bootstrap.form.DateSplitField;
+Roo.bootstrap.NumberField = Roo.bootstrap.form.NumberField;
+Roo.bootstrap.PhoneInput = Roo.bootstrap.form.PhoneInput;
+Roo.bootstrap.PhoneInputData= Roo.bootstrap.form.PhoneInputData;
+Roo.bootstrap.MoneyField = Roo.bootstrap.form.MoneyField;
+Roo.bootstrap.HtmlEditor = Roo.bootstrap.form.HtmlEditor;
+Roo.bootstrap.HtmlEditor.ToolbarStandard = Roo.bootstrap.form.HtmlEditorToolbarStandard;
+Roo.bootstrap.Markdown = Roo.bootstrap.form.Markdown;
+Roo.bootstrap.CardUploader = Roo.bootstrap.form.CardUploader;// depricated.
+Roo.bootstrap.Navbar = Roo.bootstrap.nav.Bar;
+Roo.bootstrap.NavGroup = Roo.bootstrap.nav.Group;
+Roo.bootstrap.NavHeaderbar = Roo.bootstrap.nav.Headerbar;
+Roo.bootstrap.NavItem = Roo.bootstrap.nav.Item;
+
+Roo.bootstrap.NavProgressBar = Roo.bootstrap.nav.ProgressBar;
+Roo.bootstrap.NavProgressBarItem = Roo.bootstrap.nav.ProgressBarItem;
+
+Roo.bootstrap.NavSidebar = Roo.bootstrap.nav.Sidebar;
+Roo.bootstrap.NavSidebarItem = Roo.bootstrap.nav.SidebarItem;
+
+Roo.bootstrap.NavSimplebar = Roo.bootstrap.nav.Simplebar;// deprciated
+Roo.bootstrap.Menu = Roo.bootstrap.menu.Menu;
+Roo.bootstrap.MenuItem = Roo.bootstrap.menu.Item;
+Roo.bootstrap.MenuSeparator = Roo.bootstrap.menu.Separator
+