ExtJS inline width causing a width bug in firefox - javascript

We are using ExtJS 4.1.2 to create a panel with a toolbar docked on the top. We have overridden much of the styling to achieve the look and feel we wanted. Despite our best efforts to align and tweak, we are experiencing a strange issue in Firefox where the page on which this panel appears gets a default width of 20000px. I believe the element at fault is some internal component that ExtJS creates with a single class of "x-box-inner". In the dom browser view I can see
<div id="mylist" class="x-panel listpanel x-panel-default">
<div id="toolBar###(ExtJSid)" class="x-toolbar-docked-top x-toolbarhttp://i.stack.imgur.com/ddvdF.png x-toolbar-default x-docked x-docked-top ..." style="width: 735px;..." ...>
<div id="anotherXtJSid" class="x-box-inner " style="width: 735px; ..." ...>
<div id="anotherExtJSid" style="width:20000;..." (no class)>
...
If I hover over the element, I see
If, in the browser DOM explorer I edit that 20000px width to "auto" then the firefox window scrollbar disappears, and the display is the right size.
I attempted to fix the problem with an overridden width to "width:auto" for divs at that level and below, in the scss that defines the panel:
...
.listpanel {
overflow: visible;
background: none;
border: none;
...
.x-toolbar-docked-top {
overflow: visible;
.x-box-inner + div { // added + div
overflow: visible;
width: auto; // added width here.
}
}
...
}
This class is used when creating the ExtJS panel:
Ext.define('List', {
extend: 'Ext.panel.Panel',
alias: 'widget.mylist',
... // no width defined. It messes up all components within panel.
height: 750,
frame: false,
cls: 'listpanel',
bubbleEvents: [
...
],
...
initComponent: function () {
this.callParent(arguments);
this.add({
xtype: 'listbody',
ownerCt: this,
...
},
...
The width:auto and + div on x-box-inner appears to fix the width, although I can still see the ExtJS element with width:20000pxin the DOM inspector. BUT, seemingly arbitrarily, this breaks the overfow: visible -- one of the panel's toolbar dropdown-popups now disappears beneath the panel when the user clicks the dropdown button.
Is there some (other) way to force the width of this mystery ExtJS element?

So, with further experimentation and some suggestions from my colleague the answer lay in
Using width: 100% instead of width: auto
Using > instead of + to affect all children for width
Making another rule for x-box-inner without the > div just for controlling the overflow: visible.
Making the rules !important so they aren't overridden by other styles.
The style sheet stayed the same, but with the following x-box-inner rule changes:
...
.x-box-inner > div {
width: 100% !important;
}
x.box-inner {
overflow: visible !important;
}
...

Related

z-index of Bootstrap3 Tooltip in columns is Browser specific

Using bootstrap 3 I've got two columns (sm-3 and sm-9). The left column is position: fixed and contains a link with a tooltip. The z-index of the tooltip (without being specified) seems to be browser specific.
What is (in general) the best way to define the z-index of the tooltip? I'm looking for a clean solution that works in all common browsers.
FIDDLE
Internet Explorer 11 (left) Chrome 48 / Edge 25 (right)
HTML:
<div class="container">
<div class="col-sm-3" id="left">
<a id="tooltipButton" href="#" data-toggle="tooltip" title='Long Text'>Show Tooltip</a>
</div>
<div class="col-sm-9 col-sm-offset-3" id="right">
Content
</div>
</div>
CSS:
#left { position: fixed; }
#right { background-color: #ddd; }
JS:
$('#tooltipButton').tooltip({
trigger: 'click',
html: true,
placement: 'right',
});
A few things I've tried (CSS):
.tooltip { z-index: 10; } // Doesn't work
.tooltip .tooltip.in { z-index: 10; } // Doesn't work
.tooltip .tooltip-inner { z-index: 10; } // Doesn't work
Is there a clean solution without adding more divs and without changing the attributes of the left or right div? E.g. #left { z-index: 10; } seems to work but changes the attributes and the overlapping behavior of the left div.
FIDDLE
If you give an element a position other than static it forces it to appear above any element that is still static. It's a rather unknown behavior of z-index. Therefore if a parent element has a position other than static all it's children will have their own stacking scope. It works almost like layers.
This article has an amazing write up about it: What no-one told you about z-index
So in your example all the tooptip code is appearing in the container that has it's own stacking scope and is therefore forced under the next container. If you add z-index:999; to the #left container you will see it is fixed. This is because that container (and it's contents) are now forced higher than the next.
JSFIDDLE
The other thing you could do is remove position:relative from the #right container so it doesn't have it's own stacking scope and then it works again.
JSFIDDLE v2
I don't think this helps much with your problem as I don't think you can hack you way out of it. It is much more common practice that tooltip code is injected into the bottom of the page so that it naturally stacks above everything else.

Dynamic height of main block

On the page, there are 3 blocks (header, main and footer). 4th (apple_ios_status_bar_background) is hidden by default and displayed (or hidden) dynamically in code. When this unit is not displayed, you can see all 3 blocks on the page. If the display 4th block - the block footer goes down the page. It is necessary that would block main changed its height dynamically (all blocks should always be visible on the page).
Code https://jsfiddle.net/j3qm5qgx/1/
In JS detect iOS system, if true - show apple_ios_status_bar_background block, hide if false.
In your fiddle you did not include jQuery and second you did not define iOS. If you do so it works as you wanted it to.
var iOS = (navigator.userAgent.match(/(iPad|iPhone|iPod)/g) ? true : false);
https://jsfiddle.net/j3qm5qgx/4/
Note that Safari does not really mean iOS and that you could solve that issue in css with media device.
If you do not want your footer to go offscreen, you could set it on bottom via css:
footer {
position: absolute;
bottom: 0px;
height: 20px;
width: 100%;
background-color: #dff0d8;
}
https://jsfiddle.net/j3qm5qgx/5/
Another way would be to change it by jquery, since main now is 20 pixels more short:
if (iOS) {
$("#apple_ios_status_bar_background").show();
$('main')[0].style.height = 'calc(100% - (40px + 20px + 20px))';
} else {
$("#apple_ios_status_bar_background").hide();
}
https://jsfiddle.net/j3qm5qgx/6/

TinyMCE color picker dropdown appears off-screen

This is an issue on Firefox and IE so far that I've tested; the problem does not exist on Chrome.
I'm including two TinyMCE editors on a page with one partially off-screen to start. When I select the color picker dropdown option from the toolbar on the first TinyMCE instance, the dropdown appears where it should. But if I scroll down and select the color picker dropdown in the second instance, that dropdown appears way below the editor and typically off the page.
You can see this in action here: http://jsfiddle.net/nm6wtca3/
Without removing the html, body CSS, what can I do to have the color picker always appear in the correct position?
I've traced the problem down to setting CSS on the html, body elements.
html, body {
width: 100%;
height: 100%;
overflow-x: hidden;
}
The dropdown div has CSS applied to it that is auto-calculated by TinyMCE. It looks something like this:
z-index: 65535;
left: 641.467px;
top: 633px;
width: 162px;
height: 105px;
How it appears in FF (sometimes way worse):
How it appears in Chrome (how it should look):
You did say you don't want to remove any CSS from the html,body, but you didn't say anything about adding to it! This solution is based on the assumption that you can add to the html,body
Solution
html, body {
width: 100%;
height: 100%;
overflow-x: hidden;
position: relative; /* Line added */
}
JSFiddle Example
I hope this helps. In all reality, you really only need to apply position: relative; to the body like so body { position: relative; }
I'm not super familiar with tinymce's colorpicker, but I can see the issue, and I can replicate it reliably: your problem occurs when you have a picker open, and then you scroll. I can replicate this in chrome too. Here's a video.
When I look at the DOM, I see that tinyMCE has created two absolute-positioned divs at the end of document.body, one for each picker. When you open one, their position is updated to reflect the location of the toolbar-button at the time you clicked it, but it never gets updated when you scroll!
So, how to solve this? Well, there are a few possibilities:
Option 1: it looks like tinyMCE provides a method to bind a control to an event (here). With this, you could bind a callback to 'scroll' that repositions the box...
Huh, now that I think of it, you could simply close any open colorpickers whenever a user scrolls ... kinda feels like a cop-out but there's no denying it has the best R.O.I. ;) We'll call that Option 2!
Option 3: depending on the implementation of the colorpicker, you may be able to override where in the DOM those divs get rendered. The API method I saw that looked the most promising is here. Once you have the div inside a relative-positioned parent, you'd also have to make the colorpicker's positioning algorithm smart enough to look in the right place for x and y offset ...when I tried this by just moving the element and mashing in some css by hand in chrome-console, the algorithm still computed x and y offsets based on doc.body, so depending on where you were scrolled at click-time, everything would be out of position
It looks like this issue might be troubling other people as well... maybe they've found a solution but haven't posted anything about it?
I hope this is enough info to get you past the problem... Let me know if you have any questions!
It looks like the problem is caused by overflow-x: hidden;
It may not be the answer you want but removing that or moving it to a page wrapper will solve your problem.
Working Example
html, body {
width: 100%;
height: 100%;
padding:0;
margin:0;
}
#pagewrapper{
overflow-x: hidden;
}
Another option would be to force repositioning on scroll, but honestly this is overkill... I strongly recommend fixing the css instead.
Another working example
$('body').scroll(posfix); // when the body scrolls
$('#mceu_10').click(posfix); // when you click the top font color button
$('#mceu_35').click(posfix); // when you click the bottom font color button
function posfix() {
setTimeout(function () { // hack way to ensure it fires after the menu is shown
$('#mceu_51').css({
top: $('#mceu_10').offset().top + $('#mceu_10').height(), // set top/left based on button's position
left: $('#mceu_10').offset().left + $('#mceu_10').width() / 2
});
$('#mceu_52').css({
top: $('#mceu_35').offset().top + $('#mceu_35').height(),
left: $('#mceu_35').offset().left + $('#mceu_35').width() / 2
});
}, 1);
}
it works on firefox, and Internet Explorer fine
just remove this css code
html, body {
width: 100%;
height: 100%;
overflow-x: hidden;
}
Please take a look at this:
html,
body {
width: auto;
height: auto;
overflow-x: hidden;
}
You can simply set body width and height to auto, then there won't be any need to use position and you don't have to remove anything. I think you do not need to use height: 100% since it will be auto-calculated by TinyMCE. i hope it helped.
Update
Look at the screen shot from chrome and its same in firefox. And i didn't remove any css but just changed..and by putting 100% in css the output will be like :-
Please check this one with auto but not 100%..thank you

Media Queries not working properly after Javascript alters element CSS

any idea why in the example below, media queries stops changing the height of the menu bar after it's been changed by js? (make window small and click on the arrow to expand the mini menu). Do I need to register a point of origin for the menu element or something?
CSS:
#menu {
position: fixed;
left: 0px;
bottom: 0px;
width: 100%;
height: 90px;
z-index: 11000;
opacity: 1;
background-color: #F03600;
}
JS:
if ($("#arrowup").css('top') == '0px') {
$("#menu").animate({'height':'270px'}, 800, "easeInOutQuint");
} else {
$("#menu").animate({'height':'55px'}, 800, "easeInOutQuint");
}
You can check out the page here, all the code's on a single page:
http://www.nioute.co.uk/stuff/
Also, what's a good read with regards to media queries / js interaction?
Thanks!
The reason the media queries don't work is because when you modify the bar with Javascript, it applies inline-css. This overrides CSS that you may have in your stylesheets. The problem seems to be, when you toggle the arrow back down, #menu has an inline style of height="55px" applied to it, which blocks the regular style of 90px on a larger size.
The solution would be to clear the style when the window is resized to larger than your media query breakpoint using something like $(window).resize(function()...); and checking the current width of the window against your breakpoint. If it returns true, call $('#menu').attr('style', ''); and that will remove the inline style.
You can use class for adding some styles to elements and removing they after the job instead of getElementById(#menu).style.height = ...
for example:
getElementById(#menu).classList.add("newHeight")
Or
getElementById(#menu).classList.remove("newHeight")

Kendo Grid do not play nice with Bootstrap dropdown or tooltips

I'm trying to use certain Bootstrap elements inside a Kendo Grid, for example Bootstrap dropdown buttons and tooltips.
The problem is the dropdown or tooltips are always positioned below the row below or above. I've tried adjusting the z-index of the displayed elements, but this doesn't fix it.
Has anyone managed to find a solution to this?
The .btn-group class, which is the container for the dropdown-menu is positioned relatively so altering the z-index of the dropdown-menu class won't do any good. You can position is absolutely and then adjust the positioning from there. Something like this should get you started:
.k-grid-content .btn-group {
position: absolute;
}
.k-grid-content .btn-group .btn {
top: -10px;
}
Link to a jsFiddle that demonstrates it in action.
The problem is to do with the Grid content being permanently set to overflow-y: scroll which it doesn't really need (unless you are a fixed height with the virtualization feature).
By changing the CSS of the grid content to remove the scroll bar, setting overflow: visible and adding extra padding to account for the missing scrollbar, it now works.
I've updated the jsFiddle to demonstrate.
Thanks for all the help.
For future reference, in case you have other grid cells that might contain data that will overflow into other columns with the above fix, you can set a class to the custom grid action column like so:
columns: [
{
field: "Actions",
title: " ",
filterable: false,
attributes: {"class": "actions-column"},
template: <your action button template or template link here>
}
]
Then in the styling for the page add the following CSS:
.k-grid-content tr td.actions-column {
overflow: visible;
}
edit: small css selector change

Categories

Resources