Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery UI Theme Conflict: SlickGrid and jQuery UI Tabs

I'm trying to apply this SlickGrid example:

http://mleibman.github.com/SlickGrid/examples/example4-model.html

to my own web project.

When I drop my grid in to the top of my page, it renders correctly. However, when I drop it into a jQuery UI Tabs tab on the same page, the CSS Sprite that renders the search image is incorrectly offset.

The Problem

The icon is rendered with

<span title="Toggle search panel" class="ui-icon ui-icon-search ui-state-default ui-corner-all" style="float: right;" onclick="toggleFilterRow11()"/>

It looks like jQuery UI Tabs also uses the same CSS classes, and of course a conflict arises.

Looking at the effective styles in IE9, the control outside of jQuery UI Tabs that renders correctly has the following:

Correct styles

The control that renders incorrectly looks like this:

Wrong styles

Bottom Line

Placing the SlickGrid in a jQueryUI Tab causes the ui-icon-search class to be lost and therefore the wrong background-position-x/y to be set.

Why is that class being lost and how can I fix the issue?

like image 550
Eric J. Avatar asked Apr 01 '12 06:04

Eric J.


1 Answers

The problem

When jQueryUI creates tabs from the HTML it adds the jQueryUI CSS classes. From the jQueryUI examples:

<div id="tabs">
    <ul>
        <li><a href="#tabs-1">Nunc tincidunt</a></li>
        <li><a href="#tabs-2">Proin dolor</a></li>
        <li><a href="#tabs-3">Aenean lacinia</a></li>
    </ul>
    <div id="tabs-1"></div>
    <div id="tabs-2"></div>
    <div id="tabs-3"></div>
</div>

becomes

<div id="tabs" class="ui-tabs ui-widget ui-widget-content ui-corner-all">
    <ul class="ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all">
        <li class="ui-state-default ui-corner-top ui-tabs-selected ui-state-active"><a href="#tabs-1">Nunc tincidunt</a></li>
        <li class="ui-state-default ui-corner-top"><a href="#tabs-2">Proin dolor</a></li>
        <li class="ui-state-default ui-corner-top"><a href="#tabs-3">Aenean lacinia</a></li>
    </ul>
    <div id="tabs-1" class="ui-tabs-panel ui-widget-content ui-corner-bottom"></div>
    <div id="tabs-2" class="ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide"></div>
    <div id="tabs-3" class="ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide"></div>
</div>

The problem is happening because the SlickGrid content now exits as a child of an element with the class ui-widget-content. Actually, there are 2 ancestors of the grid header that have that class - in the above code see <div id="tabs"> and <div id="tabs-1"> both have that class applied when tabs are created.

The jQueryUI CSS rules that are supposed to apply to get the correct search icon are:

.ui-icon {
    width: 16px;
    height: 16px;
    background-image: url(images/ui-icons_222222_256x240.png);
}

.ui-icon-search {
    background-position: -160px -112px;
}

.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default {
    border: 1px solid #d3d3d3;
    background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x;
    font-weight: normal;
    color: #555555;
}

The markup for the icon is:

<span style="float:right" class="ui-icon ui-icon-search ui-state-default ui-corner-all" title="Toggle search panel" onclick="toggleFilterRow()"></span>

so therefore the CSS rules .ui-icon, .ui-icon-search and the first match of the 3rd rule .ui-state-default are applied.

However when the same markup exists as a descendent of a element with the class .ui-widget-content, the 2nd part of the 3rd rule above (.ui-widget-content .ui-state-default) also matches which is more specific. See http://www.stuffandnonsense.co.uk/archives/images/specificitywars-05v2.jpg for a Star Wars themed explaination of CSS specificity. Essentially the background property of the 3rd rule that includes background-position:50% 50% is more specific than the single selector .ui-icon-search rule therefore overriding the correct background-position:-160px -112px.

The solution

Need to make the .ui-icon-search rule the same or more specific than the .ui-widget-content .ui-state-default rule which can be done by either:

  1. Adding !important to the rule
  2. Adding more selectors to the rule

For example

.ui-icon-search {
    background-position: -160px -112px !important;
}

or

.ui-icon-search, .ui-widget-content .ui-icon-search {
    background-position: -160px -112px;
}

I cannot think of a way that doesn't involve changing the jQueryUI CSS (or duplicating the .ui-icon-search rule in your own CSS with one of the two solutions above). I would actually be interested to see if there is another way myself!

like image 134
andyb Avatar answered Dec 20 '22 07:12

andyb