roojs-bootstrap.js
[roojs1] / roojs-bootstrap-debug.js
index 55c528d..77cbd3d 100644 (file)
@@ -1,4 +1,18 @@
-/*
+/**
+ * set the version of bootstrap based on the stylesheet...
+ *
+ */
+
+Roo.bootstrap.version = (
+        function() {
+                var ret=3;
+                Roo.each(document.styleSheets[0], function(s) {
+                    if (s.href.match(/css-bootstrap4/)) {
+                        ret=4;
+                    }
+                });
+        return ret;
+})();/*
  * - LGPL
  *
  * base class for bootstrap elements.
@@ -540,6 +554,17 @@ Roo.extend(Roo.bootstrap.ButtonGroup, Roo.bootstrap.Component,  {
         }
         
         return cfg;
+    },
+    /**
+     * Add a button to the group (similar to NavItem API.)
+     */
+    addItem : function(cfg)
+    {
+        var cn = new Roo.bootstrap.Button(cfg);
+        //this.register(cn);
+        cn.parentId = this.id;
+        cn.onRender(this.el, null);
+        return cn;
     }
    
 });
@@ -556,13 +581,16 @@ Roo.extend(Roo.bootstrap.ButtonGroup, Roo.bootstrap.Component,  {
  * @extends Roo.bootstrap.Component
  * Bootstrap Button class
  * @cfg {String} html The button content
- * @cfg {String} weight (default | primary | success | info | warning | danger | link ) default 
+ * @cfg {String} weight (default | primary | secondary | success | info | warning | danger | link ) default
+ * @cfg {String} badge_weight (default | primary | secondary | success | info | warning | danger | link ) default (same as button)
+ * @cfg {Boolean} outline default false (except for weight=default which emulates old behaveiour with an outline)
  * @cfg {String} size ( lg | sm | xs)
  * @cfg {String} tag ( a | input | submit)
  * @cfg {String} href empty or href
  * @cfg {Boolean} disabled default false;
  * @cfg {Boolean} isClose default false;
- * @cfg {String} glyphicon (| adjust | align-center | align-justify | align-left | align-right | arrow-down | arrow-left | arrow-right | arrow-up | asterisk | backward | ban-circle | barcode | bell | bold | book | bookmark | briefcase | bullhorn | calendar | camera | certificate | check | chevron-down | chevron-left | chevron-right | chevron-up | circle-arrow-down | circle-arrow-left | circle-arrow-right | circle-arrow-up | cloud | cloud-download | cloud-upload | cog | collapse-down | collapse-up | comment | compressed | copyright-mark | credit-card | cutlery | dashboard | download | download-alt | earphone | edit | eject | envelope | euro | exclamation-sign | expand | export | eye-close | eye-open | facetime-video | fast-backward | fast-forward | file | film | filter | fire | flag | flash | floppy-disk | floppy-open | floppy-remove | floppy-save | floppy-saved | folder-close | folder-open | font | forward | fullscreen | gbp | gift | glass | globe | hand-down | hand-left | hand-right | hand-up | hd-video | hdd | header | headphones | heart | heart-empty | home | import | inbox | indent-left | indent-right | info-sign | italic | leaf | link | list | list-alt | lock | log-in | log-out | magnet | map-marker | minus | minus-sign | move | music | new-window | off | ok | ok-circle | ok-sign | open | paperclip | pause | pencil | phone | phone-alt | picture | plane | play | play-circle | plus | plus-sign | print | pushpin | qrcode | question-sign | random | record | refresh | registration-mark | remove | remove-circle | remove-sign | repeat | resize-full | resize-horizontal | resize-small | resize-vertical | retweet | road | save | saved | screenshot | sd-video | search | send | share | share-alt | shopping-cart | signal | sort | sort-by-alphabet | sort-by-alphabet-alt | sort-by-attributes | sort-by-attributes-alt | sort-by-order | sort-by-order-alt | sound-5-1 | sound-6-1 | sound-7-1 | sound-dolby | sound-stereo | star | star-empty | stats | step-backward | step-forward | stop | subtitles | tag | tags | tasks | text-height | text-width | th | th-large | th-list | thumbs-down | thumbs-up | time | tint | tower | transfer | trash | tree-conifer | tree-deciduous | unchecked | upload | usd | user | volume-down | volume-off | volume-up | warning-sign | wrench | zoom-in | zoom-out)
+ * @cfg {String} glyphicon depricated - use fa
+ * @cfg {String} fa fontawesome icon - eg. 'comment' - without the fa/fas etc..
  * @cfg {String} badge text for badge
  * @cfg {String} theme (default|glow)  
  * @cfg {Boolean} inverse dark themed version
@@ -582,7 +610,7 @@ Roo.extend(Roo.bootstrap.ButtonGroup, Roo.bootstrap.Component,  {
 
 Roo.bootstrap.Button = function(config){
     Roo.bootstrap.Button.superclass.constructor.call(this, config);
-    this.weightClass = ["btn-default", 
+    this.weightClass = ["btn-default btn-outline-secondary", 
                        "btn-primary", 
                        "btn-success", 
                        "btn-info", 
@@ -614,12 +642,15 @@ Roo.extend(Roo.bootstrap.Button, Roo.bootstrap.Component,  {
     html: false,
     active: false,
     weight: '',
+    badge_weight: '',
+    outline : false,
     size: '',
     tag: 'button',
     href: '',
     disabled: false,
     isClose: false,
     glyphicon: '',
+    fa: '',
     badge: '',
     theme: 'default',
     inverse: false,
@@ -667,7 +698,7 @@ Roo.extend(Roo.bootstrap.Button, Roo.bootstrap.Component,  {
                 ]
             };
             
-            if (['default', 'primary', 'success', 'info', 'warning', 'danger', 'link'].indexOf(this.weight) > -1) {
+            if (['default', 'secondary' , 'primary', 'success', 'info', 'warning', 'danger', 'link'].indexOf(this.weight) > -1) {
                 cfg.cls += ' '+this.weight;
             }
             
@@ -691,9 +722,15 @@ Roo.extend(Roo.bootstrap.Button, Roo.bootstrap.Component,  {
             //if (this.parentType != 'Navbar') {
             this.weight = this.weight.length ?  this.weight : 'default';
             //}
-            if (['default', 'primary', 'success', 'info', 'warning', 'danger', 'link'].indexOf(this.weight) > -1) {
+            if (['default', 'primary', 'secondary', 'success', 'info', 'warning', 'danger', 'link'].indexOf(this.weight) > -1) {
                 
-                cfg.cls += ' btn-' + this.weight;
+                var outline = this.outline || this.weight == 'default' ? 'outline-' : '';
+                var weight = this.weight == 'default' ? 'secondary' : this.weight;
+                cfg.cls += ' btn-' + outline + weight;
+                if (this.weight == 'default') {
+                    // BC
+                    cfg.cls += ' btn-' + this.weight;
+                }
             }
         } else if (this.theme==='glow') {
             
@@ -724,6 +761,10 @@ Roo.extend(Roo.bootstrap.Button, Roo.bootstrap.Component,  {
             Roo.log('changing to ul' );
             cfg.tag = 'ul';
             this.glyphicon = 'caret';
+            if (Roo.bootstrap.version == 4) {
+                this.fa = 'caret-down';
+            }
+            
         }
         
         cfg.cls += this.size.length ? (' btn-' + this.size) : '';
@@ -762,6 +803,16 @@ Roo.extend(Roo.bootstrap.Button, Roo.bootstrap.Component,  {
                 }
             ];
         }
+        if (this.fa) {
+            cfg.html = ' ' + cfg.html;
+            
+            cfg.cn = [
+                {
+                    tag: 'i',
+                    cls: 'fa fas fa-' + this.fa
+                }
+            ];
+        }
         
         if (this.badge) {
             cfg.html += ' ';
@@ -776,18 +827,28 @@ Roo.extend(Roo.bootstrap.Button, Roo.bootstrap.Component,  {
             
             if(this.glyphicon){
                 value = {
-                            tag: 'span',
-                            cls: 'glyphicon glyphicon-' + this.glyphicon,
-                            html: this.html
-                        };
-                
+                    tag: 'span',
+                    cls: 'glyphicon glyphicon-' + this.glyphicon,
+                    html: this.html
+                };
             }
+            if(this.fa){
+                value = {
+                    tag: 'i',
+                    cls: 'fa fas fa-' + this.fa,
+                    html: this.html
+                };
+            }
+            
+            var bw = this.badge_weight.length ? this.badge_weight :
+                (this.weight.length ? this.weight : 'secondary');
+            bw = bw == 'default' ? 'secondary' : bw;
             
             cfg.cn = [
                 value,
                 {
                     tag: 'span',
-                    cls: 'badge',
+                    cls: 'badge badge-' + bw,
                     html: this.badge
                 }
             ];
@@ -921,7 +982,13 @@ Roo.extend(Roo.bootstrap.Button, Roo.bootstrap.Component,  {
     setWeight : function(str)
     {
        this.el.removeClass(this.weightClass);
-        this.el.addClass('btn-' + str);        
+        this.weight = str;
+        var outline = this.outline ? 'outline-' : '';
+        if (str == 'default') {
+            this.el.addClass('btn-default btn-outline-secondary');        
+            return;
+        }
+        this.el.addClass('btn-' + outline + str);        
     }
     
     
@@ -1988,6 +2055,8 @@ Roo.bootstrap.Menu = function(config){
     if (this.registerMenu && this.type != 'treeview')  {
         Roo.bootstrap.MenuMgr.register(this);
     }
+    
+    
     this.addEvents({
         /**
          * @event beforeshow
@@ -2105,8 +2174,13 @@ Roo.extend(Roo.bootstrap.Menu, Roo.bootstrap.Component,  {
         
         this.triggerEl.on(Roo.isTouch ? 'touchstart' : 'mouseup', this.onTriggerPress, this);
         
-        this.triggerEl.addClass('dropdown-toggle');
-        
+       
+       if (this.triggerEl.hasClass('nav-item')) {
+           // dropdown toggle on the 'a' in BS4?
+           this.triggerEl.select('.nav-link',true).first().addClass('dropdown-toggle');
+       } else {
+           this.triggerEl.addClass('dropdown-toggle');
+       }
         if (Roo.isTouch) {
             this.el.on('touchstart'  , this.onTouch, this);
         }
@@ -2241,6 +2315,7 @@ Roo.extend(Roo.bootstrap.Menu, Roo.bootstrap.Component,  {
         this.hideMenuItems();
         this.hidden = false;
         this.triggerEl.addClass('open');
+       this.el.addClass('show');
         
         // reassign x when hitting right
         if(this.el.getWidth() + xy[0] >= Roo.lib.Dom.getViewWidth()){
@@ -2290,6 +2365,7 @@ Roo.extend(Roo.bootstrap.Menu, Roo.bootstrap.Component,  {
                 this.activeItem = null;
             }
             this.triggerEl.removeClass('open');;
+           this.el.removeClass('show');
             this.hidden = true;
             this.fireEvent("hide", this);
         }
@@ -2438,7 +2514,7 @@ Roo.extend(Roo.bootstrap.MenuItem, Roo.bootstrap.Component,  {
         if(this.isContainer){
             return {
                 tag: 'li',
-                cls: 'dropdown-menu-item'
+                cls: 'dropdown-menu-item '
             };
         }
         var ctag = {
@@ -2448,6 +2524,7 @@ Roo.extend(Roo.bootstrap.MenuItem, Roo.bootstrap.Component,  {
         
         var anc = {
             tag : 'a',
+            cls : 'dropdown-item',
             href : '#',
             cn : [  ]
         };
@@ -2736,7 +2813,7 @@ Roo.extend(Roo.bootstrap.Modal, Roo.bootstrap.Component,  {
         };
 
         var header = [];
-        if (this.allow_close) {
+        if (this.allow_close && Roo.bootstrap.version == 3) {
             header.push({
                 tag: 'button',
                 cls : 'close',
@@ -2746,6 +2823,14 @@ Roo.extend(Roo.bootstrap.Modal, Roo.bootstrap.Component,  {
 
         header.push(title);
 
+        if (this.allow_close && Roo.bootstrap.version == 4) {
+            header.push({
+                tag: 'button',
+                cls : 'close',
+                html : '&times'
+            });
+        }
+        
         var size = '';
 
         if(this.size.length){
@@ -2878,15 +2963,19 @@ Roo.extend(Roo.bootstrap.Modal, Roo.bootstrap.Component,  {
         }
 
         //this.el.setStyle('display', 'block');
-        this.el.removeClass('hideing');        
-        this.el.addClass('show');
+        this.el.removeClass('hideing');
+        this.el.dom.style.display='block';
+        
+        Roo.get(document.body).addClass('modal-open');
  
         if(this.animate){  // element has 'fade'  - so stuff happens after .3s ?- not sure why the delay?
             var _this = this;
             (function(){
+                this.el.addClass('show');
                 this.el.addClass('in');
             }).defer(50, this);
         }else{
+            this.el.addClass('show');
             this.el.addClass('in');
         }
 
@@ -2899,8 +2988,10 @@ Roo.extend(Roo.bootstrap.Modal, Roo.bootstrap.Component,  {
         
         this.maskEl.setSize(Roo.lib.Dom.getViewWidth(true),   Roo.lib.Dom.getViewHeight(true));
         this.maskEl.setStyle('z-index', Roo.bootstrap.Modal.zIndex++);
+        this.maskEl.dom.style.display = 'block';
         this.maskEl.addClass('show');
         
+        
         this.resize();
         
         this.fireEvent('show', this);
@@ -2919,23 +3010,33 @@ Roo.extend(Roo.bootstrap.Modal, Roo.bootstrap.Component,  {
     hide : function()
     {
         if(this.fireEvent("beforehide", this) !== false){
+            
             this.maskEl.removeClass('show');
+            
+            this.maskEl.dom.style.display = '';
             Roo.get(document.body).removeClass("x-body-masked");
             this.el.removeClass('in');
             this.el.select('.modal-dialog', true).first().setStyle('transform','');
 
             if(this.animate){ // why
                 this.el.addClass('hideing');
+                this.el.removeClass('show');
                 (function(){
                     if (!this.el.hasClass('hideing')) {
                         return; // it's been shown again...
                     }
-                    this.el.removeClass('show');
+                    
+                    this.el.dom.style.display='';
+
+                    Roo.get(document.body).removeClass('modal-open');
                     this.el.removeClass('hideing');
                 }).defer(150,this);
                 
             }else{
-                 this.el.removeClass('show');
+                this.el.removeClass('show');
+                this.el.dom.style.display='';
+                Roo.get(document.body).removeClass('modal-open');
+
             }
             this.fireEvent('hide', this);
         }
@@ -3762,7 +3863,41 @@ Roo.extend(Roo.bootstrap.Navbar, Roo.bootstrap.Component,  {
         //Roo.log(this.el.select('.navbar-toggle',true));
         this.el.select('.navbar-toggle',true).on('click', function() {
             if(this.fireEvent('beforetoggle', this) !== false){
-               this.el.select('.navbar-collapse',true).toggleClass('in');                                 
+                var ce = this.el.select('.navbar-collapse',true).first();
+                ce.toggleClass('in'); // old...
+                if (ce.hasClass('collapse')) {
+                    // show it...
+                    ce.removeClass('collapse');
+                    ce.addClass('show');
+                    var h = ce.getHeight();
+                    Roo.log(h);
+                    ce.removeClass('show');
+                    // at this point we should be able to see it..
+                    ce.addClass('collapsing');
+                    
+                    ce.setHeight(0); // resize it ...
+                    ce.on('transitionend', function() {
+                        Roo.log('done transition');
+                        ce.removeClass('collapsing');
+                        ce.addClass('show');
+                        ce.removeClass('collapse');
+
+                        ce.dom.style.height = '';
+                    }, this, { single: true} );
+                    ce.setHeight(h);
+                    
+                } else {
+                    ce.setHeight(ce.getHeight());
+                    ce.removeClass('show');
+                    ce.addClass('collapsing');
+                    
+                    ce.on('transitionend', function() {
+                        ce.dom.style.height = '';
+                        ce.removeClass('collapsing');
+                        ce.addClass('collapse');
+                    }, this, { single: true} );
+                    ce.setHeight(0);
+                }
             }
             
         }, this);
@@ -3836,7 +3971,7 @@ Roo.extend(Roo.bootstrap.Navbar, Roo.bootstrap.Component,  {
  * 
  * @cfg {String} tag (header|footer|nav|div) default is nav 
 
- * 
+ * @cfg {String} weight (light|primary|secondary|success|danger|warning|info|dark|white) default is light.
  * 
  * 
  * @constructor
@@ -3857,7 +3992,7 @@ Roo.extend(Roo.bootstrap.NavSimplebar, Roo.bootstrap.Navbar,  {
     arrangement: '',
     align : false,
     
-    
+    weight : 'light',
     
     main : false,
     
@@ -3870,8 +4005,13 @@ Roo.extend(Roo.bootstrap.NavSimplebar, Roo.bootstrap.Navbar,  {
         
         var cfg = {
             tag : this.tag || 'div',
-            cls : 'navbar'
+            cls : 'navbar navbar-expand-lg'
         };
+       if (['light','white'].indexOf(this.weight) > -1) {
+           cfg.cls += ['light','white'].indexOf(this.weight) > -1 ? ' navbar-light' : ' navbar-dark';
+       }
+       cfg.cls += ' bg-' + this.weight;
+       
          
        
         cfg.cn = [
@@ -3930,7 +4070,8 @@ Roo.extend(Roo.bootstrap.NavSimplebar, Roo.bootstrap.Navbar,  {
  * - LGPL
  *
  * navbar
- * 
+ * navbar-fixed-top
+ * navbar-expand-md  fixed-top 
  */
 
 /**
@@ -3971,7 +4112,7 @@ Roo.extend(Roo.bootstrap.NavHeaderbar, Roo.bootstrap.NavSimplebar,  {
         
         var   cfg = {
             tag: this.nav || 'nav',
-            cls: 'navbar',
+            cls: 'navbar navbar-expand-md',
             role: 'navigation',
             cn: []
         };
@@ -3983,36 +4124,38 @@ Roo.extend(Roo.bootstrap.NavHeaderbar, Roo.bootstrap.NavSimplebar,  {
         }
         
         if(this.srButton){
-            cn.push({
-                tag: 'div',
-                cls: 'navbar-header',
+            var btn = {
+                tag: 'button',
+                type: 'button',
+                cls: 'navbar-toggle navbar-toggler',
+                'data-toggle': 'collapse',
                 cn: [
                     {
-                        tag: 'button',
-                        type: 'button',
-                        cls: 'navbar-toggle',
-                        'data-toggle': 'collapse',
-                        cn: [
-                            {
-                                tag: 'span',
-                                cls: 'sr-only',
-                                html: 'Toggle navigation'
-                            },
-                            {
-                                tag: 'span',
-                                cls: 'icon-bar'
-                            },
-                            {
-                                tag: 'span',
-                                cls: 'icon-bar'
-                            },
-                            {
-                                tag: 'span',
-                                cls: 'icon-bar'
-                            }
-                        ]
+                        tag: 'span',
+                        cls: 'sr-only',
+                        html: 'Toggle navigation'
+                    },
+                    {
+                        tag: 'span',
+                        cls: 'icon-bar navbar-toggler-icon'
+                    },
+                    {
+                        tag: 'span',
+                        cls: 'icon-bar'
+                    },
+                    {
+                        tag: 'span',
+                        cls: 'icon-bar'
                     }
                 ]
+            };
+            
+            cn.push( Roo.bootstrap.version == 4 ? btn : {
+                tag: 'div',
+                cls: 'navbar-header',
+                cn: [
+                    btn
+                ]
             });
         }
         
@@ -4022,10 +4165,10 @@ Roo.extend(Roo.bootstrap.NavHeaderbar, Roo.bootstrap.NavSimplebar,  {
             cn : []
         });
         
-        cfg.cls += this.inverse ? ' navbar-inverse' : ' navbar-default';
+        cfg.cls += this.inverse ? ' navbar-inverse navbar-dark bg-dark' : ' navbar-default';
         
         if (['fixed-top','fixed-bottom','static-top'].indexOf(this.position)>-1) {
-            cfg.cls += ' navbar-' + this.position;
+            cfg.cls += ' navbar-' + this.position + ' ' + this.position ;
             
             // tag can override this..
             
@@ -4033,7 +4176,8 @@ Roo.extend(Roo.bootstrap.NavHeaderbar, Roo.bootstrap.NavSimplebar,  {
         }
         
         if (this.brand !== '') {
-            cn[0].cn.push({
+            var cp =  Roo.bootstrap.version == 4 ? cn : cn[0].cn;
+            cp.unshift({ // changed from push ?? BS4 needs it at the start? - does this break or exsiting?
                 tag: 'a',
                 href: this.brand_href ? this.brand_href : '#',
                 cls: 'navbar-brand',
@@ -4225,15 +4369,17 @@ Roo.extend(Roo.bootstrap.NavGroup, Roo.bootstrap.Component,  {
             };
             
             if (this.align === 'right') {
-                cfg.cls += ' navbar-right';
+                cfg.cls += ' navbar-right ml-md-auto';
             } else {
                 cfg.cls += ' navbar-left';
             }
         }
         
         if (this.align === 'right') {
-            cfg.cls += ' navbar-right';
-        }
+            cfg.cls += ' navbar-right ml-md-auto';
+        } else {
+           cfg.cls += ' mr-auto';
+       }
         
         if (this.inverse) {
             cfg.cls += ' navbar-inverse';
@@ -4435,8 +4581,9 @@ Roo.apply(Roo.bootstrap.NavGroup, {
  * @cfg {String} html content of button
  * @cfg {String} badge text inside badge
  * @cfg {String} badgecls (bg-green|bg-red|bg-yellow)the extra classes for the badge
- * @cfg {String} glyphicon name of glyphicon
- * @cfg {String} icon name of font awesome icon
+ * @cfg {String} glyphicon DEPRICATED - use fa
+ * @cfg {String} icon DEPRICATED - use fa
+ * @cfg {String} fa - Fontawsome icon name (can add stuff to it like fa-2x)
  * @cfg {Boolean} active Is item active
  * @cfg {Boolean} disabled Is item disabled
  
@@ -4486,6 +4633,7 @@ Roo.extend(Roo.bootstrap.NavItem, Roo.bootstrap.Component,  {
     html: '',
     badge: '',
     icon: false,
+    fa : false,
     glyphicon: false,
     active: false,
     preventDefault : false,
@@ -4510,7 +4658,7 @@ Roo.extend(Roo.bootstrap.NavItem, Roo.bootstrap.Component,  {
             cfg.cls += ' disabled';
         }
         
-        if (this.href || this.html || this.glyphicon || this.icon) {
+        if (this.href || this.html || this.glyphicon || this.icon || this.fa) {
             cfg.cn = [
                 {
                     tag: this.tagtype,
@@ -4518,11 +4666,15 @@ Roo.extend(Roo.bootstrap.NavItem, Roo.bootstrap.Component,  {
                     html: this.html || ''
                 }
             ];
-            
+            if (this.tagtype == 'a') {
+               cfg.cn[0].cls = 'nav-link';
+           }
             if (this.icon) {
                 cfg.cn[0].html = '<i class="'+this.icon+'"></i> <span>' + cfg.cn[0].html + '</span>'
             }
-
+           if (this.fa) {
+                cfg.cn[0].html = '<i class="fa fas fa-'+this.fa+'"></i> <span>' + cfg.cn[0].html + '</span>'
+            }
             if(this.glyphicon) {
                 cfg.cn[0].html = '<span class="glyphicon glyphicon-' + this.glyphicon + '"></span> '  + cfg.cn[0].html;
             }
@@ -4535,7 +4687,7 @@ Roo.extend(Roo.bootstrap.NavItem, Roo.bootstrap.Component,  {
             
             if (this.badge !== '') {
                  
-                cfg.cn[0].html += ' <span class="badge">' + this.badge + '</span>';
+                cfg.cn[0].html += ' <span class="badge badge-secondary">' + this.badge + '</span>';
             }
         }
         
@@ -7919,7 +8071,7 @@ Roo.extend(Roo.bootstrap.Form, Roo.bootstrap.Component,  {
             cls : ''
         };
         if (this.parent().xtype.match(/^Nav/)) {
-            cfg.cls = 'navbar-form navbar-' + this.align;
+            cfg.cls = 'navbar-form form-inline navbar-' + this.align;
 
         }
 
@@ -9031,7 +9183,7 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
                 
                 inputblock.cn.push({
                     tag :'span',
-                    cls : 'roo-input-before input-group-addon',
+                    cls : 'roo-input-before input-group-addon input-group-prepend input-group-text',
                     html : this.before
                 });
             }
@@ -9040,7 +9192,7 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
                 
                 inputblock.cn.push({
                     tag :'span',
-                    cls : 'roo-input-before input-group-' +
+                    cls : 'roo-input-before input-group-prepend input-group-text input-group-' +
                         (this.before.xtype == 'Button' ? 'btn' : 'addon')  //?? what about checkboxes - that looks like a bit of a hack thought? 
                 });
             }
@@ -9050,7 +9202,7 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
             if (this.after && typeof(this.after) == 'string') {
                 inputblock.cn.push({
                     tag :'span',
-                    cls : 'roo-input-after input-group-addon',
+                    cls : 'roo-input-after input-group-append input-group-text input-group-addon',
                     html : this.after
                 });
             }
@@ -9059,7 +9211,7 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
                 
                 inputblock.cn.push({
                     tag :'span',
-                    cls : 'roo-input-after input-group-' +
+                    cls : 'roo-input-after input-group-append input-group-text input-group-' +
                         (this.after.xtype == 'Button' ? 'btn' : 'addon')  //?? what about checkboxes - that looks like a bit of a hack thought? 
                 });
             }
@@ -9069,21 +9221,27 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
                 inputblock.cn.push(feedback);
             }
         };
-        
+        var indicator = {
+            tag : 'i',
+            cls : 'roo-required-indicator ' + (this.indicatorpos == 'right'  ? 'right' : 'left') +'-indicator text-danger fa fa-lg fa-star',
+            tooltip : 'This field is required'
+        };
+        if (Roo.bootstrap.version == 4) {
+            indicator = {
+                tag : 'i',
+                style : 'display-none'
+            };
+        }
         if (align ==='left' && this.fieldLabel.length) {
             
-            cfg.cls += ' roo-form-group-label-left';
+            cfg.cls += ' roo-form-group-label-left'  + (Roo.bootstrap.version == 4 ? ' row' : '');
             
             cfg.cn = [
-                {
-                    tag : 'i',
-                    cls : 'roo-required-indicator left-indicator text-danger fa fa-lg fa-star',
-                    tooltip : 'This field is required'
-                },
+                indicator,
                 {
                     tag: 'label',
                     'for' :  id,
-                    cls : 'control-label',
+                    cls : 'control-label col-form-label',
                     html : this.fieldLabel
 
                 },
@@ -9103,17 +9261,13 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
                     {
                         tag: 'label',
                         'for' :  id,
-                        cls : 'control-label',
+                        cls : 'control-label col-form-label',
                         cn : [
                             {
                                 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'
-                            }
+                            indicator
                         ]
                     },
                     {
@@ -9237,6 +9391,10 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
     
     indicatorEl : function()
     {
+        if (Roo.bootstrap.version == 4) {
+            return false; // not enabled in v4 yet.
+        }
+        
         var indicator = this.el.select('i.roo-required-indicator',true).first();
         
         if(!indicator){
@@ -9722,7 +9880,7 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
             return;
         }
         
-        if(this.indicator){
+        if(this.indicatorEl()){
             var ar = this.el.select('label > span',true);
             
             if (ar.elements.length) {
@@ -10267,7 +10425,7 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
             if (this.before) {
                 inputblock.cn.push({
                     tag :'span',
-                    cls : 'input-group-addon',
+                    cls : 'input-group-addon input-group-prepend input-group-text',
                     html : this.before
                 });
             }
@@ -10282,62 +10440,44 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
             if (this.after) {
                 inputblock.cn.push({
                     tag :'span',
-                    cls : 'input-group-addon',
+                    cls : 'input-group-addon input-group-append input-group-text',
                     html : this.after
                 });
             }
             
         };
         
-        var box = {
-            tag: 'div',
-            cn: [
-                {
-                    tag: 'input',
-                    type : 'hidden',
-                    cls: 'form-hidden-field'
-                },
-                inputblock
-            ]
-            
-        };
+      
+        
+        var ibwrap = inputblock;
         
         if(this.multiple){
-            box = {
-                tag: 'div',
-                cn: [
-                    {
-                        tag: 'input',
-                        type : 'hidden',
-                        cls: 'form-hidden-field'
-                    },
+            ibwrap = {
+                tag: 'ul',
+                cls: 'roo-select2-choices',
+                cn:[
                     {
-                        tag: 'ul',
-                        cls: 'roo-select2-choices',
-                        cn:[
-                            {
-                                tag: 'li',
-                                cls: 'roo-select2-search-field',
-                                cn: [
+                        tag: 'li',
+                        cls: 'roo-select2-search-field',
+                        cn: [
 
-                                    inputblock
-                                ]
-                            }
+                            inputblock
                         ]
                     }
                 ]
-            }
-        };
+            };
+                
+        }
         
         var combobox = {
             cls: 'roo-select2-container input-group',
             cn: [
-                box
-//                {
-//                    tag: 'ul',
-//                    cls: 'typeahead typeahead-long dropdown-menu',
-//                    style: 'display:none'
-//                }
+                 {
+                    tag: 'input',
+                    type : 'hidden',
+                    cls: 'form-hidden-field'
+                },
+                ibwrap
             ]
         };
         
@@ -10357,7 +10497,7 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
             
             combobox.cn.push({
                 tag :'span',
-                cls : 'input-group-addon btn dropdown-toggle',
+                cls : 'input-group-addon input-group-append input-group-text btn dropdown-toggle',
                 cn : [
                     caret,
                     {
@@ -10378,17 +10518,25 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
         if(this.multiple){
             combobox.cls += ' roo-select2-container-multi';
         }
+         var indicator = {
+            tag : 'i',
+            cls : 'roo-required-indicator ' + (this.indicatorpos == 'right'  ? 'right' : 'left') +'-indicator text-danger fa fa-lg fa-star',
+            tooltip : 'This field is required'
+        };
+        if (Roo.bootstrap.version == 4) {
+            indicator = {
+                tag : 'i',
+                style : 'display:none'
+            };
+        }
+        
         
         if (align ==='left' && this.fieldLabel.length) {
             
-            cfg.cls += ' roo-form-group-label-left';
+            cfg.cls += ' roo-form-group-label-left'  + (Roo.bootstrap.version == 4 ? ' row' : '');
 
             cfg.cn = [
-                {
-                    tag : 'i',
-                    cls : 'roo-required-indicator left-indicator text-danger fa fa-lg fa-star',
-                    tooltip : 'This field is required'
-                },
+                indicator,
                 {
                     tag: 'label',
                     'for' :  id,
@@ -10419,11 +10567,7 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
                                 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'
-                            }
+                            indicator
                         ]
                     },
                     {
@@ -10470,11 +10614,7 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
         } else if ( this.fieldLabel.length) {
 //                Roo.log(" label");
             cfg.cn = [
-                {
-                   tag : 'i',
-                   cls : 'roo-required-indicator left-indicator text-danger fa fa-lg fa-star',
-                   tooltip : 'This field is required'
-               },
+                indicator,
                {
                    tag: 'label',
                    //cls : 'input-group-addon',
@@ -10496,11 +10636,7 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
                                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'
-                           }
+                           indicator
                        ]
 
                     },
@@ -10614,7 +10750,7 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
     createList : function()
     {
         this.list = Roo.get(document.body).createChild({
-            tag: 'ul',
+            tag: Roo.bootstrap.version == 4 ? 'div' : 'ul',
             cls: 'typeahead typeahead-long dropdown-menu',
             style: 'display:none'
         });
@@ -13238,6 +13374,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
         
         var box = {
             tag: 'div',
+            style : 'display: contents',
             cn: [
                 {
                     tag: 'input',
@@ -13263,6 +13400,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
         var combobox = {
             cls: 'roo-select2-container input-group roo-select2-container-multi',
             cn: [
+                
                 box
 //                {
 //                    tag: 'ul',
@@ -13282,21 +13420,27 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
             combobox.cn.push(feedback);
         }
         
-        
+        var indicator = {
+            tag : 'i',
+            cls : 'roo-required-indicator ' + (this.indicatorpos == 'right'  ? 'right' : 'left') +'-indicator text-danger fa fa-lg fa-star',
+            tooltip : 'This field is required'
+        };
+        if (Roo.bootstrap.version == 4) {
+            indicator = {
+                tag : 'i',
+                style : 'display:none'
+            };
+        }
         if (align ==='left' && this.fieldLabel.length) {
             
-            cfg.cls += ' roo-form-group-label-left';
+            cfg.cls += ' roo-form-group-label-left'  + (Roo.bootstrap.version == 4 ? ' row' : '');
             
             cfg.cn = [
-                {
-                    tag : 'i',
-                    cls : 'roo-required-indicator left-indicator text-danger fa fa-lg fa-star',
-                    tooltip : 'This field is required'
-                },
+                indicator,
                 {
                     tag: 'label',
                     'for' :  id,
-                    cls : 'control-label',
+                    cls : 'control-label col-form-label',
                     html : this.fieldLabel
 
                 },
@@ -13319,17 +13463,13 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
                     {
                         tag: 'label',
                         'for' :  id,
-                        cls : 'control-label',
+                        cls : 'control-label col-form-label',
                         cn : [
                             {
                                 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'
-                            }
+                            indicator
                         ]
                     },
                     {
@@ -13380,11 +13520,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
         } else if ( this.fieldLabel.length) {
 //                Roo.log(" label");
                  cfg.cn = [
-                    {
-                        tag : 'i',
-                        cls : 'roo-required-indicator left-indicator text-danger fa fa-lg fa-star',
-                        tooltip : 'This field is required'
-                    },
+                   indicator,
                     {
                         tag: 'label',
                         //cls : 'input-group-addon',
@@ -13400,11 +13536,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
                             //cls : 'input-group-addon',
                             html : this.fieldLabel
                         },
-                        {
-                            tag : 'i',
-                            cls : 'roo-required-indicator right-indicator text-danger fa fa-lg fa-star',
-                            tooltip : 'This field is required'
-                        },
+                        indicator,
                         combobox
                     ];
                     
@@ -13565,7 +13697,9 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
         */
             
         if(!this.tpl){
-            this.tpl = '<li><a href="#">{' + this.displayField + '}</a></li>';
+            this.tpl = Roo.bootstrap.version == 4 ?
+                '<a class="dropdown-item" href="#">{' + this.displayField + '}</a>' :  // 4 does not need <li> and it get's really confisued.
+                '<li><a class="dropdown-item" href="#">{' + this.displayField + '}</a></li>';
         }
 
         this.view = new Roo.View(this.list, this.tpl, {
@@ -15002,7 +15136,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
             
             inputblock.cn.unshift({
                 tag :'span',
-                cls : 'input-group-addon',
+                cls : 'input-group-addon input-group-prepend input-group-text',
                 html : this.before
             });
         }
@@ -15034,55 +15168,42 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
             
             inputblock.cn.push({
                 tag :'span',
-                cls : 'input-group-addon',
+                cls : 'input-group-addon input-group-append input-group-text',
                 html : this.after
             });
         }
 
-        var box = {
-            tag: 'div',
-            cn: [
-                {
-                    tag: 'input',
-                    type : 'hidden',
-                    cls: 'form-hidden-field'
-                },
-                inputblock
-            ]
-            
-        };
+        
+        var ibwrap = inputblock;
         
         if(this.multiple){
-            box = {
-                tag: 'div',
-                cn: [
-                    {
-                        tag: 'input',
-                        type : 'hidden',
-                        cls: 'form-hidden-field'
-                    },
+            ibwrap = {
+                tag: 'ul',
+                cls: 'roo-select2-choices',
+                cn:[
                     {
-                        tag: 'ul',
-                        cls: 'roo-select2-choices',
-                        cn:[
-                            {
-                                tag: 'li',
-                                cls: 'roo-select2-search-field',
-                                cn: [
+                        tag: 'li',
+                        cls: 'roo-select2-search-field',
+                        cn: [
 
-                                    inputblock
-                                ]
-                            }
+                            inputblock
                         ]
                     }
                 ]
-            }
-        };
+            };
+        
+            
+        }
         
         var combobox = {
             cls: 'roo-select2-container input-group roo-touchview-combobox ',
             cn: [
-                box
+                {
+                    tag: 'input',
+                    type : 'hidden',
+                    cls: 'form-hidden-field'
+                },
+                ibwrap
             ]
         };
         
@@ -15103,7 +15224,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
             
             combobox.cn.push({
                 tag :'span',
-                cls : 'input-group-addon btn dropdown-toggle',
+                cls : 'input-group-addon input-group-append input-group-text btn dropdown-toggle',
                 cn : [
                     caret,
                     {
@@ -15137,7 +15258,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
                 },
                 {
                     tag: 'label',
-                    cls : 'control-label',
+                    cls : 'control-label col-form-label',
                     html : this.fieldLabel
 
                 },
@@ -15158,7 +15279,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
                     {
                         tag: 'label',
                         'for' :  id,
-                        cls : 'control-label',
+                        cls : 'control-label col-form-label',
                         cn : [
                             {
                                 tag : 'span',
@@ -17582,11 +17703,11 @@ Roo.extend(Roo.bootstrap.Popover, Roo.bootstrap.Component,  {
                     cn : [
                         {
                             tag: 'h3',
-                            cls: 'popover-title',
+                            cls: 'popover-title popover-header',
                             html : this.title
                         },
                         {
-                            cls : 'popover-content',
+                            cls : 'popover-content popover-body',
                             html : this.html
                         }
                     ]
@@ -17711,7 +17832,10 @@ Roo.extend(Roo.bootstrap.Popover, Roo.bootstrap.Component,  {
         if (this.html !== false) {
             this.el.select('.popover-content',true).first().dom.innerHtml = this.html;
         }
-        this.el.removeClass(['fade','top','bottom', 'left', 'right','in']);
+        this.el.removeClass([
+            'fade','top','bottom', 'left', 'right','in',
+            'bs-popover-top','bs-popover-bottom', 'bs-popover-left', 'bs-popover-right'
+        ]);
         if (!this.title.length) {
             this.el.select('.popover-title',true).hide();
         }
@@ -17772,10 +17896,10 @@ Roo.extend(Roo.bootstrap.Popover, Roo.bootstrap.Component,  {
 });
 
 Roo.bootstrap.Popover.alignment = {
-    'left' : ['r-l', [-10,0], 'right'],
-    'right' : ['l-r', [10,0], 'left'],
-    'bottom' : ['t-b', [0,10], 'top'],
-    'top' : [ 'b-t', [0,-10], 'bottom']
+    'left' : ['r-l', [-10,0], 'right bs-popover-right'],
+    'right' : ['l-r', [10,0], 'left bs-popover-left'],
+    'bottom' : ['t-b', [0,10], 'top bs-popover-top'],
+    'top' : [ 'b-t', [0,-10], 'bottom bs-popover-bottom']
 };
 
  /*
@@ -23846,7 +23970,8 @@ Roo.extend(Roo.bootstrap.htmleditor.ToolbarStandard, Roo.bootstrap.NavSimplebar,
                 size : 'sm',
                 xtype: 'Button',
                 xns: Roo.bootstrap,
-                glyphicon : id,
+                //glyphicon : id,
+                fa: id,
                 cmd : id || cmd,
                 enableToggle:toggle !== false,
                 html : html || '',
@@ -23866,7 +23991,7 @@ Roo.extend(Roo.bootstrap.htmleditor.ToolbarStandard, Roo.bootstrap.NavSimplebar,
                 xtype: 'Button',
                 size : 'sm',
                 xns: Roo.bootstrap,
-                glyphicon : 'font',
+                fa : 'font',
                 //html : 'submit'
                 menu : {
                     xtype: 'Menu',
@@ -24632,7 +24757,11 @@ Roo.bootstrap.PagingToolbar = function(config)
         this.bind(this.ds);
     }
     
-    this.navgroup = new Roo.bootstrap.NavGroup({ cls: 'pagination' });
+    if (Roo.bootstrap.version == 4) {
+        this.navgroup = new Roo.bootstrap.ButtonGroup({ cls: 'pagination' });
+    } else {
+        this.navgroup = new Roo.bootstrap.NavGroup({ cls: 'pagination' });
+    }
     
 };
 
@@ -24731,8 +24860,8 @@ Roo.extend(Roo.bootstrap.PagingToolbar, Roo.bootstrap.NavSimplebar, {
         
         this.first = this.navgroup.addItem({
             tooltip: this.firstText,
-            cls: "prev",
-            icon : 'fa fa-step-backward',
+            cls: "prev btn-outline-secondary",
+            html : ' <i class="fa fa-step-backward"></i>',
             disabled: true,
             preventDefault: true,
             listeners : { click : this.onClick.createDelegate(this, ["first"]) }
@@ -24740,8 +24869,8 @@ Roo.extend(Roo.bootstrap.PagingToolbar, Roo.bootstrap.NavSimplebar, {
         
         this.prev =  this.navgroup.addItem({
             tooltip: this.prevText,
-            cls: "prev",
-            icon : 'fa fa-backward',
+            cls: "prev btn-outline-secondary",
+            html : ' <i class="fa fa-backward"></i>',
             disabled: true,
             preventDefault: true,
             listeners : { click :  this.onClick.createDelegate(this, ["prev"]) }
@@ -24751,8 +24880,8 @@ Roo.extend(Roo.bootstrap.PagingToolbar, Roo.bootstrap.NavSimplebar, {
         
         var field = this.navgroup.addItem( {
             tagtype : 'span',
-            cls : 'x-paging-position',
-            
+            cls : 'x-paging-position  btn-outline-secondary',
+             disabled: true,
             html : this.beforePageText  +
                 '<input type="text" size="3" value="1" class="x-grid-page-number">' +
                 '<span class="x-paging-after">' +  String.format(this.afterPageText, 1) + '</span>'
@@ -24768,16 +24897,16 @@ Roo.extend(Roo.bootstrap.PagingToolbar, Roo.bootstrap.NavSimplebar, {
         //this.addSeparator();
         this.next = this.navgroup.addItem({
             tooltip: this.nextText,
-            cls: "next",
-            html : ' <i class="fa fa-forward">',
+            cls: "next btn-outline-secondary",
+            html : ' <i class="fa fa-forward"></i>',
             disabled: true,
             preventDefault: true,
             listeners : { click :  this.onClick.createDelegate(this, ["next"]) }
         });
         this.last = this.navgroup.addItem({
             tooltip: this.lastText,
-            icon : 'fa fa-step-forward',
-            cls: "next",
+            html : ' <i class="fa fa-step-forward"></i>',
+            cls: "next btn-outline-secondary",
             disabled: true,
             preventDefault: true,
             listeners : { click :  this.onClick.createDelegate(this, ["last"]) }
@@ -24785,7 +24914,8 @@ Roo.extend(Roo.bootstrap.PagingToolbar, Roo.bootstrap.NavSimplebar, {
     //this.addSeparator();
         this.loading = this.navgroup.addItem({
             tooltip: this.refreshText,
-            icon: 'fa fa-refresh',
+            cls: "btn-outline-secondary",
+            html : ' <i class="fa fa-refresh"></i>',
             preventDefault: true,
             listeners : { click : this.onClick.createDelegate(this, ["refresh"]) }
         });
@@ -29046,6 +29176,7 @@ Roo.extend(Roo.bootstrap.DocumentManager, Roo.bootstrap.Component,  {
         this.progressDialog = new Roo.bootstrap.Modal({
             cls : 'roo-document-manager-progress-dialog',
             allow_close : false,
+            animate : false,
             title : '',
             buttons : [
                 {
@@ -39924,7 +40055,7 @@ Roo.extend(Roo.bootstrap.PhoneInput, Roo.bootstrap.TriggerField, {
             var input =  {
                 tag: 'input',
                 id : id,
-                type: 'number',
+                // type: 'number', -- do not use number - we get the flaky up/down arrows.
                 maxlength: this.max_length,
                 cls : 'form-control tel-input',
                 autocomplete: 'new-password'
@@ -40138,6 +40269,7 @@ Roo.extend(Roo.bootstrap.PhoneInput, Roo.bootstrap.TriggerField, {
             
             this.list.on('mouseover', this.onViewOver, this);
             this.list.on('mousemove', this.onViewMove, this);
+            this.inputEl().on("keyup", this.onKeyUp, this);
             this.inputEl().on("keypress", this.onKeyPress, this);
             
             this.tpl = '<li><a href="#"><div class="flag {iso2}"></div>{name} <span class="dial-code">+{dialCode}</span></a></li>';
@@ -40388,13 +40520,15 @@ Roo.extend(Roo.bootstrap.PhoneInput, Roo.bootstrap.TriggerField, {
             return this.el.select('input.hidden-tel-input',true).first();
         },
         
+        // after setting val
+        onKeyUp : function(e){
+            this.setValue(this.getValue());
+        },
+        
         onKeyPress : function(e){
-            
             if(this.allowed.indexOf(String.fromCharCode(e.getCharCode())) === -1){
                 e.stopEvent();
             }
-            
-            this.setValue(this.getValue());
         }
         
 });