12

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 FF

How it appears in Chrome (how it should look): How it appears in Chrome (how it should look)

Luke Shaheen
  • 4,262
  • 12
  • 52
  • 82
  • Can't reproduce in Firefox 37.0.1 on OS X. – Alexander O'Mara Apr 10 '15 at 17:48
  • @AlexanderO'Mara that's the exact setup I'm using. Scroll down to the second TinyMCE instance and select the dropdown for color choice. – Luke Shaheen Apr 10 '15 at 17:54
  • Strange, I was just now able to reproduce it. I can't seem to reproduce it reliably though, it's working for me most of the time. – Alexander O'Mara Apr 10 '15 at 17:59
  • @AlexanderO'Mara It happens more often than not for me - but either way, it's a problem that's gotta be fixed. And there is a solution, I'm just not sure what it is :) – Luke Shaheen Apr 10 '15 at 18:46
  • Just remove html/body height, problem solved. [Check it out](http://jsfiddle.net/nm6wtca3/7/) and if you are bored, than you can add it as 2112. bug [here](http://www.tinymce.com/develop/bugtracker_bugs.php) – skobaljic Apr 17 '15 at 08:25
  • 1
    Problem has to be they use body height, but they should use [scrollHeight](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight) instead. I tried to dig into scripts, but can't find the way `windowManager` calculates the position. – skobaljic Apr 17 '15 at 08:32
  • @skobaljic Bug has been submitted to TinyMCE and marked as Verified - http://www.tinymce.com/develop/bugtracker_view.php?id=7474 – Luke Shaheen Apr 20 '15 at 13:49

5 Answers5

4

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!

MattE_WI
  • 377
  • 1
  • 11
  • no - Option 1 (2), listening, and changing position, on every user scroll event is really heavy on the browser. Multiply that times the number of TinyMCE instances on a page, and it becomes a problem - the browser will lag. Option 3 you said yourself doesn't really work. – Luke Shaheen Apr 17 '15 at 12:02
4

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);
}
apaul
  • 16,092
  • 8
  • 47
  • 82
  • `Without removing the html, body CSS` was in my question for a reason - I understand that removing it IS an answer to the positioning, but it's not what I was looking for. – Luke Shaheen Apr 15 '15 at 18:31
  • @John Any reason you couldn't use a wrapper? – apaul Apr 15 '15 at 18:32
  • I could add a wrapper pretty easily with my codebase. The problem is, I don't know the original programmer's intent with `overflow-x: hidden` - my guess is that he had some elements overflowing that he didn't know how to fix, so it was a hack to get rid of the scroll bars. It looks like I'll end up just removing it and running tests to make sure it didn't break anything. I can't really directly give you the bounty for that answer; but I guess I can give you a +1 – Luke Shaheen Apr 15 '15 at 18:43
  • 1
    @John I added another method, but I would recommend fixing the css. The `overflow-x: hidden;` feels like a bad workaround. Adding another bad workaround to accommodate a bad workaround is probably a bad idea. – apaul Apr 15 '15 at 19:59
  • Yeah that's way too specific with the IDs - if I add another TinyMCE instance in-between the two, or change the order of the buttons, those IDs are going to automatically change. I agree with the bad workaround thought! Thanks – Luke Shaheen Apr 15 '15 at 20:12
4

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; }

HandyDan
  • 425
  • 2
  • 8
  • Perfect. Any explanation on why adding `position: relative` fixes this issue? – Luke Shaheen Apr 17 '15 at 12:04
  • Adding another rule to negate another is still hacky, but it solves my problem without removing any existing CSS which is what I was looking for with this question. – Luke Shaheen Apr 17 '15 at 15:27
  • I wouldn't necessarily call it a hack, it isn't negating any of your CSS. Explanation: For the most part, an element that has `position: absolute;` will position itself with respect to its closest `position: relative` or `position: absolute;` parent. [A great example by CSS-Tricks](https://css-tricks.com/absolute-positioning-inside-relative-positioning/) – HandyDan Apr 17 '15 at 23:40
  • @Handy i dont think its the best answer as if i will use position:relative then other drop down won't work..check in your fiddle as other dd won't work but if you will use height:auto then all drop down will work with smooth.. try that once.. – Leo the lion Apr 18 '15 at 06:59
  • @Leo All the drop downs work perfectly for me with this fix. I tested using Chrome and Internet Explorer 9-11. What browser are you using? – HandyDan Apr 19 '15 at 17:59
  • @HandyDan, i am using chrome Version 42.0.2311.90 m and firefox 37.0.1 and in both other drop down are like out of box and showing different different places..please check and when you will find problem then go with my solution and you will find no issue then..:) – Leo the lion Apr 20 '15 at 05:46
  • @Leo Strange, i'm using the same version of Chrome and Firefox and I still don't see the issue you are talking about. I do see another issue though... if the text color drop down is too close to the edge of the screen, it will get cut off. However I see the same issue with your fix. Please do keep in mind that the OP asked for a solution that would not modify his current `html,body` CSS. I do acknowledge that he has some issues with his current CSS adding double scroll bars (specifically: `html, body { width: 100%; height: 100%; }`) – HandyDan Apr 21 '15 at 18:06
  • Please check my ans with updated images..and i didn't remove any css but just changed..and please don't take me in other way as m just trying to solve the things so other askers can also get help from either your ans or mine..:) – Leo the lion Apr 22 '15 at 07:52
0

it works on firefox, and Internet Explorer fine

it works on firefox, and Internet Explorer fine

just remove this css code

html, body {
    width: 100%;
    height: 100%;
    overflow-x: hidden;
}
  • `Without removing the html, body CSS` was in my question for a reason - I understand that removing it IS an answer to the positioning, but it's not what I was looking for. – Luke Shaheen Apr 17 '15 at 12:00
0

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 Error Screen

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 :-

Auto Width

Please check this one with auto but not 100%..thank you

Leo the lion
  • 3,164
  • 2
  • 22
  • 40