diff --git a/css/khan-site.css b/css/khan-site.css index 5164e8e24..96f710bc1 100644 --- a/css/khan-site.css +++ b/css/khan-site.css @@ -57,26 +57,26 @@ .ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; } .ui-widget .ui-widget { font-size: 1em; } .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; } -.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(http://www.khanacademy.org/../jqueryui-package/images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; } +.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(http://www.khanacademy.org//stylesheets/jqueryui-package/images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; } .ui-widget-content a { color: #222222; } -.ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(http://www.khanacademy.org/../jqueryui-package/images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; } +.ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(http://www.khanacademy.org//stylesheets/jqueryui-package/images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; } .ui-widget-header a { color: #222222; } /* Interaction states ----------------------------------*/ -.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(http://www.khanacademy.org/../jqueryui-package/images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; } +.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(http://www.khanacademy.org//stylesheets/jqueryui-package/images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; } .ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; } -.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(http://www.khanacademy.org/../jqueryui-package/images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(http://www.khanacademy.org//stylesheets/jqueryui-package/images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } .ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; } -.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(http://www.khanacademy.org/../jqueryui-package/images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } +.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(http://www.khanacademy.org//stylesheets/jqueryui-package/images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } .ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; } .ui-widget :active { outline: none; } /* Interaction Cues ----------------------------------*/ -.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(http://www.khanacademy.org/../jqueryui-package/images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; } +.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(http://www.khanacademy.org//stylesheets/jqueryui-package/images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; } .ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; } -.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(http://www.khanacademy.org/../jqueryui-package/images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; } +.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(http://www.khanacademy.org//stylesheets/jqueryui-package/images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; } .ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; } .ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; } .ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } @@ -87,14 +87,14 @@ ----------------------------------*/ /* states and images */ -.ui-icon { width: 16px; height: 16px; background-image: url(http://www.khanacademy.org/../jqueryui-package/images/ui-icons_222222_256x240.png); } -.ui-widget-content .ui-icon {background-image: url(http://www.khanacademy.org/../jqueryui-package/images/ui-icons_222222_256x240.png); } -.ui-widget-header .ui-icon {background-image: url(http://www.khanacademy.org/../jqueryui-package/images/ui-icons_222222_256x240.png); } -.ui-state-default .ui-icon { background-image: url(http://www.khanacademy.org/../jqueryui-package/images/ui-icons_888888_256x240.png); } -.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(http://www.khanacademy.org/../jqueryui-package/images/ui-icons_454545_256x240.png); } -.ui-state-active .ui-icon {background-image: url(http://www.khanacademy.org/../jqueryui-package/images/ui-icons_454545_256x240.png); } -.ui-state-highlight .ui-icon {background-image: url(http://www.khanacademy.org/../jqueryui-package/images/ui-icons_2e83ff_256x240.png); } -.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(http://www.khanacademy.org/../jqueryui-package/images/ui-icons_cd0a0a_256x240.png); } +.ui-icon { width: 16px; height: 16px; background-image: url(http://www.khanacademy.org//stylesheets/jqueryui-package/images/ui-icons_222222_256x240.png); } +.ui-widget-content .ui-icon {background-image: url(http://www.khanacademy.org//stylesheets/jqueryui-package/images/ui-icons_222222_256x240.png); } +.ui-widget-header .ui-icon {background-image: url(http://www.khanacademy.org//stylesheets/jqueryui-package/images/ui-icons_222222_256x240.png); } +.ui-state-default .ui-icon { background-image: url(http://www.khanacademy.org//stylesheets/jqueryui-package/images/ui-icons_888888_256x240.png); } +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(http://www.khanacademy.org//stylesheets/jqueryui-package/images/ui-icons_454545_256x240.png); } +.ui-state-active .ui-icon {background-image: url(http://www.khanacademy.org//stylesheets/jqueryui-package/images/ui-icons_454545_256x240.png); } +.ui-state-highlight .ui-icon {background-image: url(http://www.khanacademy.org//stylesheets/jqueryui-package/images/ui-icons_2e83ff_256x240.png); } +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(http://www.khanacademy.org//stylesheets/jqueryui-package/images/ui-icons_cd0a0a_256x240.png); } /* positioning */ .ui-icon-carat-1-n { background-position: 0 0; } @@ -284,8 +284,8 @@ .ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; -khtml-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } /* Overlays */ -.ui-widget-overlay { background: #aaaaaa url(http://www.khanacademy.org/../jqueryui-package/images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); } -.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(http://www.khanacademy.org/../jqueryui-package/images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/*! +.ui-widget-overlay { background: #aaaaaa url(http://www.khanacademy.org//stylesheets/jqueryui-package/images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); } +.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(http://www.khanacademy.org//stylesheets/jqueryui-package/images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/*! * jQuery UI Resizable 1.8.24 * * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) @@ -562,22 +562,13 @@ button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra pad */ .ui-progressbar { height:2em; text-align: left; overflow: hidden; } .ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; } -/* -* qTip2 - Pretty powerful tooltips + +/*! qTip2 - Pretty powerful tooltips - v2.0.0pre - 2012-12-14 * http://craigsworks.com/projects/qtip2/ -* -* Version: 2.0.0pre -* Copyright 2009-2010 Craig Michael Thompson - http://craigsworks.com -* -* Dual licensed under MIT or GPLv2 licenses -* http://en.wikipedia.org/wiki/MIT_License -* http://en.wikipedia.org/wiki/GNU_General_Public_License -* -* Date: Sun May 13 16:01:37 2012 +0100 -*/ +* Copyright (c) 2012 Craig Michael Thompson; Licensed MIT, GPL */ /* Core qTip styles */ -.ui-tooltip, .qtip{ +.qtip, .qtip{ position: absolute; left: -28000px; top: -28000px; @@ -588,71 +579,66 @@ button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra pad font-size: 10.5px; line-height: 12px; -} - /* Fluid class for determining actual width in IE */ - .ui-tooltip-fluid{ - display: block; - visibility: hidden; - position: static !important; - float: left !important; - } + direction: ltr; +} - .ui-tooltip-content{ + .qtip-content{ position: relative; padding: 5px 9px; overflow: hidden; - border: 1px solid #000001; - text-align: left; word-wrap: break-word; - overflow: hidden; } - .ui-tooltip-titlebar{ + .qtip-titlebar{ position: relative; - min-height: 14px; padding: 5px 35px 5px 10px; overflow: hidden; - border: 1px solid #000001; - border-width: 1px 1px 0; - + border-width: 0 0 1px; font-weight: bold; } - .ui-tooltip-titlebar + .ui-tooltip-content{ border-top-width: 0px !important; } + .qtip-titlebar + .qtip-content{ border-top-width: 0 !important; } - /*! Default close button class */ - .ui-tooltip-titlebar .ui-state-default{ - position: absolute; - right: 4px; - top: 50%; - margin-top: -9px; + /* Default close button class */ + .qtip-close{ + position: absolute; + right: -9px; top: -9px; - cursor: pointer; - outline: medium none; + cursor: pointer; + outline: medium none; - border-width: 1px; - border-style: solid; + border-width: 1px; + border-style: solid; + border-color: transparent; + } + + .qtip-titlebar .qtip-close{ + right: 4px; top: 50%; + margin-top: -9px; } - - * html .ui-tooltip-titlebar .ui-state-default{ top: 16px; } /* IE fix */ + + * html .qtip-titlebar .qtip-close{ top: 16px; } /* IE fix */ - .ui-tooltip-titlebar .ui-icon, - .ui-tooltip-icon .ui-icon{ + .qtip-titlebar .ui-icon, + .qtip-icon .ui-icon{ display: block; text-indent: -1000em; + direction: ltr; + vertical-align: middle; } - .ui-tooltip-icon, .ui-tooltip-icon .ui-icon{ + .qtip-icon, .qtip-icon .ui-icon{ -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; + text-decoration: none; } - .ui-tooltip-icon .ui-icon{ + .qtip-icon .ui-icon{ width: 18px; height: 14px; @@ -666,298 +652,210 @@ button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra pad /* Applied to 'focused' tooltips e.g. most recently displayed/interacted with */ -.ui-tooltip-focus{ - -} +.qtip-focus{} /* Applied on hover of tooltips i.e. added/removed on mouseenter/mouseleave respectively */ -.ui-tooltip-hover{ - -} +.qtip-hover{} - -/*! Default tooltip style */ -.ui-tooltip-default .ui-tooltip-titlebar, -.ui-tooltip-default .ui-tooltip-content{ +/* Default tooltip style */ +.qtip-default{ + border-width: 1px; + border-style: solid; border-color: #F1D031; + background-color: #FFFFA3; color: #555; } - .ui-tooltip-default .ui-tooltip-titlebar{ + .qtip-default .qtip-titlebar{ background-color: #FFEF93; } - .ui-tooltip-default .ui-tooltip-icon{ + .qtip-default .qtip-icon{ border-color: #CCC; background: #F1F1F1; color: #777; } - .ui-tooltip-default .ui-tooltip-titlebar .ui-state-hover{ + .qtip-default .qtip-titlebar .qtip-close{ border-color: #AAA; color: #111; } -/* Modal plugin */ -#qtip-overlay{ - position: fixed; - left: -10000em; - top: -10000em; -} - - /* Applied to modals with show.modal.blur set to true */ - #qtip-overlay.blurs{ cursor: pointer; } - - /* Change opacity of overlay here */ - #qtip-overlay div{ - position: absolute; - left: 0; top: 0; - width: 100%; height: 100%; - - background-color: black; - - opacity: 0.7; - filter:alpha(opacity=70); - -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=70)"; - } - -/* Tips plugin */ -.ui-tooltip .ui-tooltip-tip{ - margin: 0 auto; - overflow: hidden; - z-index: 10; -} - - .ui-tooltip .ui-tooltip-tip, - .ui-tooltip .ui-tooltip-tip *{ - position: absolute; - - line-height: 0.1px !important; - font-size: 0.1px !important; - color: #123456; - - background: transparent; - border: 0px dashed transparent; - } - - .ui-tooltip .ui-tooltip-tip canvas{ top: 0; left: 0; } - /*! Light tooltip style */ -.ui-tooltip-light .ui-tooltip-titlebar, -.ui-tooltip-light .ui-tooltip-content{ +.qtip-light{ + background-color: white; border-color: #E2E2E2; color: #454545; } - .ui-tooltip-light .ui-tooltip-content{ - background-color: white; - } - - .ui-tooltip-light .ui-tooltip-titlebar{ + .qtip-light .qtip-titlebar{ background-color: #f1f1f1; } /*! Dark tooltip style */ -.ui-tooltip-dark .ui-tooltip-titlebar, -.ui-tooltip-dark .ui-tooltip-content{ +.qtip-dark{ + background-color: #505050; border-color: #303030; color: #f3f3f3; } - .ui-tooltip-dark .ui-tooltip-content{ - background-color: #505050; - } - - .ui-tooltip-dark .ui-tooltip-titlebar{ + .qtip-dark .qtip-titlebar{ background-color: #404040; } - .ui-tooltip-dark .ui-tooltip-icon{ + .qtip-dark .qtip-icon{ border-color: #444; } - .ui-tooltip-dark .ui-tooltip-titlebar .ui-state-hover{ + .qtip-dark .qtip-titlebar .ui-state-hover{ border-color: #303030; } /*! Cream tooltip style */ -.ui-tooltip-cream .ui-tooltip-titlebar, -.ui-tooltip-cream .ui-tooltip-content{ +.qtip-cream{ + background-color: #FBF7AA; border-color: #F9E98E; color: #A27D35; } - .ui-tooltip-cream .ui-tooltip-content{ - background-color: #FBF7AA; - } - - .ui-tooltip-cream .ui-tooltip-titlebar{ + .qtip-cream .qtip-titlebar{ background-color: #F0DE7D; } - .ui-tooltip-cream .ui-state-default .ui-tooltip-icon{ + .qtip-cream .qtip-close .qtip-icon{ background-position: -82px 0; } /*! Red tooltip style */ -.ui-tooltip-red .ui-tooltip-titlebar, -.ui-tooltip-red .ui-tooltip-content{ +.qtip-red{ + background-color: #F78B83; border-color: #D95252; color: #912323; } - .ui-tooltip-red .ui-tooltip-content{ - background-color: #F78B83; - } - - .ui-tooltip-red .ui-tooltip-titlebar{ + .qtip-red .qtip-titlebar{ background-color: #F06D65; } - .ui-tooltip-red .ui-state-default .ui-tooltip-icon{ + .qtip-red .qtip-close .qtip-icon{ background-position: -102px 0; } - .ui-tooltip-red .ui-tooltip-icon{ + .qtip-red .qtip-icon{ border-color: #D95252; } - .ui-tooltip-red .ui-tooltip-titlebar .ui-state-hover{ + .qtip-red .qtip-titlebar .ui-state-hover{ border-color: #D95252; } /*! Green tooltip style */ -.ui-tooltip-green .ui-tooltip-titlebar, -.ui-tooltip-green .ui-tooltip-content{ +.qtip-green{ + background-color: #CAED9E; border-color: #90D93F; color: #3F6219; } - .ui-tooltip-green .ui-tooltip-content{ - background-color: #CAED9E; - } - - .ui-tooltip-green .ui-tooltip-titlebar{ + .qtip-green .qtip-titlebar{ background-color: #B0DE78; } - .ui-tooltip-green .ui-state-default .ui-tooltip-icon{ + .qtip-green .qtip-close .qtip-icon{ background-position: -42px 0; } /*! Blue tooltip style */ -.ui-tooltip-blue .ui-tooltip-titlebar, -.ui-tooltip-blue .ui-tooltip-content{ +.qtip-blue{ + background-color: #E5F6FE; border-color: #ADD9ED; color: #5E99BD; } - .ui-tooltip-blue .ui-tooltip-content{ - background-color: #E5F6FE; - } - - .ui-tooltip-blue .ui-tooltip-titlebar{ + .qtip-blue .qtip-titlebar{ background-color: #D0E9F5; } - .ui-tooltip-blue .ui-state-default .ui-tooltip-icon{ + .qtip-blue .qtip-close .qtip-icon{ background-position: -2px 0; } -/*! Add shadows to your tooltips in: FF3+, Chrome 2+, Opera 10.6+, IE6+, Safari 2+ */ -.ui-tooltip-shadow{ + +/* Add shadows to your tooltips in: FF3+, Chrome 2+, Opera 10.6+, IE9+, Safari 2+ */ +.qtip-shadow{ -webkit-box-shadow: 1px 1px 3px 1px rgba(0, 0, 0, 0.15); -moz-box-shadow: 1px 1px 3px 1px rgba(0, 0, 0, 0.15); box-shadow: 1px 1px 3px 1px rgba(0, 0, 0, 0.15); } - .ui-tooltip-shadow .ui-tooltip-titlebar, - .ui-tooltip-shadow .ui-tooltip-content{ - filter: progid:DXImageTransform.Microsoft.Shadow(Color='gray', Direction=135, Strength=3); - -ms-filter:"progid:DXImageTransform.Microsoft.Shadow(Color='gray', Direction=135, Strength=3)"; - - _margin-bottom: -3px; /* IE6 */ - .margin-bottom: -3px; /* IE7 */ - } - - -/*! Add rounded corners to your tooltips in: FF3+, Chrome 2+, Opera 10.6+, IE9+, Safari 2+ */ -.ui-tooltip-rounded, -.ui-tooltip-rounded .ui-tooltip-content, -.ui-tooltip-tipsy, -.ui-tooltip-tipsy .ui-tooltip-content, -.ui-tooltip-youtube, -.ui-tooltip-youtube .ui-tooltip-content, -.ui-tooltip-bootstrap, -.ui-tooltip-bootstrap .ui-tooltip-content{ +/* Add rounded corners to your tooltips in: FF3+, Chrome 2+, Opera 10.6+, IE9+, Safari 2+ */ +.qtip-rounded, +.qtip-tipsy, +.qtip-bootstrap{ -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; } -.ui-tooltip-rounded .ui-tooltip-titlebar, -.ui-tooltip-tipsy .ui-tooltip-titlebar, -.ui-tooltip-youtube .ui-tooltip-titlebar, -.ui-tooltip-bootstrap .ui-tooltip-titlebar{ - -moz-border-radius: 5px 5px 0 0; - -webkit-border-radius: 5px 5px 0 0; - border-radius: 5px 5px 0 0; -} - -.ui-tooltip-rounded .ui-tooltip-titlebar + .ui-tooltip-content, -.ui-tooltip-tipsy .ui-tooltip-titlebar + .ui-tooltip-content, -.ui-tooltip-youtube .ui-tooltip-titlebar + .ui-tooltip-content, -.ui-tooltip-bootstrap .ui-tooltip-titlebar + .ui-tooltip-content{ - -moz-border-radius: 0 0 5px 5px; - -webkit-border-radius: 0 0 5px 5px; - border-radius: 0 0 5px 5px; -} - - -/*! Youtube tooltip style */ -.ui-tooltip-youtube{ +/* Youtube tooltip style */ +.qtip-youtube{ + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + border-radius: 2px; + -webkit-box-shadow: 0 0 3px #333; -moz-box-shadow: 0 0 3px #333; box-shadow: 0 0 3px #333; -} - .ui-tooltip-youtube .ui-tooltip-titlebar, - .ui-tooltip-youtube .ui-tooltip-content{ - _margin-bottom: 0; /* IE6 */ - .margin-bottom: 0; /* IE7 */ + color: white; + border-width: 0; - background: transparent; - background: rgba(0, 0, 0, 0.85); - filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#D9000000,endColorstr=#D9000000); - -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#D9000000,endColorstr=#D9000000)"; + background: #4A4A4A; + background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0,#4A4A4A),color-stop(100%,black)); + background-image: -webkit-linear-gradient(top,#4A4A4A 0,black 100%); + background-image: -moz-linear-gradient(top,#4A4A4A 0,black 100%); + background-image: -ms-linear-gradient(top,#4A4A4A 0,black 100%); + background-image: -o-linear-gradient(top,#4A4A4A 0,black 100%); +} - color: white; - border-color: #CCCCCC; + .qtip-youtube .qtip-titlebar{ + background-color: #4A4A4A; + background-color: rgba(0,0,0,0); + } + + .qtip-youtube .qtip-content{ + padding: .75em; + font: 12px arial,sans-serif; + + filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr=#4a4a4a,EndColorStr=#000000); + -ms-filter: "progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr=#4a4a4a,EndColorStr=#000000);"; } - .ui-tooltip-youtube .ui-tooltip-icon{ + .qtip-youtube .qtip-icon{ border-color: #222; } - .ui-tooltip-youtube .ui-tooltip-titlebar .ui-state-hover{ + .qtip-youtube .qtip-titlebar .ui-state-hover{ border-color: #303030; } /* jQuery TOOLS Tooltip style */ -.ui-tooltip-jtools{ +.qtip-jtools{ background: #232323; background: rgba(0, 0, 0, 0.7); - background-image: -moz-linear-gradient(top, #717171, #232323); background-image: -webkit-gradient(linear, left top, left bottom, from(#717171), to(#232323)); - + background-image: -moz-linear-gradient(top, #717171, #232323); + background-image: -webkit-linear-gradient(top, #717171, #232323); + background-image: -ms-linear-gradient(top, #717171, #232323); + background-image: -o-linear-gradient(top, #717171, #232323); + border: 2px solid #ddd; border: 2px solid rgba(241,241,241,1); @@ -971,147 +869,128 @@ button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra pad } /* IE Specific */ - .ui-tooltip-jtools .ui-tooltip-titlebar{ + .qtip-jtools .qtip-titlebar{ + background-color: transparent; filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171,endColorstr=#4A4A4A); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171,endColorstr=#4A4A4A)"; } - .ui-tooltip-jtools .ui-tooltip-content{ + .qtip-jtools .qtip-content{ filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A,endColorstr=#232323); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A,endColorstr=#232323)"; } - .ui-tooltip-jtools .ui-tooltip-titlebar, - .ui-tooltip-jtools .ui-tooltip-content{ + .qtip-jtools .qtip-titlebar, + .qtip-jtools .qtip-content{ background: transparent; color: white; border: 0 dashed transparent; } - .ui-tooltip-jtools .ui-tooltip-icon{ + .qtip-jtools .qtip-icon{ border-color: #555; } - .ui-tooltip-jtools .ui-tooltip-titlebar .ui-state-hover{ + .qtip-jtools .qtip-titlebar .ui-state-hover{ border-color: #333; } /* Cluetip style */ -.ui-tooltip-cluetip{ +.qtip-cluetip{ -webkit-box-shadow: 4px 4px 5px rgba(0, 0, 0, 0.4); -moz-box-shadow: 4px 4px 5px rgba(0, 0, 0, 0.4); box-shadow: 4px 4px 5px rgba(0, 0, 0, 0.4); + + background-color: #D9D9C2; + color: #111; + border: 0 dashed transparent; } - .ui-tooltip-cluetip .ui-tooltip-titlebar{ + .qtip-cluetip .qtip-titlebar{ background-color: #87876A; color: white; border: 0 dashed transparent; } - - .ui-tooltip-cluetip .ui-tooltip-content{ - background-color: #D9D9C2; - color: #111; - border: 0 dashed transparent; - } - .ui-tooltip-cluetip .ui-tooltip-icon{ + .qtip-cluetip .qtip-icon{ border-color: #808064; } - .ui-tooltip-cluetip .ui-tooltip-titlebar .ui-state-hover{ + .qtip-cluetip .qtip-titlebar .ui-state-hover{ border-color: #696952; color: #696952; } /* Tipsy style */ -.ui-tooltip-tipsy{ - border: 0; -} - - .ui-tooltip-tipsy .ui-tooltip-titlebar, - .ui-tooltip-tipsy .ui-tooltip-content{ - _margin-bottom: 0; /* IE6 */ - .margin-bottom: 0; /* IE7 */ +.qtip-tipsy{ + background: black; + background: rgba(0, 0, 0, .87); - background: transparent; - background: rgba(0, 0, 0, .87); - filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#D9000000,endColorstr=#D9000000); - -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#D9000000,endColorstr=#D9000000)"; - - color: white; - border: 0px transparent; + color: white; + border: 0 solid transparent; - font-size: 11px; - font-family: 'Lucida Grande', sans-serif; - font-weight: bold; - line-height: 16px; - text-shadow: 0 1px black; - } + font-size: 11px; + font-family: 'Lucida Grande', sans-serif; + font-weight: bold; + line-height: 16px; + text-shadow: 0 1px black; +} - .ui-tooltip-tipsy .ui-tooltip-titlebar{ + .qtip-tipsy .qtip-titlebar{ padding: 6px 35px 0 10; + background-color: transparent; } - .ui-tooltip-tipsy .ui-tooltip-content{ + .qtip-tipsy .qtip-content{ padding: 6px 10; } - .ui-tooltip-tipsy .ui-tooltip-icon{ + .qtip-tipsy .qtip-icon{ border-color: #222; text-shadow: none; } - .ui-tooltip-tipsy .ui-tooltip-titlebar .ui-state-hover{ + .qtip-tipsy .qtip-titlebar .ui-state-hover{ border-color: #303030; } /* Tipped style */ -.ui-tooltip-tipped{ +.qtip-tipped{ + border: 3px solid #959FA9; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; + + background-color: #F9F9F9; + color: #454545; + + font-weight: normal; + font-family: serif; } - - .ui-tooltip-tipped .ui-tooltip-titlebar, - .ui-tooltip-tipped .ui-tooltip-content{ - border: 3px solid #959FA9; - filter: none; -ms-filter: none; - } + .qtip-tipped .qtip-titlebar{ + border-bottom-width: 0; - .ui-tooltip-tipped .ui-tooltip-titlebar{ + color: white; background: #3A79B8; - background-image: -moz-linear-gradient(top, #3A79B8, #2E629D); background-image: -webkit-gradient(linear, left top, left bottom, from(#3A79B8), to(#2E629D)); + background-image: -webkit-linear-gradient(top, #3A79B8, #2E629D); + background-image: -moz-linear-gradient(top, #3A79B8, #2E629D); + background-image: -ms-linear-gradient(top, #3A79B8, #2E629D); + background-image: -o-linear-gradient(top, #3A79B8, #2E629D); filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8,endColorstr=#2E629D); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8,endColorstr=#2E629D)"; - - color: white; - font-weight: normal; - font-family: serif; - - border-bottom-width: 0; - -moz-border-radius: 3px 3px 0 0; - -webkit-border-radius: 3px 3px 0 0; - border-radius: 3px 3px 0 0; - } - - .ui-tooltip-tipped .ui-tooltip-content{ - background-color: #F9F9F9; - color: #454545; - - -moz-border-radius: 0 0 3px 3px; - -webkit-border-radius: 0 0 3px 3px; - border-radius: 0 0 3px 3px; } - .ui-tooltip-tipped .ui-tooltip-icon{ + .qtip-tipped .qtip-icon{ border: 2px solid #285589; background: #285589; } - .ui-tooltip-tipped .ui-tooltip-icon .ui-icon{ + .qtip-tipped .qtip-icon .ui-icon{ background-color: #FBFBFB; color: #555; } @@ -1123,54 +1002,87 @@ button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra pad * Tested with IE 8, IE 9, Chrome 18, Firefox 9, Opera 11. * Does not work with IE 7. */ -.ui-tooltip-bootstrap{ - font-size: 13px; - line-height: 18px; - - *border-right-width: 2px; - *border-bottom-width: 2px; - - -webkit-border-radius: 5px; - -moz-border-radius: 5px; - border-radius: 5px; - +.qtip-bootstrap{ + /** Taken from Bootstrap body */ + font-size: 14px; + line-height: 20px; + color: #333333; + + /** Taken from Bootstrap .popover */ + padding: 1px; + background-color: #ffffff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - -webkit-background-clip: padding-box; -moz-background-clip: padding; background-clip: padding-box; } - .ui-tooltip-bootstrap .ui-tooltip-titlebar, - .ui-tooltip-bootstrap .ui-tooltip-content{ - color: #333333; - background-color: #ffffff; - - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.2); - } - - .ui-tooltip-bootstrap .ui-tooltip-titlebar{ - font-size: 18px; - line-height: 22px; - - border-bottom: 1px solid #ccc; + .qtip-bootstrap .qtip-titlebar{ + /** Taken from Bootstrap .popover-title */ + padding: 8px 14px; + margin: 0; + font-size: 14px; + font-weight: normal; + line-height: 18px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + -webkit-border-radius: 5px 5px 0 0; + -moz-border-radius: 5px 5px 0 0; + border-radius: 5px 5px 0 0; } - .ui-tooltip-bootstrap .ui-tooltip-titlebar .ui-state-default{ - right: 9px; top: 49%; + .qtip-bootstrap .qtip-titlebar .qtip-close{ + /** + * Overrides qTip2: + * .qtip-titlebar .qtip-close{ + * [...] + * right: 4px; + * top: 50%; + * [...] + * border-style: solid; + * } + */ + right: 11px; + top: 45%; border-style: none; } - .ui-tooltip-bootstrap .ui-tooltip-icon{ - background: white; + .qtip-bootstrap .qtip-content{ + /** Taken from Bootstrap .popover-content */ + padding: 9px 14px; + } + + .qtip-bootstrap .qtip-icon{ + /** + * Overrides qTip2: + * .qtip-default .qtip-icon { + * border-color: #CCC; + * background: #F1F1F1; + * color: #777; + * } + */ + background: transparent; } - .ui-tooltip-bootstrap .ui-tooltip-icon .ui-icon{ + .qtip-bootstrap .qtip-icon .ui-icon{ + /** + * Overrides qTip2: + * .qtip-icon .ui-icon{ + * width: 18px; + * height: 14px; + * } + */ width: auto; height: auto; + + /* Taken from Bootstrap .close */ float: right; font-size: 20px; font-weight: bold; @@ -1181,7 +1093,8 @@ button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra pad filter: alpha(opacity=20); } - .ui-tooltip-bootstrap .ui-tooltip-icon .ui-icon:hover{ + .qtip-bootstrap .qtip-icon .ui-icon:hover{ + /* Taken from Bootstrap .close:hover */ color: #000000; text-decoration: none; cursor: pointer; @@ -1191,13 +1104,64 @@ button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra pad /* IE9 fix - removes all filters */ -.ui-tooltip:not(.ie9haxors) div.ui-tooltip-content, -.ui-tooltip:not(.ie9haxors) div.ui-tooltip-titlebar{ +.qtip:not(.ie9haxors) div.qtip-content, +.qtip:not(.ie9haxors) div.qtip-titlebar{ filter: none; -ms-filter: none; } +/* Tips plugin */ +.qtip .qtip-tip{ + margin: 0 auto; + overflow: hidden; + z-index: 10; +} + + .qtip .qtip-tip, + .qtip .qtip-tip .qtip-vml{ + position: absolute; + + color: #123456; + background: transparent; + border: 0 dashed transparent; + } + + .qtip .qtip-tip canvas{ top: 0; left: 0; } + + .qtip .qtip-tip .qtip-vml{ + behavior: url(#default#VML); + display: inline-block; + visibility: visible; + } +/* Modal plugin */ +#qtip-overlay{ + position: fixed; + left: -10000em; + top: -10000em; +} + + /* Applied to modals with show.modal.blur set to true */ + #qtip-overlay.blurs{ cursor: pointer; } + + /* Change opacity of overlay here */ + #qtip-overlay div{ + position: absolute; + left: 0; top: 0; + width: 100%; height: 100%; + + background-color: black; + + opacity: 0.7; + filter:alpha(opacity=70); + -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=70)"; + } + + +/* IE6 Modal plugin fix */ +.qtipmodal-ie6fix{ + position: absolute !important; +} /* http://meyerweb.com/eric/tools/css/reset/ v2.0 | 20110126 License: none (public domain) @@ -1267,14 +1231,14 @@ body { #outer-wrapper { - background: url(http://www.khanacademy.org//images/light-page-bg.png) repeat-x; /*! data-uri(/images/light-page-bg.png) */ + background: url(http://www.khanacademy.org//images/light-page-bg.png) repeat-x; min-height: 100%; height: auto !important; height: 100%; margin: 0 0 -77px; } #page-container, #page-container-inner { - background: transparent url(http://www.khanacademy.org//images/content-border.1.png) no-repeat right 85px; /*! data-uri(/images/content-border.1.png) */ + background: transparent url(http://www.khanacademy.org//images/content-border.1.png) no-repeat right 85px; } #page-container { background-position: 0 85px; @@ -1452,7 +1416,7 @@ form { display: inline; } */ .ui-autocomplete { position: absolute; cursor: default; } -.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(http://www.khanacademy.org/../jqueryui-package/images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; } +.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(http://www.khanacademy.org//stylesheets/jqueryui-package/images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; } .ui-autocomplete.ui-menu { padding:0; @@ -1507,6 +1471,7 @@ ul.ui-autocomplete .ui-menu-item .autocomplete-empty { .autocomplete-spacer { height: 7px; } + header, footer { display: block; width: 100%; @@ -1516,7 +1481,7 @@ header, footer { footer { height: 208px; clear: both; - background: url(http://www.khanacademy.org//images/footer-bg.png) repeat-x 0 0; /*! data-uri(/images/footer-bg.png) */ + background: url(http://www.khanacademy.org//images/footer-bg.png) repeat-x 0 0; min-width: 970px; position: relative; } @@ -1659,13 +1624,13 @@ footer { width: 280px; height: 68px; background-position: 0 0; - background-image: url(http://www.khanacademy.org//images/ka-logo.png); /*! data-uri(/images/ka-logo.png) */ + background-image: url(http://www.khanacademy.org//images/ka-logo.png); /*! data-uri */ background-size: 100%; } @media only screen and (-webkit-min-device-pixel-ratio: 2) { #logo-image { - background-image: url(http://www.khanacademy.org//images/ka-logo_2x.png); /*! data-uri(/images/ka-logo_2x.png) */ + background-image: url(http://www.khanacademy.org//images/ka-logo_2x.png); /*! data-uri */ } } @@ -3084,15 +3049,15 @@ div.arrow-right, div.arrow-left { .qtip.custom-override { max-width: 400px; } -.ui-tooltip-default.custom-override { +.qtip-default.custom-override { border-color: transparent; background-color: transparent; } - .ui-tooltip-default.custom-override .ui-tooltip-tip { + .qtip-default.custom-override .qtip-tip { /* Because qtip seems to add inline styles in IE */ display: none !important; } - .ui-tooltip-default.custom-override .ui-tooltip-content { + .qtip-default.custom-override .qtip-content { border: none; background-color: transparent; padding: 0 0 10px 0; @@ -3183,6 +3148,7 @@ div.arrow-right, div.arrow-left { color: #999; font-size: 90%; } + /* Start knowledge map CSS */ .nodeLabel { display: block; @@ -3215,15 +3181,15 @@ a.nodeLabel:hover { display: inline-block; } -.node-icon.node-complete { background: url(http://www.khanacademy.org//images/node-complete.png?glove); /*! data-uri(/images/node-complete.png) */ } -.node-icon.node-review { background: url(http://www.khanacademy.org//images/node-review.png?glove); /*! data-uri(/images/node-review.png) */ } -.node-icon.node-suggested { background: url(http://www.khanacademy.org//images/node-suggested.png?glove); /*! data-uri(/images/node-suggested.png) */ } -.node-icon.node-not-started { background: url(http://www.khanacademy.org//images/node-not-started.png?glove); /*! data-uri(/images/node-not-started.png) */ } +.node-icon.node-complete { background: url(http://www.khanacademy.org//images/node-complete.png?glove); } /*! data-uri */ +.node-icon.node-review { background: url(http://www.khanacademy.org//images/node-review.png?glove); } /*! data-uri */ +.node-icon.node-suggested { background: url(http://www.khanacademy.org//images/node-suggested.png?glove); } /*! data-uri */ +.node-icon.node-not-started { background: url(http://www.khanacademy.org//images/node-not-started.png?glove); } /*! data-uri */ -.nodeLabelFiltered .node-icon.node-complete { background: url(http://www.khanacademy.org//images/node-complete-faded.png?glove); /*! data-uri(/images/node-complete-faded.png) */ } -.nodeLabelFiltered .node-icon.node-review { background: url(http://www.khanacademy.org//images/node-review-faded.png?glove); /*! data-uri(/images/node-review-faded.png) */ } -.nodeLabelFiltered .node-icon.node-suggested { background: url(http://www.khanacademy.org//images/node-suggested-faded.png?glove); /*! data-uri(/images/node-suggested-faded.png) */ } -.nodeLabelFiltered .node-icon.node-not-started { background: url(http://www.khanacademy.org//images/node-not-started-faded.png?glove); /*! data-uri(/images/node-not-started-faded.png) */ } +.nodeLabelFiltered .node-icon.node-complete { background: url(http://www.khanacademy.org//images/node-complete-faded.png?glove); } /*! data-uri */ +.nodeLabelFiltered .node-icon.node-review { background: url(http://www.khanacademy.org//images/node-review-faded.png?glove); } /*! data-uri */ +.nodeLabelFiltered .node-icon.node-suggested { background: url(http://www.khanacademy.org//images/node-suggested-faded.png?glove); } /*! data-uri */ +.nodeLabelFiltered .node-icon.node-not-started { background: url(http://www.khanacademy.org//images/node-not-started-faded.png?glove); } /*! data-uri */ .zoom10 .nodeLabel { position: relative; @@ -3256,15 +3222,15 @@ a.nodeLabel:hover { height: 40px; } -.zoom9 .nodeLabel.exercise .node-icon.node-complete { background: url(http://www.khanacademy.org//images/node-complete-40.png?glove); /*! data-uri(/images/node-complete-40.png) */ } -.zoom9 .nodeLabel.exercise .node-icon.node-review { background: url(http://www.khanacademy.org//images/node-review-40.png?glove); /*! data-uri(/images/node-review-40.png) */ } -.zoom9 .nodeLabel.exercise .node-icon.node-suggested { background: url(http://www.khanacademy.org//images/node-suggested-40.png?glove); /*! data-uri(/images/node-suggested-40.png) */ } -.zoom9 .nodeLabel.exercise .node-icon.node-not-started { background: url(http://www.khanacademy.org//images/node-not-started-40.png?glove); /*! data-uri(/images/node-not-started-40.png) */ } +.zoom9 .nodeLabel.exercise .node-icon.node-complete { background: url(http://www.khanacademy.org//images/node-complete-40.png?glove); } +.zoom9 .nodeLabel.exercise .node-icon.node-review { background: url(http://www.khanacademy.org//images/node-review-40.png?glove); } +.zoom9 .nodeLabel.exercise .node-icon.node-suggested { background: url(http://www.khanacademy.org//images/node-suggested-40.png?glove); } +.zoom9 .nodeLabel.exercise .node-icon.node-not-started { background: url(http://www.khanacademy.org//images/node-not-started-40.png?glove); } -.zoom9 .nodeLabelFiltered.exercise .node-icon.node-complete { background: url(http://www.khanacademy.org//images/node-complete-40-faded.png?glove); /*! data-uri(/images/node-complete-40-faded.png) */ } -.zoom9 .nodeLabelFiltered.exercise .node-icon.node-review { background: url(http://www.khanacademy.org//images/node-review-40-faded.png?glove); /*! data-uri(/images/node-review-40-faded.png) */ } -.zoom9 .nodeLabelFiltered.exercise .node-icon.node-suggested { background: url(http://www.khanacademy.org//images/node-suggested-40-faded.png?glove); /*! data-uri(/images/node-suggested-40-faded.png) */ } -.zoom9 .nodeLabelFiltered.exercise .node-icon.node-not-started { background: url(http://www.khanacademy.org//images/node-not-started-40-faded.png?glove); /*! data-uri(/images/node-not-started-40-faded.png) */ } +.zoom9 .nodeLabelFiltered.exercise .node-icon.node-complete { background: url(http://www.khanacademy.org//images/node-complete-40-faded.png?glove); } +.zoom9 .nodeLabelFiltered.exercise .node-icon.node-review { background: url(http://www.khanacademy.org//images/node-review-40-faded.png?glove); } +.zoom9 .nodeLabelFiltered.exercise .node-icon.node-suggested { background: url(http://www.khanacademy.org//images/node-suggested-40-faded.png?glove); } +.zoom9 .nodeLabelFiltered.exercise .node-icon.node-not-started { background: url(http://www.khanacademy.org//images/node-not-started-40-faded.png?glove); } .zoom7 .nodeLabel.exercise .node-icon { width: 10px; @@ -3274,15 +3240,15 @@ a.nodeLabel:hover { display: none; } -.zoom7 .nodeLabel.exercise .node-icon.node-complete { background: url(http://www.khanacademy.org//images/node-complete-10.png?glove); /*! data-uri(/images/node-complete-10.png) */ } -.zoom7 .nodeLabel.exercise .node-icon.node-review { background: url(http://www.khanacademy.org//images/node-review-10.png?glove); /*! data-uri(/images/node-review-10.png) */ } -.zoom7 .nodeLabel.exercise .node-icon.node-suggested { background: url(http://www.khanacademy.org//images/node-suggested-10.png?glove); /*! data-uri(/images/node-suggested-10.png) */ } -.zoom7 .nodeLabel.exercise .node-icon.node-not-started { background: url(http://www.khanacademy.org//images/node-not-started-10.png?glove); /*! data-uri(/images/node-not-started-10.png) */ } +.zoom7 .nodeLabel.exercise .node-icon.node-complete { background: url(http://www.khanacademy.org//images/node-complete-10.png?glove); } +.zoom7 .nodeLabel.exercise .node-icon.node-review { background: url(http://www.khanacademy.org//images/node-review-10.png?glove); } +.zoom7 .nodeLabel.exercise .node-icon.node-suggested { background: url(http://www.khanacademy.org//images/node-suggested-10.png?glove); } +.zoom7 .nodeLabel.exercise .node-icon.node-not-started { background: url(http://www.khanacademy.org//images/node-not-started-10.png?glove); } -.zoom7 .nodeLabelFiltered.exercise .node-icon.node-complete { background: url(http://www.khanacademy.org//images/node-complete-10-faded.png?glove); /*! data-uri(/images/node-complete-10-faded.png) */ } -.zoom7 .nodeLabelFiltered.exercise .node-icon.node-review { background: url(http://www.khanacademy.org//images/node-review-10-faded.png?glove); /*! data-uri(/images/node-review-10-faded.png) */ } -.zoom7 .nodeLabelFiltered.exercise .node-icon.node-suggested { background: url(http://www.khanacademy.org//images/node-suggested-10-faded.png?glove); /*! data-uri(/images/node-suggested-10-faded.png) */ } -.zoom7 .nodeLabelFiltered.exercise .node-icon.node-not-started { background: url(http://www.khanacademy.org//images/node-not-started-10-faded.png?glove); /*! data-uri(/images/node-not-started-10-faded.png) */ } +.zoom7 .nodeLabelFiltered.exercise .node-icon.node-complete { background: url(http://www.khanacademy.org//images/node-complete-10-faded.png?glove); } +.zoom7 .nodeLabelFiltered.exercise .node-icon.node-review { background: url(http://www.khanacademy.org//images/node-review-10-faded.png?glove); } +.zoom7 .nodeLabelFiltered.exercise .node-icon.node-suggested { background: url(http://www.khanacademy.org//images/node-suggested-10-faded.png?glove); } +.zoom7 .nodeLabelFiltered.exercise .node-icon.node-not-started { background: url(http://www.khanacademy.org//images/node-not-started-10-faded.png?glove); } .lte7 .zoom6 .nodeLabel .node-icon, .lte7 .zoom7 .nodeLabel.topic .node-icon, @@ -3310,15 +3276,15 @@ a.nodeLabel:hover { margin-left: 18px; } -.zoom8 .nodeLabel.exercise .node-icon.node-complete { background: url(http://www.khanacademy.org//images/node-complete-26.png?glove); /*! data-uri(/images/node-complete-26.png) */ } -.zoom8 .nodeLabel.exercise .node-icon.node-review { background: url(http://www.khanacademy.org//images/node-review-26.png?glove); /*! data-uri(/images/node-review-26.png) */ } -.zoom8 .nodeLabel.exercise .node-icon.node-suggested { background: url(http://www.khanacademy.org//images/node-suggested-26.png?glove); /*! data-uri(/images/node-suggested-26.png) */ } -.zoom8 .nodeLabel.exercise .node-icon.node-not-started { background: url(http://www.khanacademy.org//images/node-not-started-26.png?glove); /*! data-uri(/images/node-not-started-26.png) */ } +.zoom8 .nodeLabel.exercise .node-icon.node-complete { background: url(http://www.khanacademy.org//images/node-complete-26.png?glove); } +.zoom8 .nodeLabel.exercise .node-icon.node-review { background: url(http://www.khanacademy.org//images/node-review-26.png?glove); } +.zoom8 .nodeLabel.exercise .node-icon.node-suggested { background: url(http://www.khanacademy.org//images/node-suggested-26.png?glove); } +.zoom8 .nodeLabel.exercise .node-icon.node-not-started { background: url(http://www.khanacademy.org//images/node-not-started-26.png?glove); } -.zoom8 .nodeLabelFiltered.exercise .node-icon.node-complete { background: url(http://www.khanacademy.org//images/node-complete-26-faded.png?glove); /*! data-uri(/images/node-complete-26-faded.png) */ } -.zoom8 .nodeLabelFiltered.exercise .node-icon.node-review { background: url(http://www.khanacademy.org//images/node-review-26-faded.png?glove); /*! data-uri(/images/node-review-26-faded.png) */ } -.zoom8 .nodeLabelFiltered.exercise .node-icon.node-suggested { background: url(http://www.khanacademy.org//images/node-suggested-26-faded.png?glove); /*! data-uri(/images/node-suggested-26-faded.png) */ } -.zoom8 .nodeLabelFiltered.exercise .node-icon.node-not-started { background: url(http://www.khanacademy.org//images/node-not-started-26-faded.png?glove); /*! data-uri(/images/node-not-started-26-faded.png) */ } +.zoom8 .nodeLabelFiltered.exercise .node-icon.node-complete { background: url(http://www.khanacademy.org//images/node-complete-26-faded.png?glove); } +.zoom8 .nodeLabelFiltered.exercise .node-icon.node-review { background: url(http://www.khanacademy.org//images/node-review-26-faded.png?glove); } +.zoom8 .nodeLabelFiltered.exercise .node-icon.node-suggested { background: url(http://www.khanacademy.org//images/node-suggested-26-faded.png?glove); } +.zoom8 .nodeLabelFiltered.exercise .node-icon.node-not-started { background: url(http://www.khanacademy.org//images/node-not-started-26-faded.png?glove); } .zoom6 .nodeLabel.exercise { display: none; @@ -3446,7 +3412,7 @@ input[type=number]::-webkit-inner-spin-button, input[type=number]::-webkit-outer .mobile-only { display: none; } -/* Shared by both versions of the homepage +/* Shared by both versions of the homepage * #social-actions, #rss-feed */ #social-actions { @@ -3474,7 +3440,7 @@ input[type=number]::-webkit-inner-spin-button, input[type=number]::-webkit-outer display: inline-block; } -/* Used on about pages and blog +/* Used on about pages and blog * .rounded-background */ img.rounded-background { @@ -3632,7 +3598,7 @@ span.youTube:hover { /* End of exercise related styles */ -/* Used in exercise_message_proficient_withgraph.html +/* Used in exercise_message_proficient_withgraph.html * TODO(jasonrr) determine if that file is still in use */ #you-are-here{ position:relative; @@ -3853,7 +3819,7 @@ a.control:hover { color: #DD6900; } font-size: 12px; } -.ui-tooltip, .qtip { +.qtip { font-size: 100%; line-height: 1.3; } @@ -4196,13 +4162,51 @@ a.control:hover { color: #DD6900; } -moz-box-sizing: border-box; -ms-box-sizing: border-box; box-sizing: border-box; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + -ms-box-sizing: border-box; + box-sizing: border-box; +} +#khanType .thinHeader { + color: #2c3747; + display: block; + font-family: "MuseoSans300", sans-serif; + font-size: 24px; + font-weight: normal; +} +#khanType .smallThinHeader { + color: #555; + display: block; + font-family: "MuseoSans300", sans-serif; + font-size: 18px; + font-weight: normal; + line-height: 22px; +} +#khanType .headerDescription { + color: #a9c0d1; + display: block; + font-family: "MuseoSans300", sans-serif; + font-size: 13px; + font-weight: normal; + line-height: 22px; + margin-top: 2px; } .vertical-shadow { + border: 1px solid #cccccc; border: 1px solid #cccccc; border-bottom: 1px solid #aaa; -webkit-box-shadow: 0 1px 3px #cccccc; -moz-box-shadow: 0 1px 3px #cccccc; box-shadow: 0 1px 3px #cccccc; + -webkit-box-shadow: 0 1px 3px #cccccc; + -moz-box-shadow: 0 1px 3px #cccccc; + box-shadow: 0 1px 3px #cccccc; + -webkit-box-shadow: 0 1px 3px #cccccc; + -moz-box-shadow: 0 1px 3px #cccccc; + box-shadow: 0 1px 3px #cccccc; + -webkit-box-shadow: 0 1px 3px #cccccc; + -moz-box-shadow: 0 1px 3px #cccccc; + box-shadow: 0 1px 3px #cccccc; } .alert { padding: 8px 35px 8px 14px; @@ -4213,6 +4217,15 @@ a.control:hover { color: #DD6900; } -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; color: #c09853; } .alert-heading { @@ -4260,6 +4273,8 @@ a.control:hover { color: #DD6900; } text-shadow: 0 1px 0 #ffffff; opacity: 0.2; filter: alpha(opacity=20); + opacity: 0.2; + filter: alpha(opacity=20); } .close:hover { color: #000000; @@ -4267,6 +4282,8 @@ a.control:hover { color: #DD6900; } cursor: pointer; opacity: 0.4; filter: alpha(opacity=40); + opacity: 0.4; + filter: alpha(opacity=40); } button.close { padding: 0; @@ -4282,6 +4299,11 @@ button.close { -ms-transition: opacity 0.15s linear; -o-transition: opacity 0.15s linear; transition: opacity 0.15s linear; + -webkit-transition: opacity 0.15s linear; + -moz-transition: opacity 0.15s linear; + -ms-transition: opacity 0.15s linear; + -o-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; } .fade.in { opacity: 1; @@ -4295,6 +4317,11 @@ button.close { -ms-transition: height 0.35s ease; -o-transition: height 0.35s ease; transition: height 0.35s ease; + -webkit-transition: height 0.35s ease; + -moz-transition: height 0.35s ease; + -ms-transition: height 0.35s ease; + -o-transition: height 0.35s ease; + transition: height 0.35s ease; } .collapse.in { height: auto; @@ -4308,13 +4335,31 @@ button.close { -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; -webkit-box-shadow: inset 0 0 4px rgba(0, 0, 0, 0.3); -moz-box-shadow: inset 0 0 4px rgba(0, 0, 0, 0.3); box-shadow: inset 0 0 4px rgba(0, 0, 0, 0.3); -} -.skill-bar .description { - position: relative; - color: #fff; + -webkit-box-shadow: inset 0 0 4px rgba(0, 0, 0, 0.3); + -moz-box-shadow: inset 0 0 4px rgba(0, 0, 0, 0.3); + box-shadow: inset 0 0 4px rgba(0, 0, 0, 0.3); + -webkit-box-shadow: inset 0 0 4px rgba(0, 0, 0, 0.3); + -moz-box-shadow: inset 0 0 4px rgba(0, 0, 0, 0.3); + box-shadow: inset 0 0 4px rgba(0, 0, 0, 0.3); + -webkit-box-shadow: inset 0 0 4px rgba(0, 0, 0, 0.3); + -moz-box-shadow: inset 0 0 4px rgba(0, 0, 0, 0.3); + box-shadow: inset 0 0 4px rgba(0, 0, 0, 0.3); +} +.skill-bar .description { + position: relative; + color: #fff; line-height: 17px; /* This needs to be adjusted if you adjust the skill-bar height */ @@ -4327,6 +4372,24 @@ button.close { -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + background-color: #3bd453; + background-image: -moz-linear-gradient(top, #2bc253, #54f054); + background-image: -ms-linear-gradient(top, #2bc253, #54f054); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#2bc253), to(#54f054)); + background-image: -webkit-linear-gradient(top, #2bc253, #54f054); + background-image: -o-linear-gradient(top, #2bc253, #54f054); + background-image: linear-gradient(top, #2bc253, #54f054); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#2bc253', endColorstr='#54f054', GradientType=0); background-color: #3bd453; background-image: -moz-linear-gradient(top, #2bc253, #54f054); background-image: -ms-linear-gradient(top, #2bc253, #54f054); @@ -4339,6 +4402,15 @@ button.close { -webkit-box-shadow: inset 0 2px 9px rgba(255,255,255,0.3); -moz-box-shadow: inset 0 2px 9px rgba(255,255,255,0.3); box-shadow: inset 0 2px 9px rgba(255,255,255,0.3); + -webkit-box-shadow: inset 0 2px 9px rgba(255,255,255,0.3); + -moz-box-shadow: inset 0 2px 9px rgba(255,255,255,0.3); + box-shadow: inset 0 2px 9px rgba(255,255,255,0.3); + -webkit-box-shadow: inset 0 2px 9px rgba(255,255,255,0.3); + -moz-box-shadow: inset 0 2px 9px rgba(255,255,255,0.3); + box-shadow: inset 0 2px 9px rgba(255,255,255,0.3); + -webkit-box-shadow: inset 0 2px 9px rgba(255,255,255,0.3); + -moz-box-shadow: inset 0 2px 9px rgba(255,255,255,0.3); + box-shadow: inset 0 2px 9px rgba(255,255,255,0.3); position: relative; overflow: hidden; } @@ -4352,6 +4424,15 @@ button.close { background-image: linear-gradient(top, #dddddd, #cccccc); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#dddddd', endColorstr='#cccccc', GradientType=0); + background-color: #d6d6d6; + background-image: -moz-linear-gradient(top, #dddddd, #cccccc); + background-image: -ms-linear-gradient(top, #dddddd, #cccccc); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#dddddd), to(#cccccc)); + background-image: -webkit-linear-gradient(top, #dddddd, #cccccc); + background-image: -o-linear-gradient(top, #dddddd, #cccccc); + background-image: linear-gradient(top, #dddddd, #cccccc); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#dddddd', endColorstr='#cccccc', GradientType=0); } .skill-bar .fill.green { background-color: #7fac05; @@ -4363,6 +4444,15 @@ button.close { background-image: linear-gradient(top, #8aba08, #6e9700); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#8aba08', endColorstr='#6e9700', GradientType=0); + background-color: #7fac05; + background-image: -moz-linear-gradient(top, #8aba08, #6e9700); + background-image: -ms-linear-gradient(top, #8aba08, #6e9700); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#8aba08), to(#6e9700)); + background-image: -webkit-linear-gradient(top, #8aba08, #6e9700); + background-image: -o-linear-gradient(top, #8aba08, #6e9700); + background-image: linear-gradient(top, #8aba08, #6e9700); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#8aba08', endColorstr='#6e9700', GradientType=0); } .skill-bar .fill.blue { background-color: #0093e8; @@ -4374,6 +4464,15 @@ button.close { background-image: linear-gradient(top, #00a0fc, #0080c9); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00a0fc', endColorstr='#0080c9', GradientType=0); + background-color: #0093e8; + background-image: -moz-linear-gradient(top, #00a0fc, #0080c9); + background-image: -ms-linear-gradient(top, #00a0fc, #0080c9); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#00a0fc), to(#0080c9)); + background-image: -webkit-linear-gradient(top, #00a0fc, #0080c9); + background-image: -o-linear-gradient(top, #00a0fc, #0080c9); + background-image: linear-gradient(top, #00a0fc, #0080c9); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00a0fc', endColorstr='#0080c9', GradientType=0); } .skill-bar .fill.orange { background-color: #ed6224; @@ -4385,6 +4484,15 @@ button.close { background-image: linear-gradient(top, #f46626, #e35d22); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f46626', endColorstr='#e35d22', GradientType=0); + background-color: #ed6224; + background-image: -moz-linear-gradient(top, #f46626, #e35d22); + background-image: -ms-linear-gradient(top, #f46626, #e35d22); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f46626), to(#e35d22)); + background-image: -webkit-linear-gradient(top, #f46626, #e35d22); + background-image: -o-linear-gradient(top, #f46626, #e35d22); + background-image: linear-gradient(top, #f46626, #e35d22); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f46626', endColorstr='#e35d22', GradientType=0); } .skill-bar .fill.gray { position: relative; @@ -4409,19 +4517,15 @@ button.close { } .small-exercise-icon.node-complete { background: url(http://www.khanacademy.org//images/node-complete-20.png); - /*! data-uri(/images/node-complete-20.png) */ } .small-exercise-icon.node-review { background: url(http://www.khanacademy.org//images/node-review-20.png); - /*! data-uri(/images/node-review-20.png) */ } .small-exercise-icon.node-suggested { background: url(http://www.khanacademy.org//images/node-suggested-20.png); - /*! data-uri(/images/node-suggested-20.png) */ } .small-exercise-icon.node-not-started { background: url(http://www.khanacademy.org//images/node-not-started-20.png); - /*! data-uri(/images/node-not-started-20.png) */ } .topic-exercise-badge { float: left; @@ -4437,6 +4541,15 @@ button.close { -webkit-border-radius: 20px; -moz-border-radius: 20px; border-radius: 20px; + -webkit-border-radius: 20px; + -moz-border-radius: 20px; + border-radius: 20px; + -webkit-border-radius: 20px; + -moz-border-radius: 20px; + border-radius: 20px; + -webkit-border-radius: 20px; + -moz-border-radius: 20px; + border-radius: 20px; } .dropdown-toggle { cursor: pointer; @@ -4463,38 +4576,118 @@ button.close { -moz-background-clip: padding; -webkit-background-clip: padding-box; background-clip: padding-box; + -webkit-border-top-right-radius: 5px; + -webkit-border-bottom-right-radius: 0; + -webkit-border-bottom-left-radius: 0; + -webkit-border-top-left-radius: 5px; + -moz-border-radius-topright: 5px; + -moz-border-radius-bottomright: 0; + -moz-border-radius-bottomleft: 0; + -moz-border-radius-topleft: 5px; + border-top-right-radius: 5px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; + border-top-left-radius: 5px; + -moz-background-clip: padding; + -webkit-background-clip: padding-box; + background-clip: padding-box; } .right-arrow { + top: 50%; + right: 0; + margin-top: -3px; + border-top: 3px solid transparent; + border-bottom: 3px solid transparent; + border-left: 3px solid #000000; + top: 50%; + right: 0; + border-top: 3px solid transparent; + border-bottom: 3px solid transparent; + border-left: 3px solid #444444; + border-top: 3px solid transparent; + border-bottom: 3px solid transparent; + border-left: 3px solid #444444; + top: 50%; + right: 0; + margin-top: -3px; + border-top: 3px solid transparent; + border-bottom: 3px solid transparent; border-left: 3px solid #000000; top: 50%; right: 0; border-top: 3px solid transparent; border-bottom: 3px solid transparent; border-left: 3px solid #444444; + border-top: 3px solid transparent; + border-bottom: 3px solid transparent; + border-left: 3px solid #444444; position: absolute; right: 6px; margin-top: -3px; } .caret { + bottom: 0; + left: 50%; + margin-left: -4px; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 4px solid #000000; + bottom: 0; + left: 50%; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 4px solid #444444; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 4px solid #444444; + bottom: 0; + left: 50%; margin-left: -4px; + border-left: 4px solid transparent; + border-right: 4px solid transparent; border-top: 4px solid #000000; bottom: 0; left: 50%; border-left: 4px solid transparent; border-right: 4px solid transparent; border-top: 4px solid #444444; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 4px solid #444444; display: inline-block; margin-left: 2px; margin-bottom: 2px; } .dropdown-toggle:hover .caret, .open.dropdown .caret { + bottom: 0; + left: 50%; + margin-left: -4px; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 4px solid #ffffff; + bottom: 0; + left: 50%; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 4px solid #ffffff; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 4px solid #ffffff; + bottom: 0; + left: 50%; margin-left: -4px; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 4px solid #ffffff; bottom: 0; left: 50%; border-left: 4px solid transparent; border-right: 4px solid transparent; border-top: 4px solid #ffffff; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 4px solid #ffffff; margin-left: 2px; } .dropdown.open > .dropdown-menu { @@ -4510,6 +4703,18 @@ button.close { border-color: #94a170; padding: 3px 0; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 12px; + font-weight: normal; + line-height: 24px; + font-size: 12px; + font-weight: normal; + line-height: 24px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 12px; + font-weight: normal; + line-height: 24px; font-size: 12px; font-weight: normal; line-height: 24px; @@ -4518,6 +4723,15 @@ button.close { -webkit-box-shadow: 0 5px 8px #444444; -moz-box-shadow: 0 5px 8px #444444; box-shadow: 0 5px 8px #444444; + -webkit-box-shadow: 0 5px 8px #444444; + -moz-box-shadow: 0 5px 8px #444444; + box-shadow: 0 5px 8px #444444; + -webkit-box-shadow: 0 5px 8px #444444; + -moz-box-shadow: 0 5px 8px #444444; + box-shadow: 0 5px 8px #444444; + -webkit-box-shadow: 0 5px 8px #444444; + -moz-box-shadow: 0 5px 8px #444444; + box-shadow: 0 5px 8px #444444; } .dropdown-menu li { position: relative; @@ -4534,7 +4748,6 @@ button.close { color: #444444; border-top: 1px solid transparent; border-bottom: 1px solid transparent; - -webkit-transform: translate3d(0, 0, 0); } .dropdown-menu > li > a { color: #444444; @@ -4554,7 +4767,6 @@ button.close { background-color: #89b908; border-top: 1px solid #76a005; border-bottom: 1px solid #76a005; - -webkit-transform: translate3d(0, 0, 0); } .dropdown-menu.child-active > li.hover-active > a, .dropdown-menu.none-active > li:hover > a, @@ -4566,17 +4778,38 @@ button.close { color: #ffffff; font-weight: bold; text-decoration: none; - -webkit-transform: translateY(-1px); } .dropdown-menu.child-active > li.hover-active > div.right-arrow, .dropdown-menu.none-active > li:hover > div.right-arrow, .dropdown-menu.no-submenus > li:hover > div.right-arrow { + top: 50%; + right: 0; + margin-top: -3px; + border-top: 3px solid transparent; + border-bottom: 3px solid transparent; + border-left: 3px solid #ffffff; + top: 50%; + right: 0; + border-top: 3px solid transparent; + border-bottom: 3px solid transparent; + border-left: 3px solid #ffffff; + border-top: 3px solid transparent; + border-bottom: 3px solid transparent; + border-left: 3px solid #ffffff; + top: 50%; + right: 0; margin-top: -3px; + border-top: 3px solid transparent; + border-bottom: 3px solid transparent; + border-left: 3px solid #ffffff; top: 50%; right: 0; border-top: 3px solid transparent; border-bottom: 3px solid transparent; border-left: 3px solid #ffffff; + border-top: 3px solid transparent; + border-bottom: 3px solid transparent; + border-left: 3px solid #ffffff; position: absolute; right: 6px; } @@ -4599,10 +4832,22 @@ button.close { bottom: 0px; text-shadow: none; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 9px; + font-weight: normal; + line-height: 17px; + font-size: 9px; + font-weight: normal; + line-height: 17px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 9px; + font-weight: normal; + line-height: 17px; font-size: 9px; font-weight: normal; line-height: 17px; - -webkit-transform: translateY(0px); + -webkit-transform: translatey(0px); } .dropdown-menu > li.hover-active > ul { display: block; @@ -4631,6 +4876,9 @@ button.close { -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25); -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25); + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25); + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25); } ul.topic-browser-menu.new > li > ul { width: 100%; @@ -4669,6 +4917,24 @@ ul.topic-browser-menu.new > li > ul { -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255, .3); + -moz-box-shadow: inset 0 1px 0 rgba(255,255,255, .3); + box-shadow: inset 0 1px 0 rgba(255,255,255, .3); + -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255, .3); + -moz-box-shadow: inset 0 1px 0 rgba(255,255,255, .3); + box-shadow: inset 0 1px 0 rgba(255,255,255, .3); + -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255, .3); + -moz-box-shadow: inset 0 1px 0 rgba(255,255,255, .3); + box-shadow: inset 0 1px 0 rgba(255,255,255, .3); -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255, .3); -moz-box-shadow: inset 0 1px 0 rgba(255,255,255, .3); box-shadow: inset 0 1px 0 rgba(255,255,255, .3); @@ -4681,14 +4947,89 @@ ul.topic-browser-menu.new > li > ul { background-image: linear-gradient(top, #ffffff, #eeeeee); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0); + background-color: #f8f8f8; + background-image: -moz-linear-gradient(top, #ffffff, #eeeeee); + background-image: -ms-linear-gradient(top, #ffffff, #eeeeee); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#eeeeee)); + background-image: -webkit-linear-gradient(top, #ffffff, #eeeeee); + background-image: -o-linear-gradient(top, #ffffff, #eeeeee); + background-image: linear-gradient(top, #ffffff, #eeeeee); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0); border-color: #eeeeee #eeeeee #c8c8c8; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - *background-color: #eeeeee; - /* Darken IE7 buttons by default so they stand out more given they won't have borders */ - - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - color: #595959 !important; - cursor: pointer !important; + background-color: #f8f8f8; + background-image: -moz-linear-gradient(top, #ffffff, #eeeeee); + background-image: -ms-linear-gradient(top, #ffffff, #eeeeee); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#eeeeee)); + background-image: -webkit-linear-gradient(top, #ffffff, #eeeeee); + background-image: -o-linear-gradient(top, #ffffff, #eeeeee); + background-image: linear-gradient(top, #ffffff, #eeeeee); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0); + background-color: #f8f8f8; + background-image: -moz-linear-gradient(top, #ffffff, #eeeeee); + background-image: -ms-linear-gradient(top, #ffffff, #eeeeee); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#eeeeee)); + background-image: -webkit-linear-gradient(top, #ffffff, #eeeeee); + background-image: -o-linear-gradient(top, #ffffff, #eeeeee); + background-image: linear-gradient(top, #ffffff, #eeeeee); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0); + border-color: #eeeeee #eeeeee #c8c8c8; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #eeeeee; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + background-color: #f8f8f8; + background-image: -moz-linear-gradient(top, #ffffff, #eeeeee); + background-image: -ms-linear-gradient(top, #ffffff, #eeeeee); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#eeeeee)); + background-image: -webkit-linear-gradient(top, #ffffff, #eeeeee); + background-image: -o-linear-gradient(top, #ffffff, #eeeeee); + background-image: linear-gradient(top, #ffffff, #eeeeee); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0); + background-color: #f8f8f8; + background-image: -moz-linear-gradient(top, #ffffff, #eeeeee); + background-image: -ms-linear-gradient(top, #ffffff, #eeeeee); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#eeeeee)); + background-image: -webkit-linear-gradient(top, #ffffff, #eeeeee); + background-image: -o-linear-gradient(top, #ffffff, #eeeeee); + background-image: linear-gradient(top, #ffffff, #eeeeee); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0); + border-color: #eeeeee #eeeeee #c8c8c8; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + background-color: #f8f8f8; + background-image: -moz-linear-gradient(top, #ffffff, #eeeeee); + background-image: -ms-linear-gradient(top, #ffffff, #eeeeee); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#eeeeee)); + background-image: -webkit-linear-gradient(top, #ffffff, #eeeeee); + background-image: -o-linear-gradient(top, #ffffff, #eeeeee); + background-image: linear-gradient(top, #ffffff, #eeeeee); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0); + background-color: #f8f8f8; + background-image: -moz-linear-gradient(top, #ffffff, #eeeeee); + background-image: -ms-linear-gradient(top, #ffffff, #eeeeee); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#eeeeee)); + background-image: -webkit-linear-gradient(top, #ffffff, #eeeeee); + background-image: -o-linear-gradient(top, #ffffff, #eeeeee); + background-image: linear-gradient(top, #ffffff, #eeeeee); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0); + border-color: #eeeeee #eeeeee #c8c8c8; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #eeeeee; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + color: #595959 !important; + cursor: pointer !important; font-family: inherit; /* input[type=button] won't inherit by default */ @@ -4698,6 +5039,7 @@ ul.topic-browser-menu.new > li > ul { position: relative; text-decoration: none !important; text-shadow: 0 -1px 0 #ffffff; + -webkit-appearance: none; /* Special button types */ } @@ -4730,12 +5072,30 @@ ul.topic-browser-menu.new > li > ul { -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255, .4), inset 0 0 50px 5px rgba(255,255,255,.2); -moz-box-shadow: inset 0 1px 0 rgba(255,255,255, .4), inset 0 0 50px 5px rgba(255,255,255,.2); box-shadow: inset 0 1px 0 rgba(255,255,255, .4), inset 0 0 50px 5px rgba(255,255,255,.2); + -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255, .4), inset 0 0 50px 5px rgba(255,255,255,.2); + -moz-box-shadow: inset 0 1px 0 rgba(255,255,255, .4), inset 0 0 50px 5px rgba(255,255,255,.2); + box-shadow: inset 0 1px 0 rgba(255,255,255, .4), inset 0 0 50px 5px rgba(255,255,255,.2); + -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255, .4), inset 0 0 50px 5px rgba(255,255,255,.2); + -moz-box-shadow: inset 0 1px 0 rgba(255,255,255, .4), inset 0 0 50px 5px rgba(255,255,255,.2); + box-shadow: inset 0 1px 0 rgba(255,255,255, .4), inset 0 0 50px 5px rgba(255,255,255,.2); + -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255, .4), inset 0 0 50px 5px rgba(255,255,255,.2); + -moz-box-shadow: inset 0 1px 0 rgba(255,255,255, .4), inset 0 0 50px 5px rgba(255,255,255,.2); + box-shadow: inset 0 1px 0 rgba(255,255,255, .4), inset 0 0 50px 5px rgba(255,255,255,.2); } .simple-button:active, .simple-button.toggled { -webkit-box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.3), inset 0 2px 4px rgba(0, 0, 0, 0.4); -moz-box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.3), inset 0 2px 4px rgba(0, 0, 0, 0.4); box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.3), inset 0 2px 4px rgba(0, 0, 0, 0.4); + -webkit-box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.3), inset 0 2px 4px rgba(0, 0, 0, 0.4); + -moz-box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.3), inset 0 2px 4px rgba(0, 0, 0, 0.4); + box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.3), inset 0 2px 4px rgba(0, 0, 0, 0.4); + -webkit-box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.3), inset 0 2px 4px rgba(0, 0, 0, 0.4); + -moz-box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.3), inset 0 2px 4px rgba(0, 0, 0, 0.4); + box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.3), inset 0 2px 4px rgba(0, 0, 0, 0.4); + -webkit-box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.3), inset 0 2px 4px rgba(0, 0, 0, 0.4); + -moz-box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.3), inset 0 2px 4px rgba(0, 0, 0, 0.4); + box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.3), inset 0 2px 4px rgba(0, 0, 0, 0.4); } .simple-button:disabled, .simple-button.disabled { @@ -4743,9 +5103,20 @@ ul.topic-browser-menu.new > li > ul { -webkit-box-shadow: none; -moz-box-shadow: none; box-shadow: none; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; cursor: not-allowed !important; opacity: 0.5; filter: alpha(opacity=50); + opacity: 0.5; + filter: alpha(opacity=50); top: 0 !important; } .simple-button.blue, @@ -4761,11 +5132,86 @@ ul.topic-browser-menu.new > li > ul { background-image: linear-gradient(top, #3a4759, #303b4a); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#3a4759', endColorstr='#303b4a', GradientType=0); + background-color: #364253; + background-image: -moz-linear-gradient(top, #3a4759, #303b4a); + background-image: -ms-linear-gradient(top, #3a4759, #303b4a); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#3a4759), to(#303b4a)); + background-image: -webkit-linear-gradient(top, #3a4759, #303b4a); + background-image: -o-linear-gradient(top, #3a4759, #303b4a); + background-image: linear-gradient(top, #3a4759, #303b4a); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#3a4759', endColorstr='#303b4a', GradientType=0); + border-color: #303b4a #303b4a #12161b; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + background-color: #364253; + background-image: -moz-linear-gradient(top, #3a4759, #303b4a); + background-image: -ms-linear-gradient(top, #3a4759, #303b4a); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#3a4759), to(#303b4a)); + background-image: -webkit-linear-gradient(top, #3a4759, #303b4a); + background-image: -o-linear-gradient(top, #3a4759, #303b4a); + background-image: linear-gradient(top, #3a4759, #303b4a); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#3a4759', endColorstr='#303b4a', GradientType=0); + background-color: #364253; + background-image: -moz-linear-gradient(top, #3a4759, #303b4a); + background-image: -ms-linear-gradient(top, #3a4759, #303b4a); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#3a4759), to(#303b4a)); + background-image: -webkit-linear-gradient(top, #3a4759, #303b4a); + background-image: -o-linear-gradient(top, #3a4759, #303b4a); + background-image: linear-gradient(top, #3a4759, #303b4a); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#3a4759', endColorstr='#303b4a', GradientType=0); + border-color: #303b4a #303b4a #12161b; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #303b4a; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + background-color: #364253; + background-image: -moz-linear-gradient(top, #3a4759, #303b4a); + background-image: -ms-linear-gradient(top, #3a4759, #303b4a); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#3a4759), to(#303b4a)); + background-image: -webkit-linear-gradient(top, #3a4759, #303b4a); + background-image: -o-linear-gradient(top, #3a4759, #303b4a); + background-image: linear-gradient(top, #3a4759, #303b4a); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#3a4759', endColorstr='#303b4a', GradientType=0); + background-color: #364253; + background-image: -moz-linear-gradient(top, #3a4759, #303b4a); + background-image: -ms-linear-gradient(top, #3a4759, #303b4a); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#3a4759), to(#303b4a)); + background-image: -webkit-linear-gradient(top, #3a4759, #303b4a); + background-image: -o-linear-gradient(top, #3a4759, #303b4a); + background-image: linear-gradient(top, #3a4759, #303b4a); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#3a4759', endColorstr='#303b4a', GradientType=0); + border-color: #303b4a #303b4a #12161b; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + background-color: #364253; + background-image: -moz-linear-gradient(top, #3a4759, #303b4a); + background-image: -ms-linear-gradient(top, #3a4759, #303b4a); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#3a4759), to(#303b4a)); + background-image: -webkit-linear-gradient(top, #3a4759, #303b4a); + background-image: -o-linear-gradient(top, #3a4759, #303b4a); + background-image: linear-gradient(top, #3a4759, #303b4a); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#3a4759', endColorstr='#303b4a', GradientType=0); + background-color: #364253; + background-image: -moz-linear-gradient(top, #3a4759, #303b4a); + background-image: -ms-linear-gradient(top, #3a4759, #303b4a); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#3a4759), to(#303b4a)); + background-image: -webkit-linear-gradient(top, #3a4759, #303b4a); + background-image: -o-linear-gradient(top, #3a4759, #303b4a); + background-image: linear-gradient(top, #3a4759, #303b4a); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#3a4759', endColorstr='#303b4a', GradientType=0); border-color: #303b4a #303b4a #12161b; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); *background-color: #303b4a; /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); color: #ffffff !important; text-shadow: 0 -1px 0 #050608; @@ -4821,11 +5267,86 @@ ul.topic-browser-menu.new > li > ul { background-image: linear-gradient(top, #8aba08, #6e9700); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#8aba08', endColorstr='#6e9700', GradientType=0); + background-color: #7fac05; + background-image: -moz-linear-gradient(top, #8aba08, #6e9700); + background-image: -ms-linear-gradient(top, #8aba08, #6e9700); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#8aba08), to(#6e9700)); + background-image: -webkit-linear-gradient(top, #8aba08, #6e9700); + background-image: -o-linear-gradient(top, #8aba08, #6e9700); + background-image: linear-gradient(top, #8aba08, #6e9700); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#8aba08', endColorstr='#6e9700', GradientType=0); + border-color: #6e9700 #6e9700 #364b00; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + background-color: #7fac05; + background-image: -moz-linear-gradient(top, #8aba08, #6e9700); + background-image: -ms-linear-gradient(top, #8aba08, #6e9700); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#8aba08), to(#6e9700)); + background-image: -webkit-linear-gradient(top, #8aba08, #6e9700); + background-image: -o-linear-gradient(top, #8aba08, #6e9700); + background-image: linear-gradient(top, #8aba08, #6e9700); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#8aba08', endColorstr='#6e9700', GradientType=0); + background-color: #7fac05; + background-image: -moz-linear-gradient(top, #8aba08, #6e9700); + background-image: -ms-linear-gradient(top, #8aba08, #6e9700); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#8aba08), to(#6e9700)); + background-image: -webkit-linear-gradient(top, #8aba08, #6e9700); + background-image: -o-linear-gradient(top, #8aba08, #6e9700); + background-image: linear-gradient(top, #8aba08, #6e9700); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#8aba08', endColorstr='#6e9700', GradientType=0); + border-color: #6e9700 #6e9700 #364b00; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #6e9700; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + background-color: #7fac05; + background-image: -moz-linear-gradient(top, #8aba08, #6e9700); + background-image: -ms-linear-gradient(top, #8aba08, #6e9700); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#8aba08), to(#6e9700)); + background-image: -webkit-linear-gradient(top, #8aba08, #6e9700); + background-image: -o-linear-gradient(top, #8aba08, #6e9700); + background-image: linear-gradient(top, #8aba08, #6e9700); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#8aba08', endColorstr='#6e9700', GradientType=0); + background-color: #7fac05; + background-image: -moz-linear-gradient(top, #8aba08, #6e9700); + background-image: -ms-linear-gradient(top, #8aba08, #6e9700); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#8aba08), to(#6e9700)); + background-image: -webkit-linear-gradient(top, #8aba08, #6e9700); + background-image: -o-linear-gradient(top, #8aba08, #6e9700); + background-image: linear-gradient(top, #8aba08, #6e9700); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#8aba08', endColorstr='#6e9700', GradientType=0); + border-color: #6e9700 #6e9700 #364b00; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + background-color: #7fac05; + background-image: -moz-linear-gradient(top, #8aba08, #6e9700); + background-image: -ms-linear-gradient(top, #8aba08, #6e9700); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#8aba08), to(#6e9700)); + background-image: -webkit-linear-gradient(top, #8aba08, #6e9700); + background-image: -o-linear-gradient(top, #8aba08, #6e9700); + background-image: linear-gradient(top, #8aba08, #6e9700); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#8aba08', endColorstr='#6e9700', GradientType=0); + background-color: #7fac05; + background-image: -moz-linear-gradient(top, #8aba08, #6e9700); + background-image: -ms-linear-gradient(top, #8aba08, #6e9700); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#8aba08), to(#6e9700)); + background-image: -webkit-linear-gradient(top, #8aba08, #6e9700); + background-image: -o-linear-gradient(top, #8aba08, #6e9700); + background-image: linear-gradient(top, #8aba08, #6e9700); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#8aba08', endColorstr='#6e9700', GradientType=0); border-color: #6e9700 #6e9700 #364b00; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); *background-color: #6e9700; /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); color: #ffffff !important; text-shadow: 0 -1px 0 #526f03; @@ -4881,11 +5402,86 @@ ul.topic-browser-menu.new > li > ul { background-image: linear-gradient(top, #e35d04, #bf4f04); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#e35d04', endColorstr='#bf4f04', GradientType=0); - border-color: #bf4f04 #bf4f04 #743002; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - *background-color: #bf4f04; - /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + background-color: #d55704; + background-image: -moz-linear-gradient(top, #e35d04, #bf4f04); + background-image: -ms-linear-gradient(top, #e35d04, #bf4f04); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#e35d04), to(#bf4f04)); + background-image: -webkit-linear-gradient(top, #e35d04, #bf4f04); + background-image: -o-linear-gradient(top, #e35d04, #bf4f04); + background-image: linear-gradient(top, #e35d04, #bf4f04); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#e35d04', endColorstr='#bf4f04', GradientType=0); + border-color: #bf4f04 #bf4f04 #743002; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + background-color: #d55704; + background-image: -moz-linear-gradient(top, #e35d04, #bf4f04); + background-image: -ms-linear-gradient(top, #e35d04, #bf4f04); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#e35d04), to(#bf4f04)); + background-image: -webkit-linear-gradient(top, #e35d04, #bf4f04); + background-image: -o-linear-gradient(top, #e35d04, #bf4f04); + background-image: linear-gradient(top, #e35d04, #bf4f04); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#e35d04', endColorstr='#bf4f04', GradientType=0); + background-color: #d55704; + background-image: -moz-linear-gradient(top, #e35d04, #bf4f04); + background-image: -ms-linear-gradient(top, #e35d04, #bf4f04); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#e35d04), to(#bf4f04)); + background-image: -webkit-linear-gradient(top, #e35d04, #bf4f04); + background-image: -o-linear-gradient(top, #e35d04, #bf4f04); + background-image: linear-gradient(top, #e35d04, #bf4f04); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#e35d04', endColorstr='#bf4f04', GradientType=0); + border-color: #bf4f04 #bf4f04 #743002; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #bf4f04; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + background-color: #d55704; + background-image: -moz-linear-gradient(top, #e35d04, #bf4f04); + background-image: -ms-linear-gradient(top, #e35d04, #bf4f04); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#e35d04), to(#bf4f04)); + background-image: -webkit-linear-gradient(top, #e35d04, #bf4f04); + background-image: -o-linear-gradient(top, #e35d04, #bf4f04); + background-image: linear-gradient(top, #e35d04, #bf4f04); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#e35d04', endColorstr='#bf4f04', GradientType=0); + background-color: #d55704; + background-image: -moz-linear-gradient(top, #e35d04, #bf4f04); + background-image: -ms-linear-gradient(top, #e35d04, #bf4f04); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#e35d04), to(#bf4f04)); + background-image: -webkit-linear-gradient(top, #e35d04, #bf4f04); + background-image: -o-linear-gradient(top, #e35d04, #bf4f04); + background-image: linear-gradient(top, #e35d04, #bf4f04); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#e35d04', endColorstr='#bf4f04', GradientType=0); + border-color: #bf4f04 #bf4f04 #743002; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + background-color: #d55704; + background-image: -moz-linear-gradient(top, #e35d04, #bf4f04); + background-image: -ms-linear-gradient(top, #e35d04, #bf4f04); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#e35d04), to(#bf4f04)); + background-image: -webkit-linear-gradient(top, #e35d04, #bf4f04); + background-image: -o-linear-gradient(top, #e35d04, #bf4f04); + background-image: linear-gradient(top, #e35d04, #bf4f04); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#e35d04', endColorstr='#bf4f04', GradientType=0); + background-color: #d55704; + background-image: -moz-linear-gradient(top, #e35d04, #bf4f04); + background-image: -ms-linear-gradient(top, #e35d04, #bf4f04); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#e35d04), to(#bf4f04)); + background-image: -webkit-linear-gradient(top, #e35d04, #bf4f04); + background-image: -o-linear-gradient(top, #e35d04, #bf4f04); + background-image: linear-gradient(top, #e35d04, #bf4f04); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#e35d04', endColorstr='#bf4f04', GradientType=0); + border-color: #bf4f04 #bf4f04 #743002; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #bf4f04; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); color: #ffffff !important; text-shadow: 0 -1px 0 #743002; @@ -4976,6 +5572,35 @@ ul.topic-browser-menu.new > li > ul { .action-gradient { /* TODO (jasonrr): remove this once the last few uses of it have been converted or removed */ + background-color: #f3f3f3; + background-image: -moz-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -ms-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f7f7f7), to(#eeeeee)); + background-image: -webkit-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -o-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: linear-gradient(top, #f7f7f7, #eeeeee); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f7f7f7', endColorstr='#eeeeee', GradientType=0); + background-color: #f3f3f3; + background-image: -moz-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -ms-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f7f7f7), to(#eeeeee)); + background-image: -webkit-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -o-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: linear-gradient(top, #f7f7f7, #eeeeee); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f7f7f7', endColorstr='#eeeeee', GradientType=0); + border-color: #eeeeee #eeeeee #c8c8c8; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + background-color: #f3f3f3; + background-image: -moz-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -ms-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f7f7f7), to(#eeeeee)); + background-image: -webkit-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -o-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: linear-gradient(top, #f7f7f7, #eeeeee); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f7f7f7', endColorstr='#eeeeee', GradientType=0); background-color: #f3f3f3; background-image: -moz-linear-gradient(top, #f7f7f7, #eeeeee); background-image: -ms-linear-gradient(top, #f7f7f7, #eeeeee); @@ -4991,6 +5616,52 @@ ul.topic-browser-menu.new > li > ul { /* Darken IE7 buttons by default so they stand out more given they won't have borders */ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + background-color: #f3f3f3; + background-image: -moz-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -ms-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f7f7f7), to(#eeeeee)); + background-image: -webkit-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -o-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: linear-gradient(top, #f7f7f7, #eeeeee); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f7f7f7', endColorstr='#eeeeee', GradientType=0); + background-color: #f3f3f3; + background-image: -moz-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -ms-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f7f7f7), to(#eeeeee)); + background-image: -webkit-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -o-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: linear-gradient(top, #f7f7f7, #eeeeee); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f7f7f7', endColorstr='#eeeeee', GradientType=0); + border-color: #eeeeee #eeeeee #c8c8c8; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + background-color: #f3f3f3; + background-image: -moz-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -ms-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f7f7f7), to(#eeeeee)); + background-image: -webkit-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -o-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: linear-gradient(top, #f7f7f7, #eeeeee); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f7f7f7', endColorstr='#eeeeee', GradientType=0); + background-color: #f3f3f3; + background-image: -moz-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -ms-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f7f7f7), to(#eeeeee)); + background-image: -webkit-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -o-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: linear-gradient(top, #f7f7f7, #eeeeee); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f7f7f7', endColorstr='#eeeeee', GradientType=0); + border-color: #eeeeee #eeeeee #c8c8c8; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #eeeeee; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); } .action-gradient:hover, .action-gradient:active, @@ -5065,6 +5736,15 @@ a.big-button:active > div { -webkit-box-shadow: 0px 0px 4px 0px #aaaaaa; -moz-box-shadow: 0px 0px 4px 0px #aaaaaa; box-shadow: 0px 0px 4px 0px #aaaaaa; + -webkit-box-shadow: 0px 0px 4px 0px #aaaaaa; + -moz-box-shadow: 0px 0px 4px 0px #aaaaaa; + box-shadow: 0px 0px 4px 0px #aaaaaa; + -webkit-box-shadow: 0px 0px 4px 0px #aaaaaa; + -moz-box-shadow: 0px 0px 4px 0px #aaaaaa; + box-shadow: 0px 0px 4px 0px #aaaaaa; + -webkit-box-shadow: 0px 0px 4px 0px #aaaaaa; + -moz-box-shadow: 0px 0px 4px 0px #aaaaaa; + box-shadow: 0px 0px 4px 0px #aaaaaa; } .ui-corner-right.strict { -webkit-border-top-right-radius: 5px; @@ -5082,6 +5762,21 @@ a.big-button:active > div { -moz-background-clip: padding; -webkit-background-clip: padding-box; background-clip: padding-box; + -webkit-border-top-right-radius: 5px; + -webkit-border-bottom-right-radius: 5px; + -webkit-border-bottom-left-radius: 0; + -webkit-border-top-left-radius: 0; + -moz-border-radius-topright: 5px; + -moz-border-radius-bottomright: 5px; + -moz-border-radius-bottomleft: 0; + -moz-border-radius-topleft: 0; + border-top-right-radius: 5px; + border-bottom-right-radius: 5px; + border-bottom-left-radius: 0; + border-top-left-radius: 0; + -moz-background-clip: padding; + -webkit-background-clip: padding-box; + background-clip: padding-box; } .headline-container { position: relative; @@ -5107,12 +5802,24 @@ ul.scratchpad-list li { margin-left: 30px; } ul.scratchpad-list li .scratchpad-thumbnail { + width: 200px; + height: 200px; + height: 200px; + width: 200px; + width: 200px; + height: 200px; height: 200px; width: 200px; border: 1px solid #aaaaaa; position: relative; } ul.scratchpad-list li .scratchpad-thumbnail img { + width: 200px; + height: 200px; + height: 200px; + width: 200px; + width: 200px; + height: 200px; height: 200px; width: 200px; } @@ -5140,6 +5847,9 @@ ul.scratchpad-list li h4 { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } /* A simple 3D button style */ .simple-button { @@ -5148,9 +5858,47 @@ ul.scratchpad-list li h4 { -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255, .3); -moz-box-shadow: inset 0 1px 0 rgba(255,255,255, .3); box-shadow: inset 0 1px 0 rgba(255,255,255, .3); + -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255, .3); + -moz-box-shadow: inset 0 1px 0 rgba(255,255,255, .3); + box-shadow: inset 0 1px 0 rgba(255,255,255, .3); + -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255, .3); + -moz-box-shadow: inset 0 1px 0 rgba(255,255,255, .3); + box-shadow: inset 0 1px 0 rgba(255,255,255, .3); + -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255, .3); + -moz-box-shadow: inset 0 1px 0 rgba(255,255,255, .3); + box-shadow: inset 0 1px 0 rgba(255,255,255, .3); + background-color: #f8f8f8; + background-image: -moz-linear-gradient(top, #ffffff, #eeeeee); + background-image: -ms-linear-gradient(top, #ffffff, #eeeeee); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#eeeeee)); + background-image: -webkit-linear-gradient(top, #ffffff, #eeeeee); + background-image: -o-linear-gradient(top, #ffffff, #eeeeee); + background-image: linear-gradient(top, #ffffff, #eeeeee); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0); + background-color: #f8f8f8; + background-image: -moz-linear-gradient(top, #ffffff, #eeeeee); + background-image: -ms-linear-gradient(top, #ffffff, #eeeeee); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#eeeeee)); + background-image: -webkit-linear-gradient(top, #ffffff, #eeeeee); + background-image: -o-linear-gradient(top, #ffffff, #eeeeee); + background-image: linear-gradient(top, #ffffff, #eeeeee); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0); + border-color: #eeeeee #eeeeee #c8c8c8; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); background-color: #f8f8f8; background-image: -moz-linear-gradient(top, #ffffff, #eeeeee); background-image: -ms-linear-gradient(top, #ffffff, #eeeeee); @@ -5159,78 +5907,237 @@ ul.scratchpad-list li h4 { background-image: -o-linear-gradient(top, #ffffff, #eeeeee); background-image: linear-gradient(top, #ffffff, #eeeeee); background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0); - border-color: #eeeeee #eeeeee #c8c8c8; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - *background-color: #eeeeee; - /* Darken IE7 buttons by default so they stand out more given they won't have borders */ - - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - color: #595959 !important; - cursor: pointer !important; - font-family: inherit; - /* input[type=button] won't inherit by default */ - - line-height: 22px; - margin: 0; - padding: 5px 10px; - position: relative; - text-decoration: none !important; - text-shadow: 0 -1px 0 #ffffff; - /* Special button types */ - -} -.simple-button:hover, -.simple-button:active, -.simple-button.active, -.simple-button.disabled, -.simple-button[disabled] { - background-color: #eeeeee; - *background-color: #e1e1e1; -} -.simple-button:active, -.simple-button.active { - background-color: #d5d5d5 \9; -} -.simple-button:hover, -.simple-button:active, -.simple-button.active, -.simple-button.disabled, -.simple-button[disabled] { - background-color: #eeeeee; - *background-color: #e1e1e1; -} -.simple-button:active, -.simple-button.active { - background-color: #d5d5d5 \9; -} -.simple-button:hover { - border-color: #aaaaaa; - -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255, .4), inset 0 0 50px 5px rgba(255,255,255,.2); - -moz-box-shadow: inset 0 1px 0 rgba(255,255,255, .4), inset 0 0 50px 5px rgba(255,255,255,.2); - box-shadow: inset 0 1px 0 rgba(255,255,255, .4), inset 0 0 50px 5px rgba(255,255,255,.2); -} -.simple-button:active, -.simple-button.toggled { - -webkit-box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.3), inset 0 2px 4px rgba(0, 0, 0, 0.4); - -moz-box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.3), inset 0 2px 4px rgba(0, 0, 0, 0.4); - box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.3), inset 0 2px 4px rgba(0, 0, 0, 0.4); -} -.simple-button:disabled, -.simple-button.disabled { - background-image: none !important; - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; - cursor: not-allowed !important; - opacity: 0.5; - filter: alpha(opacity=50); - top: 0 !important; -} -.simple-button.blue, -.simple-button.secondary { - border-color: #2c3747 !important; - border-bottom-color: #000000 !important; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0); + background-color: #f8f8f8; + background-image: -moz-linear-gradient(top, #ffffff, #eeeeee); + background-image: -ms-linear-gradient(top, #ffffff, #eeeeee); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#eeeeee)); + background-image: -webkit-linear-gradient(top, #ffffff, #eeeeee); + background-image: -o-linear-gradient(top, #ffffff, #eeeeee); + background-image: linear-gradient(top, #ffffff, #eeeeee); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0); + border-color: #eeeeee #eeeeee #c8c8c8; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #eeeeee; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + background-color: #f8f8f8; + background-image: -moz-linear-gradient(top, #ffffff, #eeeeee); + background-image: -ms-linear-gradient(top, #ffffff, #eeeeee); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#eeeeee)); + background-image: -webkit-linear-gradient(top, #ffffff, #eeeeee); + background-image: -o-linear-gradient(top, #ffffff, #eeeeee); + background-image: linear-gradient(top, #ffffff, #eeeeee); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0); + background-color: #f8f8f8; + background-image: -moz-linear-gradient(top, #ffffff, #eeeeee); + background-image: -ms-linear-gradient(top, #ffffff, #eeeeee); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#eeeeee)); + background-image: -webkit-linear-gradient(top, #ffffff, #eeeeee); + background-image: -o-linear-gradient(top, #ffffff, #eeeeee); + background-image: linear-gradient(top, #ffffff, #eeeeee); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0); + border-color: #eeeeee #eeeeee #c8c8c8; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + background-color: #f8f8f8; + background-image: -moz-linear-gradient(top, #ffffff, #eeeeee); + background-image: -ms-linear-gradient(top, #ffffff, #eeeeee); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#eeeeee)); + background-image: -webkit-linear-gradient(top, #ffffff, #eeeeee); + background-image: -o-linear-gradient(top, #ffffff, #eeeeee); + background-image: linear-gradient(top, #ffffff, #eeeeee); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0); + background-color: #f8f8f8; + background-image: -moz-linear-gradient(top, #ffffff, #eeeeee); + background-image: -ms-linear-gradient(top, #ffffff, #eeeeee); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#eeeeee)); + background-image: -webkit-linear-gradient(top, #ffffff, #eeeeee); + background-image: -o-linear-gradient(top, #ffffff, #eeeeee); + background-image: linear-gradient(top, #ffffff, #eeeeee); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0); + border-color: #eeeeee #eeeeee #c8c8c8; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #eeeeee; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + color: #595959 !important; + cursor: pointer !important; + font-family: inherit; + /* input[type=button] won't inherit by default */ + + line-height: 22px; + margin: 0; + padding: 5px 10px; + position: relative; + text-decoration: none !important; + text-shadow: 0 -1px 0 #ffffff; + -webkit-appearance: none; + /* Special button types */ + +} +.simple-button:hover, +.simple-button:active, +.simple-button.active, +.simple-button.disabled, +.simple-button[disabled] { + background-color: #eeeeee; + *background-color: #e1e1e1; +} +.simple-button:active, +.simple-button.active { + background-color: #d5d5d5 \9; +} +.simple-button:hover, +.simple-button:active, +.simple-button.active, +.simple-button.disabled, +.simple-button[disabled] { + background-color: #eeeeee; + *background-color: #e1e1e1; +} +.simple-button:active, +.simple-button.active { + background-color: #d5d5d5 \9; +} +.simple-button:hover { + border-color: #aaaaaa; + -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255, .4), inset 0 0 50px 5px rgba(255,255,255,.2); + -moz-box-shadow: inset 0 1px 0 rgba(255,255,255, .4), inset 0 0 50px 5px rgba(255,255,255,.2); + box-shadow: inset 0 1px 0 rgba(255,255,255, .4), inset 0 0 50px 5px rgba(255,255,255,.2); + -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255, .4), inset 0 0 50px 5px rgba(255,255,255,.2); + -moz-box-shadow: inset 0 1px 0 rgba(255,255,255, .4), inset 0 0 50px 5px rgba(255,255,255,.2); + box-shadow: inset 0 1px 0 rgba(255,255,255, .4), inset 0 0 50px 5px rgba(255,255,255,.2); + -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255, .4), inset 0 0 50px 5px rgba(255,255,255,.2); + -moz-box-shadow: inset 0 1px 0 rgba(255,255,255, .4), inset 0 0 50px 5px rgba(255,255,255,.2); + box-shadow: inset 0 1px 0 rgba(255,255,255, .4), inset 0 0 50px 5px rgba(255,255,255,.2); + -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255, .4), inset 0 0 50px 5px rgba(255,255,255,.2); + -moz-box-shadow: inset 0 1px 0 rgba(255,255,255, .4), inset 0 0 50px 5px rgba(255,255,255,.2); + box-shadow: inset 0 1px 0 rgba(255,255,255, .4), inset 0 0 50px 5px rgba(255,255,255,.2); +} +.simple-button:active, +.simple-button.toggled { + -webkit-box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.3), inset 0 2px 4px rgba(0, 0, 0, 0.4); + -moz-box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.3), inset 0 2px 4px rgba(0, 0, 0, 0.4); + box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.3), inset 0 2px 4px rgba(0, 0, 0, 0.4); + -webkit-box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.3), inset 0 2px 4px rgba(0, 0, 0, 0.4); + -moz-box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.3), inset 0 2px 4px rgba(0, 0, 0, 0.4); + box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.3), inset 0 2px 4px rgba(0, 0, 0, 0.4); + -webkit-box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.3), inset 0 2px 4px rgba(0, 0, 0, 0.4); + -moz-box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.3), inset 0 2px 4px rgba(0, 0, 0, 0.4); + box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.3), inset 0 2px 4px rgba(0, 0, 0, 0.4); + -webkit-box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.3), inset 0 2px 4px rgba(0, 0, 0, 0.4); + -moz-box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.3), inset 0 2px 4px rgba(0, 0, 0, 0.4); + box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.3), inset 0 2px 4px rgba(0, 0, 0, 0.4); +} +.simple-button:disabled, +.simple-button.disabled { + background-image: none !important; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + cursor: not-allowed !important; + opacity: 0.5; + filter: alpha(opacity=50); + opacity: 0.5; + filter: alpha(opacity=50); + top: 0 !important; +} +.simple-button.blue, +.simple-button.secondary { + border-color: #2c3747 !important; + border-bottom-color: #000000 !important; + background-color: #364253; + background-image: -moz-linear-gradient(top, #3a4759, #303b4a); + background-image: -ms-linear-gradient(top, #3a4759, #303b4a); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#3a4759), to(#303b4a)); + background-image: -webkit-linear-gradient(top, #3a4759, #303b4a); + background-image: -o-linear-gradient(top, #3a4759, #303b4a); + background-image: linear-gradient(top, #3a4759, #303b4a); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#3a4759', endColorstr='#303b4a', GradientType=0); + background-color: #364253; + background-image: -moz-linear-gradient(top, #3a4759, #303b4a); + background-image: -ms-linear-gradient(top, #3a4759, #303b4a); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#3a4759), to(#303b4a)); + background-image: -webkit-linear-gradient(top, #3a4759, #303b4a); + background-image: -o-linear-gradient(top, #3a4759, #303b4a); + background-image: linear-gradient(top, #3a4759, #303b4a); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#3a4759', endColorstr='#303b4a', GradientType=0); + border-color: #303b4a #303b4a #12161b; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + background-color: #364253; + background-image: -moz-linear-gradient(top, #3a4759, #303b4a); + background-image: -ms-linear-gradient(top, #3a4759, #303b4a); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#3a4759), to(#303b4a)); + background-image: -webkit-linear-gradient(top, #3a4759, #303b4a); + background-image: -o-linear-gradient(top, #3a4759, #303b4a); + background-image: linear-gradient(top, #3a4759, #303b4a); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#3a4759', endColorstr='#303b4a', GradientType=0); + background-color: #364253; + background-image: -moz-linear-gradient(top, #3a4759, #303b4a); + background-image: -ms-linear-gradient(top, #3a4759, #303b4a); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#3a4759), to(#303b4a)); + background-image: -webkit-linear-gradient(top, #3a4759, #303b4a); + background-image: -o-linear-gradient(top, #3a4759, #303b4a); + background-image: linear-gradient(top, #3a4759, #303b4a); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#3a4759', endColorstr='#303b4a', GradientType=0); + border-color: #303b4a #303b4a #12161b; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #303b4a; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + background-color: #364253; + background-image: -moz-linear-gradient(top, #3a4759, #303b4a); + background-image: -ms-linear-gradient(top, #3a4759, #303b4a); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#3a4759), to(#303b4a)); + background-image: -webkit-linear-gradient(top, #3a4759, #303b4a); + background-image: -o-linear-gradient(top, #3a4759, #303b4a); + background-image: linear-gradient(top, #3a4759, #303b4a); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#3a4759', endColorstr='#303b4a', GradientType=0); + background-color: #364253; + background-image: -moz-linear-gradient(top, #3a4759, #303b4a); + background-image: -ms-linear-gradient(top, #3a4759, #303b4a); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#3a4759), to(#303b4a)); + background-image: -webkit-linear-gradient(top, #3a4759, #303b4a); + background-image: -o-linear-gradient(top, #3a4759, #303b4a); + background-image: linear-gradient(top, #3a4759, #303b4a); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#3a4759', endColorstr='#303b4a', GradientType=0); + border-color: #303b4a #303b4a #12161b; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + background-color: #364253; + background-image: -moz-linear-gradient(top, #3a4759, #303b4a); + background-image: -ms-linear-gradient(top, #3a4759, #303b4a); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#3a4759), to(#303b4a)); + background-image: -webkit-linear-gradient(top, #3a4759, #303b4a); + background-image: -o-linear-gradient(top, #3a4759, #303b4a); + background-image: linear-gradient(top, #3a4759, #303b4a); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#3a4759', endColorstr='#303b4a', GradientType=0); background-color: #364253; background-image: -moz-linear-gradient(top, #3a4759, #303b4a); background-image: -ms-linear-gradient(top, #3a4759, #303b4a); @@ -5245,6 +6152,7 @@ ul.scratchpad-list li h4 { *background-color: #303b4a; /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); color: #ffffff !important; text-shadow: 0 -1px 0 #050608; @@ -5300,11 +6208,86 @@ ul.scratchpad-list li h4 { background-image: linear-gradient(top, #8aba08, #6e9700); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#8aba08', endColorstr='#6e9700', GradientType=0); + background-color: #7fac05; + background-image: -moz-linear-gradient(top, #8aba08, #6e9700); + background-image: -ms-linear-gradient(top, #8aba08, #6e9700); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#8aba08), to(#6e9700)); + background-image: -webkit-linear-gradient(top, #8aba08, #6e9700); + background-image: -o-linear-gradient(top, #8aba08, #6e9700); + background-image: linear-gradient(top, #8aba08, #6e9700); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#8aba08', endColorstr='#6e9700', GradientType=0); + border-color: #6e9700 #6e9700 #364b00; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + background-color: #7fac05; + background-image: -moz-linear-gradient(top, #8aba08, #6e9700); + background-image: -ms-linear-gradient(top, #8aba08, #6e9700); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#8aba08), to(#6e9700)); + background-image: -webkit-linear-gradient(top, #8aba08, #6e9700); + background-image: -o-linear-gradient(top, #8aba08, #6e9700); + background-image: linear-gradient(top, #8aba08, #6e9700); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#8aba08', endColorstr='#6e9700', GradientType=0); + background-color: #7fac05; + background-image: -moz-linear-gradient(top, #8aba08, #6e9700); + background-image: -ms-linear-gradient(top, #8aba08, #6e9700); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#8aba08), to(#6e9700)); + background-image: -webkit-linear-gradient(top, #8aba08, #6e9700); + background-image: -o-linear-gradient(top, #8aba08, #6e9700); + background-image: linear-gradient(top, #8aba08, #6e9700); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#8aba08', endColorstr='#6e9700', GradientType=0); + border-color: #6e9700 #6e9700 #364b00; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #6e9700; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + background-color: #7fac05; + background-image: -moz-linear-gradient(top, #8aba08, #6e9700); + background-image: -ms-linear-gradient(top, #8aba08, #6e9700); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#8aba08), to(#6e9700)); + background-image: -webkit-linear-gradient(top, #8aba08, #6e9700); + background-image: -o-linear-gradient(top, #8aba08, #6e9700); + background-image: linear-gradient(top, #8aba08, #6e9700); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#8aba08', endColorstr='#6e9700', GradientType=0); + background-color: #7fac05; + background-image: -moz-linear-gradient(top, #8aba08, #6e9700); + background-image: -ms-linear-gradient(top, #8aba08, #6e9700); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#8aba08), to(#6e9700)); + background-image: -webkit-linear-gradient(top, #8aba08, #6e9700); + background-image: -o-linear-gradient(top, #8aba08, #6e9700); + background-image: linear-gradient(top, #8aba08, #6e9700); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#8aba08', endColorstr='#6e9700', GradientType=0); + border-color: #6e9700 #6e9700 #364b00; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + background-color: #7fac05; + background-image: -moz-linear-gradient(top, #8aba08, #6e9700); + background-image: -ms-linear-gradient(top, #8aba08, #6e9700); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#8aba08), to(#6e9700)); + background-image: -webkit-linear-gradient(top, #8aba08, #6e9700); + background-image: -o-linear-gradient(top, #8aba08, #6e9700); + background-image: linear-gradient(top, #8aba08, #6e9700); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#8aba08', endColorstr='#6e9700', GradientType=0); + background-color: #7fac05; + background-image: -moz-linear-gradient(top, #8aba08, #6e9700); + background-image: -ms-linear-gradient(top, #8aba08, #6e9700); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#8aba08), to(#6e9700)); + background-image: -webkit-linear-gradient(top, #8aba08, #6e9700); + background-image: -o-linear-gradient(top, #8aba08, #6e9700); + background-image: linear-gradient(top, #8aba08, #6e9700); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#8aba08', endColorstr='#6e9700', GradientType=0); border-color: #6e9700 #6e9700 #364b00; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); *background-color: #6e9700; /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); color: #ffffff !important; text-shadow: 0 -1px 0 #526f03; @@ -5360,11 +6343,86 @@ ul.scratchpad-list li h4 { background-image: linear-gradient(top, #e35d04, #bf4f04); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#e35d04', endColorstr='#bf4f04', GradientType=0); + background-color: #d55704; + background-image: -moz-linear-gradient(top, #e35d04, #bf4f04); + background-image: -ms-linear-gradient(top, #e35d04, #bf4f04); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#e35d04), to(#bf4f04)); + background-image: -webkit-linear-gradient(top, #e35d04, #bf4f04); + background-image: -o-linear-gradient(top, #e35d04, #bf4f04); + background-image: linear-gradient(top, #e35d04, #bf4f04); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#e35d04', endColorstr='#bf4f04', GradientType=0); + border-color: #bf4f04 #bf4f04 #743002; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + background-color: #d55704; + background-image: -moz-linear-gradient(top, #e35d04, #bf4f04); + background-image: -ms-linear-gradient(top, #e35d04, #bf4f04); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#e35d04), to(#bf4f04)); + background-image: -webkit-linear-gradient(top, #e35d04, #bf4f04); + background-image: -o-linear-gradient(top, #e35d04, #bf4f04); + background-image: linear-gradient(top, #e35d04, #bf4f04); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#e35d04', endColorstr='#bf4f04', GradientType=0); + background-color: #d55704; + background-image: -moz-linear-gradient(top, #e35d04, #bf4f04); + background-image: -ms-linear-gradient(top, #e35d04, #bf4f04); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#e35d04), to(#bf4f04)); + background-image: -webkit-linear-gradient(top, #e35d04, #bf4f04); + background-image: -o-linear-gradient(top, #e35d04, #bf4f04); + background-image: linear-gradient(top, #e35d04, #bf4f04); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#e35d04', endColorstr='#bf4f04', GradientType=0); + border-color: #bf4f04 #bf4f04 #743002; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #bf4f04; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + background-color: #d55704; + background-image: -moz-linear-gradient(top, #e35d04, #bf4f04); + background-image: -ms-linear-gradient(top, #e35d04, #bf4f04); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#e35d04), to(#bf4f04)); + background-image: -webkit-linear-gradient(top, #e35d04, #bf4f04); + background-image: -o-linear-gradient(top, #e35d04, #bf4f04); + background-image: linear-gradient(top, #e35d04, #bf4f04); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#e35d04', endColorstr='#bf4f04', GradientType=0); + background-color: #d55704; + background-image: -moz-linear-gradient(top, #e35d04, #bf4f04); + background-image: -ms-linear-gradient(top, #e35d04, #bf4f04); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#e35d04), to(#bf4f04)); + background-image: -webkit-linear-gradient(top, #e35d04, #bf4f04); + background-image: -o-linear-gradient(top, #e35d04, #bf4f04); + background-image: linear-gradient(top, #e35d04, #bf4f04); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#e35d04', endColorstr='#bf4f04', GradientType=0); + border-color: #bf4f04 #bf4f04 #743002; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + background-color: #d55704; + background-image: -moz-linear-gradient(top, #e35d04, #bf4f04); + background-image: -ms-linear-gradient(top, #e35d04, #bf4f04); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#e35d04), to(#bf4f04)); + background-image: -webkit-linear-gradient(top, #e35d04, #bf4f04); + background-image: -o-linear-gradient(top, #e35d04, #bf4f04); + background-image: linear-gradient(top, #e35d04, #bf4f04); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#e35d04', endColorstr='#bf4f04', GradientType=0); + background-color: #d55704; + background-image: -moz-linear-gradient(top, #e35d04, #bf4f04); + background-image: -ms-linear-gradient(top, #e35d04, #bf4f04); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#e35d04), to(#bf4f04)); + background-image: -webkit-linear-gradient(top, #e35d04, #bf4f04); + background-image: -o-linear-gradient(top, #e35d04, #bf4f04); + background-image: linear-gradient(top, #e35d04, #bf4f04); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#e35d04', endColorstr='#bf4f04', GradientType=0); border-color: #bf4f04 #bf4f04 #743002; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); *background-color: #bf4f04; /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); color: #ffffff !important; text-shadow: 0 -1px 0 #743002; @@ -5455,6 +6513,80 @@ ul.scratchpad-list li h4 { .action-gradient { /* TODO (jasonrr): remove this once the last few uses of it have been converted or removed */ + background-color: #f3f3f3; + background-image: -moz-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -ms-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f7f7f7), to(#eeeeee)); + background-image: -webkit-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -o-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: linear-gradient(top, #f7f7f7, #eeeeee); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f7f7f7', endColorstr='#eeeeee', GradientType=0); + background-color: #f3f3f3; + background-image: -moz-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -ms-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f7f7f7), to(#eeeeee)); + background-image: -webkit-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -o-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: linear-gradient(top, #f7f7f7, #eeeeee); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f7f7f7', endColorstr='#eeeeee', GradientType=0); + border-color: #eeeeee #eeeeee #c8c8c8; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + background-color: #f3f3f3; + background-image: -moz-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -ms-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f7f7f7), to(#eeeeee)); + background-image: -webkit-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -o-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: linear-gradient(top, #f7f7f7, #eeeeee); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f7f7f7', endColorstr='#eeeeee', GradientType=0); + background-color: #f3f3f3; + background-image: -moz-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -ms-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f7f7f7), to(#eeeeee)); + background-image: -webkit-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -o-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: linear-gradient(top, #f7f7f7, #eeeeee); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f7f7f7', endColorstr='#eeeeee', GradientType=0); + border-color: #eeeeee #eeeeee #c8c8c8; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #eeeeee; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + background-color: #f3f3f3; + background-image: -moz-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -ms-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f7f7f7), to(#eeeeee)); + background-image: -webkit-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -o-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: linear-gradient(top, #f7f7f7, #eeeeee); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f7f7f7', endColorstr='#eeeeee', GradientType=0); + background-color: #f3f3f3; + background-image: -moz-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -ms-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f7f7f7), to(#eeeeee)); + background-image: -webkit-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -o-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: linear-gradient(top, #f7f7f7, #eeeeee); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f7f7f7', endColorstr='#eeeeee', GradientType=0); + border-color: #eeeeee #eeeeee #c8c8c8; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + background-color: #f3f3f3; + background-image: -moz-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -ms-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f7f7f7), to(#eeeeee)); + background-image: -webkit-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: -o-linear-gradient(top, #f7f7f7, #eeeeee); + background-image: linear-gradient(top, #f7f7f7, #eeeeee); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f7f7f7', endColorstr='#eeeeee', GradientType=0); background-color: #f3f3f3; background-image: -moz-linear-gradient(top, #f7f7f7, #eeeeee); background-image: -ms-linear-gradient(top, #f7f7f7, #eeeeee); @@ -5470,6 +6602,7 @@ ul.scratchpad-list li h4 { /* Darken IE7 buttons by default so they stand out more given they won't have borders */ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); } .action-gradient:hover, .action-gradient:active, @@ -5544,6 +6677,15 @@ a.big-button:active > div { -webkit-box-shadow: 0px 0px 4px 0px #aaaaaa; -moz-box-shadow: 0px 0px 4px 0px #aaaaaa; box-shadow: 0px 0px 4px 0px #aaaaaa; + -webkit-box-shadow: 0px 0px 4px 0px #aaaaaa; + -moz-box-shadow: 0px 0px 4px 0px #aaaaaa; + box-shadow: 0px 0px 4px 0px #aaaaaa; + -webkit-box-shadow: 0px 0px 4px 0px #aaaaaa; + -moz-box-shadow: 0px 0px 4px 0px #aaaaaa; + box-shadow: 0px 0px 4px 0px #aaaaaa; + -webkit-box-shadow: 0px 0px 4px 0px #aaaaaa; + -moz-box-shadow: 0px 0px 4px 0px #aaaaaa; + box-shadow: 0px 0px 4px 0px #aaaaaa; } .ui-corner-right.strict { -webkit-border-top-right-radius: 5px; @@ -5561,6 +6703,21 @@ a.big-button:active > div { -moz-background-clip: padding; -webkit-background-clip: padding-box; background-clip: padding-box; + -webkit-border-top-right-radius: 5px; + -webkit-border-bottom-right-radius: 5px; + -webkit-border-bottom-left-radius: 0; + -webkit-border-top-left-radius: 0; + -moz-border-radius-topright: 5px; + -moz-border-radius-bottomright: 5px; + -moz-border-radius-bottomleft: 0; + -moz-border-radius-topleft: 0; + border-top-right-radius: 5px; + border-bottom-right-radius: 5px; + border-bottom-left-radius: 0; + border-top-left-radius: 0; + -moz-background-clip: padding; + -webkit-background-clip: padding-box; + background-clip: padding-box; } /* Font Awesome the iconic font designed for use with Twitter Bootstrap @@ -6286,6 +7443,19 @@ ul.icons li .icon-large:before { -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + -ms-box-sizing: border-box; + box-sizing: border-box; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; -ms-box-sizing: border-box; @@ -6295,6 +7465,10 @@ ul.icons li .icon-large:before { height: 100%; height: 50px; width: 100%; + width: 50px; + height: 100%; + height: 50px; + width: 100%; } .lte8 #large-search-input, .lte8 .large-search-bar { @@ -6319,11 +7493,20 @@ ul.icons li .icon-large:before { right: auto; bottom: auto; left: 8px; + position: absolute; + top: 16px; + right: auto; + bottom: auto; + left: 8px; } .large-search-form .throbber { background-image: url(http://www.khanacademy.org//images/throbber.gif); - /*! data-uri(/images/throbber.gif) */ - + width: 16px; + height: 16px; + height: 16px; + width: 16px; + width: 16px; + height: 16px; height: 16px; width: 16px; position: absolute; @@ -6331,6 +7514,11 @@ ul.icons li .icon-large:before { right: auto; bottom: auto; left: 8px; + position: absolute; + top: 14px; + right: auto; + bottom: auto; + left: 8px; visibility: hidden; } .large-search-form .large-search-submit { @@ -6367,6 +7555,7 @@ ul.icons li .icon-large:before { line-height: 22px; } .progress-container .progress-icon.icon-exercise-node, +.progress-container .progress-icon.icon-scratchpad-node, .progress-container .progress-icon.icon-video-node { color: #dddddd; display: table-cell; @@ -6374,6 +7563,7 @@ ul.icons li .icon-large:before { text-indent: 0; } .progress-container .progress-icon.icon-exercise-node:after, +.progress-container .progress-icon.icon-scratchpad-node:after, .progress-container .progress-icon.icon-video-node:after { color: #76a005; display: none; @@ -6384,18 +7574,25 @@ ul.icons li .icon-large:before { right: auto; bottom: auto; left: 3px; + position: absolute; + top: 2px; + right: auto; + bottom: auto; + left: 3px; font-family: FontAwesome; font-weight: normal; font-style: normal; text-decoration: inherit; } .progress-container .progress-icon.icon-exercise-node.small-icon, +.progress-container .progress-icon.icon-scratchpad-node.small-icon, .progress-container .progress-icon.icon-video-node.small-icon { font-size: 12px; width: auto; line-height: 22px; } .progress-container .progress-icon.icon-exercise-node.small-icon:after, +.progress-container .progress-icon.icon-scratchpad-node.small-icon:after, .progress-container .progress-icon.icon-video-node.small-icon:after { height: 9px; position: absolute; @@ -6403,6 +7600,11 @@ ul.icons li .icon-large:before { right: auto; bottom: auto; left: 0px; + position: absolute; + top: 1px; + right: auto; + bottom: auto; + left: 0px; } .progress-container .progress-icon.icon-exercise-node { font-size: 18px; @@ -6414,6 +7616,11 @@ ul.icons li .icon-large:before { right: auto; bottom: auto; left: 3px; + position: absolute; + top: 1px; + right: auto; + bottom: auto; + left: 3px; } .progress-container .progress-icon.icon-exercise-node:before, .progress-container .progress-icon.icon-exercise-node:after { @@ -6423,6 +7630,10 @@ ul.icons li .icon-large:before { .progress-container .progress-icon.icon-video-node:after { content: "\f03d"; } +.progress-container .progress-icon.icon-scratchpad-node:before, +.progress-container .progress-icon.icon-scratchpad-node:after { + content: "\f03e"; +} .progress-container .progress-icon.progress-started:after { display: inline-block !important; } @@ -6444,6 +7655,24 @@ ul.icons li .icon-large:before { right: auto; bottom: auto; left: 9px; + position: absolute; + top: 11px; + right: auto; + bottom: auto; + left: 9px; +} +.tutorial-nav-node.progress-container .progress-icon.icon-scratchpad-node:after { + height: 7px; + position: absolute; + top: 11px; + right: auto; + bottom: auto; + left: 9px; + position: absolute; + top: 11px; + right: auto; + bottom: auto; + left: 9px; } .tutorial-nav-node.progress-container .progress-icon.icon-exercise-node:after { height: 8px; @@ -6452,8 +7681,14 @@ ul.icons li .icon-large:before { right: auto; bottom: auto; left: 9px; + position: absolute; + top: 10px; + right: auto; + bottom: auto; + left: 9px; } .related-video-list .progress-container .progress-icon.icon-exercise-node:after, +.related-video-list .progress-container .progress-icon.icon-scratchpad-node:after, .related-video-list .progress-container .progress-icon.icon-video-node:after { height: 10px; position: absolute; @@ -6461,8 +7696,14 @@ ul.icons li .icon-large:before { right: auto; bottom: auto; left: 2px; + position: absolute; + top: 1px; + right: auto; + bottom: auto; + left: 2px; } .topic-video .progress-container .progress-icon.icon-exercise-node:after, +.topic-video .progress-container .progress-icon.icon-scratchpad-node:after, .topic-video .progress-container .progress-icon.icon-video-node:after { height: 11px; } @@ -6476,6 +7717,11 @@ ul.icons li .icon-large:before { right: auto; bottom: auto; left: 14px; + position: absolute; + top: 3px; + right: auto; + bottom: auto; + left: 14px; } #library-content.library-rtl .topic-heading, #library-content.library-rtl .topic-desc { @@ -6507,13 +7753,51 @@ ul.icons li .icon-large:before { -moz-box-sizing: border-box; -ms-box-sizing: border-box; box-sizing: border-box; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + -ms-box-sizing: border-box; + box-sizing: border-box; +} +#khanType .thinHeader { + color: #2c3747; + display: block; + font-family: "MuseoSans300", sans-serif; + font-size: 24px; + font-weight: normal; +} +#khanType .smallThinHeader { + color: #555; + display: block; + font-family: "MuseoSans300", sans-serif; + font-size: 18px; + font-weight: normal; + line-height: 22px; +} +#khanType .headerDescription { + color: #a9c0d1; + display: block; + font-family: "MuseoSans300", sans-serif; + font-size: 13px; + font-weight: normal; + line-height: 22px; + margin-top: 2px; } .vertical-shadow { + border: 1px solid #cccccc; border: 1px solid #cccccc; border-bottom: 1px solid #aaa; -webkit-box-shadow: 0 1px 3px #cccccc; -moz-box-shadow: 0 1px 3px #cccccc; box-shadow: 0 1px 3px #cccccc; + -webkit-box-shadow: 0 1px 3px #cccccc; + -moz-box-shadow: 0 1px 3px #cccccc; + box-shadow: 0 1px 3px #cccccc; + -webkit-box-shadow: 0 1px 3px #cccccc; + -moz-box-shadow: 0 1px 3px #cccccc; + box-shadow: 0 1px 3px #cccccc; + -webkit-box-shadow: 0 1px 3px #cccccc; + -moz-box-shadow: 0 1px 3px #cccccc; + box-shadow: 0 1px 3px #cccccc; } .ie8 .subscription { visibility: hidden; @@ -6529,12 +7813,27 @@ ul.icons li .icon-large:before { border: 1px solid #cccccc; height: 25px; font-family: "MuseoSans300", sans-serif; + font-family: "MuseoSans300", sans-serif; + font-size: 14px; + font-weight: normal; + line-height: 22px; + font-size: 14px; + font-weight: normal; + line-height: 22px; + font-family: "MuseoSans300", sans-serif; + font-family: "MuseoSans300", sans-serif; + font-size: 14px; + font-weight: normal; + line-height: 22px; font-size: 14px; font-weight: normal; line-height: 22px; -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; } .subscription input.invalid { border-color: #FF0000; @@ -6554,10 +7853,31 @@ ul.icons li .icon-large:before { -webkit-box-shadow: 0 5px 8px #333333; -moz-box-shadow: 0 5px 8px #333333; box-shadow: 0 5px 8px #333333; + -webkit-box-shadow: 0 5px 8px #333333; + -moz-box-shadow: 0 5px 8px #333333; + box-shadow: 0 5px 8px #333333; + -webkit-box-shadow: 0 5px 8px #333333; + -moz-box-shadow: 0 5px 8px #333333; + box-shadow: 0 5px 8px #333333; + -webkit-box-shadow: 0 5px 8px #333333; + -moz-box-shadow: 0 5px 8px #333333; + box-shadow: 0 5px 8px #333333; } .subscription .subscribe-button { display: inline-block; font-family: "MuseoSans500", sans-serif; + font-family: "MuseoSans500", sans-serif; + font-size: 14px; + font-weight: normal; + line-height: 22px; + font-size: 14px; + font-weight: normal; + line-height: 22px; + font-family: "MuseoSans500", sans-serif; + font-family: "MuseoSans500", sans-serif; + font-size: 14px; + font-weight: normal; + line-height: 22px; font-size: 14px; font-weight: normal; line-height: 22px; @@ -6654,6 +7974,10 @@ input.placeholder { *display: inline; /* IE7 inline-block hack */ + *zoom: 1; + *display: inline; + /* IE7 inline-block hack */ + *zoom: 1; margin-bottom: 0; } @@ -6698,6 +8022,7 @@ legend + .control-group { .form-horizontal .control-group { margin-bottom: 22px; *zoom: 1; + *zoom: 1; } .form-horizontal .control-group:before, .form-horizontal .control-group:after { @@ -6765,6 +8090,8 @@ legend + .control-group { .modal-backdrop.fade.in { opacity: 0.8; filter: alpha(opacity=80); + opacity: 0.8; + filter: alpha(opacity=80); } .modal { position: fixed; @@ -6783,14 +8110,40 @@ legend + .control-group { -webkit-border-radius: 6px; -moz-border-radius: 6px; border-radius: 6px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -webkit-background-clip: padding-box; + -moz-background-clip: padding-box; + background-clip: padding-box; -webkit-background-clip: padding-box; -moz-background-clip: padding-box; background-clip: padding-box; } .modal.fade { + -webkit-transition: opacity .3s linear, top .3s ease-out; + -moz-transition: opacity .3s linear, top .3s ease-out; + -ms-transition: opacity .3s linear, top .3s ease-out; + -o-transition: opacity .3s linear, top .3s ease-out; + transition: opacity .3s linear, top .3s ease-out; -webkit-transition: opacity .3s linear, top .3s ease-out; -moz-transition: opacity .3s linear, top .3s ease-out; -ms-transition: opacity .3s linear, top .3s ease-out; @@ -6825,10 +8178,29 @@ legend + .control-group { -webkit-border-radius: 0 0 6px 6px; -moz-border-radius: 0 0 6px 6px; border-radius: 0 0 6px 6px; + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; + -webkit-box-shadow: inset 0 1px 0 #ffffff; + -moz-box-shadow: inset 0 1px 0 #ffffff; + box-shadow: inset 0 1px 0 #ffffff; + -webkit-box-shadow: inset 0 1px 0 #ffffff; + -moz-box-shadow: inset 0 1px 0 #ffffff; + box-shadow: inset 0 1px 0 #ffffff; + -webkit-box-shadow: inset 0 1px 0 #ffffff; + -moz-box-shadow: inset 0 1px 0 #ffffff; + box-shadow: inset 0 1px 0 #ffffff; -webkit-box-shadow: inset 0 1px 0 #ffffff; -moz-box-shadow: inset 0 1px 0 #ffffff; box-shadow: inset 0 1px 0 #ffffff; *zoom: 1; + *zoom: 1; } .modal-footer:before, .modal-footer:after { @@ -6863,6 +8235,7 @@ legend + .control-group { } .modal h2, .modal h4 { + font-family: "MuseoSans300", sans-serif; font-family: "MuseoSans300", sans-serif; color: #555555; } @@ -6873,6 +8246,8 @@ legend + .control-group { .modal-backdrop.fade.in { opacity: 0.3; filter: alpha(opacity=30); + opacity: 0.3; + filter: alpha(opacity=30); } .modal-header { border-bottom: 1px solid #ddd; @@ -6904,24 +8279,21 @@ legend + .control-group { } .notification-bar { background: #356700; - width: 100%; - height: 35px; + height: 40px; text-align: center; - vertical-align: middle; border-bottom: 1px solid #233400; - color: #eee; + color: #eeeeee; position: fixed; z-index: 200; left: 0; - top: -35px; + right: 0; + top: -40px; font-size: 16px; /* Override to base-element-styles.css link styling. */ } .notification-bar.auto-visible { - position: static; top: 0; - width: auto; } .notification-bar a:link, .notification-bar a:visited, @@ -6930,44 +8302,95 @@ legend + .control-group { .notification-bar a:link:focus, .notification-bar a:visited:focus { text-decoration: underline; - color: #eee; + color: #eeeeee; +} +.notification-bar .notification-bar-close { + float: right; + line-height: 40px; + position: absolute; + right: 20px; +} +.notification-bar .notification-bar-content { + position: relative; + /* For vertical positioning. */ + + line-height: 40px; } .notification-bar.phantom-notification-bar { + color: #d3d9cc; padding: 0 8px; - text-align: left; +} +.notification-bar.phantom-notification-bar.error { + background: #e5772e; + border-bottom-color: #513326; + text-align: center; +} +.notification-bar.phantom-notification-bar.error .notification-bar-content { + color: #faebe1; + text-shadow: 0 -1px 0 #743002; } .notification-bar.phantom-notification-bar .email-address { - color: #fff; + color: #eeeeee; } -.notification-bar.phantom-notification-bar .finish-sign-up { +.notification-bar.phantom-notification-bar a.resend-link, +.notification-bar.phantom-notification-bar a.change-link { color: #d3d9cc; + line-height: 40px; + margin-left: 8px; } -.notification-bar.phantom-notification-bar .resend-link { - float: right; - /* Same as the notification-bar itself - used to vertically center. */ - - line-height: 35px; +.notification-bar.phantom-notification-bar a.resend-link.no-link, +.notification-bar.phantom-notification-bar a.change-link.no-link { + text-decoration: none; + cursor: text; +} +.notification-bar.phantom-notification-bar a.resend-link:not(.no-link):link:hover, +.notification-bar.phantom-notification-bar a.change-link:not(.no-link):link:hover { + color: #eeeeee; } .notification-bar.phantom-notification-bar .simple-button { - margin-right: 7px; + margin: 0 5px 0 7px; /* Adjust to work with envelope icon */ padding: 5px 5px 5px 10px; } -.notification-bar-content { - vertical-align: middle; - position: relative; - top: 5px; -} -.notification-bar-close { - float: right; - position: absolute; - top: 5px; - right: 20px; -} .notification-bar-spacer { height: 0; } +.notification-bar-spacer.auto-visible { + height: 40px; +} +/* TODO(benkomalo): these change-signup-email-dialog styles aren't strictly + notification-bar related, but that dialog is triggered and only accessible + via a notification bar, so there's no better place right now. */ +.change-signup-email-dialog.modal { + width: 300px; + margin-left: -150px; +} +.change-signup-email-dialog.modal.fade.in { + top: 200px; +} +.change-signup-email-dialog .field-row { + margin-top: 8px; +} +.change-signup-email-dialog label { + display: inline-block; + font-size: 14px; + margin-right: 6px; + width: 48px; + text-align: right; +} +.change-signup-email-dialog .simple-input { + display: inline-block; + font-size: 14px; + padding: 0 4px; + width: 231px; +} +.change-signup-email-dialog .simple-button { + font-size: 14px; +} +.change-signup-email-dialog .error { + color: red; +} .popover { position: absolute; top: 0; @@ -6989,6 +8412,22 @@ legend + .control-group { margin-left: -5px; } .popover.top .arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-top: 5px solid #000000; + bottom: 0; + left: 50%; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 4px solid #444444; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 4px solid #444444; + bottom: 0; + left: 50%; margin-left: -5px; border-left: 5px solid transparent; border-right: 5px solid transparent; @@ -6998,8 +8437,27 @@ legend + .control-group { border-left: 4px solid transparent; border-right: 4px solid transparent; border-top: 4px solid #444444; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 4px solid #444444; } .popover.right .arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + border-right: 5px solid #000000; + top: 50%; + left: 0; + border-top: 4px solid transparent; + border-bottom: 4px solid transparent; + border-right: 4px solid #444444; + border-top: 4px solid transparent; + border-bottom: 4px solid transparent; + border-right: 4px solid #444444; + top: 50%; + left: 0; margin-top: -5px; border-top: 5px solid transparent; border-bottom: 5px solid transparent; @@ -7009,8 +8467,27 @@ legend + .control-group { border-top: 4px solid transparent; border-bottom: 4px solid transparent; border-right: 4px solid #444444; + border-top: 4px solid transparent; + border-bottom: 4px solid transparent; + border-right: 4px solid #444444; } .popover.bottom .arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-bottom: 5px solid #000000; + top: 0; + left: 50%; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-bottom: 4px solid #444444; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-bottom: 4px solid #444444; + top: 0; + left: 50%; margin-left: -5px; border-left: 5px solid transparent; border-right: 5px solid transparent; @@ -7020,8 +8497,27 @@ legend + .control-group { border-left: 4px solid transparent; border-right: 4px solid transparent; border-bottom: 4px solid #444444; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-bottom: 4px solid #444444; } .popover.left .arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + border-left: 5px solid #000000; + top: 50%; + right: 0; + border-top: 4px solid transparent; + border-bottom: 4px solid transparent; + border-left: 4px solid #444444; + border-top: 4px solid transparent; + border-bottom: 4px solid transparent; + border-left: 4px solid #444444; + top: 50%; + right: 0; margin-top: -5px; border-top: 5px solid transparent; border-bottom: 5px solid transparent; @@ -7031,6 +8527,9 @@ legend + .control-group { border-top: 4px solid transparent; border-bottom: 4px solid transparent; border-left: 4px solid #444444; + border-top: 4px solid transparent; + border-bottom: 4px solid transparent; + border-left: 4px solid #444444; } .popover .arrow { position: absolute; @@ -7046,6 +8545,24 @@ legend + .control-group { -webkit-border-radius: 6px; -moz-border-radius: 6px; border-radius: 6px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); @@ -7058,6 +8575,15 @@ legend + .control-group { -webkit-border-radius: 3px 3px 0 0; -moz-border-radius: 3px 3px 0 0; border-radius: 3px 3px 0 0; + -webkit-border-radius: 3px 3px 0 0; + -moz-border-radius: 3px 3px 0 0; + border-radius: 3px 3px 0 0; + -webkit-border-radius: 3px 3px 0 0; + -moz-border-radius: 3px 3px 0 0; + border-radius: 3px 3px 0 0; + -webkit-border-radius: 3px 3px 0 0; + -moz-border-radius: 3px 3px 0 0; + border-radius: 3px 3px 0 0; } .popover-content { padding: 14px; @@ -7065,6 +8591,18 @@ legend + .control-group { -webkit-border-radius: 0 0 3px 3px; -moz-border-radius: 0 0 3px 3px; border-radius: 0 0 3px 3px; + -webkit-border-radius: 0 0 3px 3px; + -moz-border-radius: 0 0 3px 3px; + border-radius: 0 0 3px 3px; + -webkit-border-radius: 0 0 3px 3px; + -moz-border-radius: 0 0 3px 3px; + border-radius: 0 0 3px 3px; + -webkit-border-radius: 0 0 3px 3px; + -moz-border-radius: 0 0 3px 3px; + border-radius: 0 0 3px 3px; + -webkit-background-clip: padding-box; + -moz-background-clip: padding-box; + background-clip: padding-box; -webkit-background-clip: padding-box; -moz-background-clip: padding-box; background-clip: padding-box; @@ -7136,15 +8674,11 @@ ul.inline-list li { .goal a.objective.GoalObjectiveExerciseProficiency:before, .goal a.objective.GoalObjectiveAnyExerciseProficiency:before { background: #3a4759 url(http://www.khanacademy.org//images/generic-exercise-icon-inset-small.png) no-repeat 4px 4px; - /*! data-uri(/images/generic-exercise-icon-inset-small.png) */ - } .goal a.objective.video:before, .goal a.objective.GoalObjectiveWatchVideo:before, .goal a.objective.GoalObjectiveAnyVideo:before { background: #3a4759 url(http://www.khanacademy.org//images/video-camera-icon-inset-small.png) no-repeat 50% 50%; - /*! data-uri(/images/video-camera-icon-inset-small.png) */ - } .ie .goal a.objective:before { border: none; @@ -7178,8 +8712,6 @@ ul.inline-list li { width: 20px; height: 20px; background: transparent url(http://www.khanacademy.org//images/video-camera-icon-full-small.png) no-repeat 0 1px; - /*! data-uri(/images/video-camera-icon-full-small.png) */ - position: absolute; left: -5px; top: 0; @@ -7197,8 +8729,6 @@ ul.inline-list li { width: 20px; height: 20px; background: transparent url(http://www.khanacademy.org//images/generic-exercise-icon-full-small.png) no-repeat 0 0; - /*! data-uri(/images/generic-exercise-icon-full-small.png) */ - position: absolute; left: -6px; top: 0; @@ -7252,8 +8782,6 @@ ul.inline-list li { width: 30px; height: 30px; background: #c7e5f7 url(http://www.khanacademy.org//images/objective-complete-tick.png) no-repeat 50% 50%; - /*! data-uri(/images/objective-complete-tick.png) */ - position: absolute; left: -12px; top: -5px; @@ -7276,8 +8804,6 @@ ul.inline-list li { #create-goal-view .goal a.objective.exercise:hover:before, #create-goal-view .goal a.objective.video:hover:before { background: #3a4759 url(http://www.khanacademy.org//images/delete-icon-inset-small.png) no-repeat 50% 50%; - /*! data-uri(/images/delete-icon-inset-small.png) */ - } #create-goal-view .goal a.objective:hover:before { border-color: #C30202; @@ -7548,6 +9074,10 @@ a.simple-button.seethrough.goal-history { -moz-box-sizing: border-box; -ms-box-sizing: border-box; box-sizing: border-box; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + -ms-box-sizing: border-box; + box-sizing: border-box; } .goalpicker h3, .goalpicker h4 { @@ -7685,6 +9215,17 @@ a.simple-button.seethrough.goal-history { right: 50px; bottom: 50px; left: 50px; + position: fixed; + top: 85px; + right: 50px; + bottom: 50px; + left: 50px; + width: auto; + height: auto; + height: auto; + width: auto; + width: auto; + height: auto; height: auto; width: auto; } @@ -7692,6 +9233,7 @@ a.simple-button.seethrough.goal-history { top: 85px; } .modal.goal-new-custom .modal-body { + padding-top: 0; max-height: none; } .modal.goal-new-custom .progress-bar-wrapper { @@ -7755,12 +9297,39 @@ a.simple-button.seethrough.goal-history { -ms-box-sizing: border-box; box-sizing: border-box; } +#khanType .thinHeader { + color: #2c3747; + display: block; + font-family: "MuseoSans300", sans-serif; + font-size: 24px; + font-weight: normal; +} +#khanType .smallThinHeader { + color: #555; + display: block; + font-family: "MuseoSans300", sans-serif; + font-size: 18px; + font-weight: normal; + line-height: 22px; +} +#khanType .headerDescription { + color: #a9c0d1; + display: block; + font-family: "MuseoSans300", sans-serif; + font-size: 13px; + font-weight: normal; + line-height: 22px; + margin-top: 2px; +} .vertical-shadow { border: 1px solid #cccccc; border-bottom: 1px solid #aaa; -webkit-box-shadow: 0 1px 3px #cccccc; -moz-box-shadow: 0 1px 3px #cccccc; box-shadow: 0 1px 3px #cccccc; + -webkit-box-shadow: 0 1px 3px #cccccc; + -moz-box-shadow: 0 1px 3px #cccccc; + box-shadow: 0 1px 3px #cccccc; } /* Stack Key Frame Animations */ /* Stack to current card to finished stack animations */ @@ -8039,49 +9608,49 @@ a.simple-button.seethrough.goal-history { * the chaining transforms (rotate, translate, rotate, translate) used here. */ .half-circle-arc 0% { - -webkit-transform: rotate(0deg) translateX(70px) rotate(0deg) translateX(-70px); - -moz-transform: rotate(0deg) translateX(70px) rotate(0deg) translateX(-70px); - -ms-transform: rotate(0deg) translateX(70px) rotate(0deg) translateX(-70px); + -webkit-transform: rotate(0deg) translatex(70px) rotate(0deg) translatex(-70px); + -moz-transform: rotate(0deg) translatex(70px) rotate(0deg) translatex(-70px); + -ms-transform: rotate(0deg) translatex(70px) rotate(0deg) translatex(-70px); } .half-circle-arc 100% { - -webkit-transform: rotate(-180deg) translateX(70px) rotate(180deg) translateX(-70px); - -moz-transform: rotate(-180deg) translateX(70px) rotate(180deg) translateX(-70px); - -ms-transform: rotate(-180deg) translateX(70px) rotate(180deg) translateX(-70px); + -webkit-transform: rotate(-180deg) translatex(70px) rotate(180deg) translatex(-70px); + -moz-transform: rotate(-180deg) translatex(70px) rotate(180deg) translatex(-70px); + -ms-transform: rotate(-180deg) translatex(70px) rotate(180deg) translatex(-70px); } @-webkit-keyframes card-up-down { 0% { - -webkit-transform: rotate(0deg) translateX(70px) rotate(0deg) translateX(-70px); - -moz-transform: rotate(0deg) translateX(70px) rotate(0deg) translateX(-70px); - -ms-transform: rotate(0deg) translateX(70px) rotate(0deg) translateX(-70px); + -webkit-transform: rotate(0deg) translatex(70px) rotate(0deg) translatex(-70px); + -moz-transform: rotate(0deg) translatex(70px) rotate(0deg) translatex(-70px); + -ms-transform: rotate(0deg) translatex(70px) rotate(0deg) translatex(-70px); } 100% { - -webkit-transform: rotate(-180deg) translateX(70px) rotate(180deg) translateX(-70px); - -moz-transform: rotate(-180deg) translateX(70px) rotate(180deg) translateX(-70px); - -ms-transform: rotate(-180deg) translateX(70px) rotate(180deg) translateX(-70px); + -webkit-transform: rotate(-180deg) translatex(70px) rotate(180deg) translatex(-70px); + -moz-transform: rotate(-180deg) translatex(70px) rotate(180deg) translatex(-70px); + -ms-transform: rotate(-180deg) translatex(70px) rotate(180deg) translatex(-70px); } } @-moz-keyframes card-up-down { 0% { - -webkit-transform: rotate(0deg) translateX(70px) rotate(0deg) translateX(-70px); - -moz-transform: rotate(0deg) translateX(70px) rotate(0deg) translateX(-70px); - -ms-transform: rotate(0deg) translateX(70px) rotate(0deg) translateX(-70px); + -webkit-transform: rotate(0deg) translatex(70px) rotate(0deg) translatex(-70px); + -moz-transform: rotate(0deg) translatex(70px) rotate(0deg) translatex(-70px); + -ms-transform: rotate(0deg) translatex(70px) rotate(0deg) translatex(-70px); } 100% { - -webkit-transform: rotate(-180deg) translateX(70px) rotate(180deg) translateX(-70px); - -moz-transform: rotate(-180deg) translateX(70px) rotate(180deg) translateX(-70px); - -ms-transform: rotate(-180deg) translateX(70px) rotate(180deg) translateX(-70px); + -webkit-transform: rotate(-180deg) translatex(70px) rotate(180deg) translatex(-70px); + -moz-transform: rotate(-180deg) translatex(70px) rotate(180deg) translatex(-70px); + -ms-transform: rotate(-180deg) translatex(70px) rotate(180deg) translatex(-70px); } } @-ms-keyframes card-up-down { 0% { - -webkit-transform: rotate(0deg) translateX(70px) rotate(0deg) translateX(-70px); - -moz-transform: rotate(0deg) translateX(70px) rotate(0deg) translateX(-70px); - -ms-transform: rotate(0deg) translateX(70px) rotate(0deg) translateX(-70px); + -webkit-transform: rotate(0deg) translatex(70px) rotate(0deg) translatex(-70px); + -moz-transform: rotate(0deg) translatex(70px) rotate(0deg) translatex(-70px); + -ms-transform: rotate(0deg) translatex(70px) rotate(0deg) translatex(-70px); } 100% { - -webkit-transform: rotate(-180deg) translateX(70px) rotate(180deg) translateX(-70px); - -moz-transform: rotate(-180deg) translateX(70px) rotate(180deg) translateX(-70px); - -ms-transform: rotate(-180deg) translateX(70px) rotate(180deg) translateX(-70px); + -webkit-transform: rotate(-180deg) translatex(70px) rotate(180deg) translatex(-70px); + -moz-transform: rotate(-180deg) translatex(70px) rotate(180deg) translatex(-70px); + -ms-transform: rotate(-180deg) translatex(70px) rotate(180deg) translatex(-70px); } } .stack .card-container.into-pocket { @@ -8275,7 +9844,7 @@ a.simple-button.seethrough.goal-history { /* the default card/stack view */ /* this handles much of pre-tutorials exercise layout which is encapsulated in stacks and cards: i.e. the stack of mini cards, the big exercise card, etc. - + */ .stack { min-height: 100px; @@ -8314,6 +9883,9 @@ a.simple-button.seethrough.goal-history { -webkit-box-shadow: 0 0 3px #cccccc; -moz-box-shadow: 0 0 3px #cccccc; box-shadow: 0 0 3px #cccccc; + -webkit-box-shadow: 0 0 3px #cccccc; + -moz-box-shadow: 0 0 3px #cccccc; + box-shadow: 0 0 3px #cccccc; } .exercise-template-old .stack .card { -webkit-transition: all 0.18s ease-in-out; @@ -8357,6 +9929,9 @@ a.simple-button.seethrough.goal-history { background-color: #aaa; } .stack .card-face.card-back { + -webkit-box-shadow: inset 0 0 0 2px #fff, inset 0 0 0 4px #cfcfcf; + -moz-box-shadow: inset 0 0 0 2px #fff, inset 0 0 0 4px #cfcfcf; + box-shadow: inset 0 0 0 2px #fff, inset 0 0 0 4px #cfcfcf; -webkit-box-shadow: inset 0 0 0 2px #fff, inset 0 0 0 4px #cfcfcf; -moz-box-shadow: inset 0 0 0 2px #fff, inset 0 0 0 4px #cfcfcf; box-shadow: inset 0 0 0 2px #fff, inset 0 0 0 4px #cfcfcf; @@ -8376,6 +9951,9 @@ a.simple-button.seethrough.goal-history { -webkit-box-shadow: inset 0 0 0 2px white, inset 0 0 0 4px #e9efdd; -moz-box-shadow: inset 0 0 0 2px white, inset 0 0 0 4px #e9efdd; box-shadow: inset 0 0 0 2px white, inset 0 0 0 4px #e9efdd; + -webkit-box-shadow: inset 0 0 0 2px white, inset 0 0 0 4px #e9efdd; + -moz-box-shadow: inset 0 0 0 2px white, inset 0 0 0 4px #e9efdd; + box-shadow: inset 0 0 0 2px white, inset 0 0 0 4px #e9efdd; } .exercises-stack, .exercises-card { @@ -8431,7 +10009,7 @@ a.simple-button.seethrough.goal-history { .card-type-problem .leaves-container { display: block; } -.qtip.ui-tooltip.leaf-tooltip { +.qtip.leaf-tooltip { max-width: 200px !important; } /*FIXME(marcos): this seems at leaf.earned */ @@ -8484,6 +10062,9 @@ a.simple-button.seethrough.goal-history { -webkit-box-shadow: inset 0 0 9px 1px rgba(0, 0, 0, 0.25); -moz-box-shadow: inset 0 0 9px 1px rgba(0, 0, 0, 0.25); box-shadow: inset 0 0 9px 1px rgba(0, 0, 0, 0.25); + -webkit-box-shadow: inset 0 0 9px 1px rgba(0, 0, 0, 0.25); + -moz-box-shadow: inset 0 0 9px 1px rgba(0, 0, 0, 0.25); + box-shadow: inset 0 0 9px 1px rgba(0, 0, 0, 0.25); } .leaves .leaf.available { /* Nothing right now */ @@ -8575,7 +10156,7 @@ a.simple-button.seethrough.goal-history { * * */ - -webkit-transform: translateZ(0); + -webkit-transform: translatez(0); } /* "Calculating End of Stack" Card Styling */ .calculating-end-of-stack { @@ -8669,6 +10250,9 @@ a.simple-button.seethrough.goal-history { -webkit-border-radius: 50px; -moz-border-radius: 50px; border-radius: 50px; + -webkit-border-radius: 50px; + -moz-border-radius: 50px; + border-radius: 50px; border: 1px solid #DDD; color: #777; cursor: default; @@ -9081,6 +10665,9 @@ a.simple-button.seethrough.goal-history { top: 5px; } #tutorial-page .tutorial-description .card-container:last-child .card-face.card-back { + -webkit-box-shadow: inset 0 0 0 2px white, inset 0 0 0 4px #cccccc; + -moz-box-shadow: inset 0 0 0 2px white, inset 0 0 0 4px #cccccc; + box-shadow: inset 0 0 0 2px white, inset 0 0 0 4px #cccccc; -webkit-box-shadow: inset 0 0 0 2px white, inset 0 0 0 4px #cccccc; -moz-box-shadow: inset 0 0 0 2px white, inset 0 0 0 4px #cccccc; box-shadow: inset 0 0 0 2px white, inset 0 0 0 4px #cccccc; @@ -9088,6 +10675,9 @@ a.simple-button.seethrough.goal-history { } #tutorial-page .tutorial-description .active .card, #tutorial-page .tutorial-description .completed .card { + -webkit-box-shadow: 0 0 4px #cccccc; + -moz-box-shadow: 0 0 4px #cccccc; + box-shadow: 0 0 4px #cccccc; -webkit-box-shadow: 0 0 4px #cccccc; -moz-box-shadow: 0 0 4px #cccccc; box-shadow: 0 0 4px #cccccc; @@ -9097,6 +10687,9 @@ a.simple-button.seethrough.goal-history { #tutorial-page .tutorial-description .completed:last-child .card-back.card-face, #tutorial-page .tutorial-description .active .card-back.card-face, #tutorial-page .tutorial-description .completed .card-back.card-face { + -webkit-box-shadow: inset 0 0 0 2px white, inset 0 0 0 4px #a7d2eb; + -moz-box-shadow: inset 0 0 0 2px white, inset 0 0 0 4px #a7d2eb; + box-shadow: inset 0 0 0 2px white, inset 0 0 0 4px #a7d2eb; -webkit-box-shadow: inset 0 0 0 2px white, inset 0 0 0 4px #a7d2eb; -moz-box-shadow: inset 0 0 0 2px white, inset 0 0 0 4px #a7d2eb; box-shadow: inset 0 0 0 2px white, inset 0 0 0 4px #a7d2eb; @@ -9117,6 +10710,9 @@ a.simple-button.seethrough.goal-history { -webkit-box-shadow: 0 0 4px #a7d2eb; -moz-box-shadow: 0 0 4px #a7d2eb; box-shadow: 0 0 4px #a7d2eb; + -webkit-box-shadow: 0 0 4px #a7d2eb; + -moz-box-shadow: 0 0 4px #a7d2eb; + box-shadow: 0 0 4px #a7d2eb; } #tutorial-page .tutorial-description .completed .card-face.card-back { background-color: #f4fafd; diff --git a/jquery.qtip.js b/jquery.qtip.js index 6f58c1973..f58d2e221 100644 --- a/jquery.qtip.js +++ b/jquery.qtip.js @@ -1,2197 +1,3313 @@ -/* -* qTip2 - Pretty powerful tooltips +/*! qTip2 - Pretty powerful tooltips - v2.0.0pre - 2012-12-14 * http://craigsworks.com/projects/qtip2/ -* -* Version: 2.0.0pre -* Copyright 2009-2010 Craig Michael Thompson - http://craigsworks.com -* -* Dual licensed under MIT or GPLv2 licenses -* http://en.wikipedia.org/wiki/MIT_License -* http://en.wikipedia.org/wiki/GNU_General_Public_License -* -* Date: Sun May 13 16:01:37 2012 +0100 -*/ +* Copyright (c) 2012 Craig Michael Thompson; Licensed MIT, GPL */ /*jslint browser: true, onevar: true, undef: true, nomen: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: true */ /*global window: false, jQuery: false, console: false, define: false */ +/* Cache window, document, undefined */ +(function( window, document, undefined ) { + // Uses AMD or browser globals to create a jQuery plugin. -(function(factory) { +(function( factory ) { + "use strict"; if(typeof define === 'function' && define.amd) { define(['jquery'], factory); } - else { + else if(jQuery && !jQuery.fn.qtip) { factory(jQuery); } } (function($) { + /* This currently causes issues with Safari 6, so for it's disabled */ + //"use strict"; // (Dis)able ECMAScript "strict" operation for this function. See more: http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/ - "use strict"; // Enable ECMAScript "strict" operation for this function. See more: http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/ - // Munge the primitives - Paul Irish tip var TRUE = true, FALSE = false, NULL = null, - undefined, - + + // Side names and other stuff + X = 'x', Y = 'y', + WIDTH = 'width', + HEIGHT = 'height', + TOP = 'top', + LEFT = 'left', + BOTTOM = 'bottom', + RIGHT = 'right', + CENTER = 'center', + FLIP = 'flip', + FLIPINVERT = 'flipinvert', + SHIFT = 'shift', + // Shortcut vars QTIP, PLUGINS, MOUSE, + NAMESPACE = 'qtip', usedIDs = {}, - uitooltip = 'ui-tooltip', - widget = 'ui-widget', - disabled = 'ui-state-disabled', - selector = 'div.qtip.'+uitooltip, - defaultClass = uitooltip + '-default', - focusClass = uitooltip + '-focus', - hoverClass = uitooltip + '-hover', - fluidClass = uitooltip + '-fluid', - hideOffset = '-31000px', + widget = ['ui-widget', 'ui-tooltip'], + selector = 'div.qtip.'+NAMESPACE, + defaultClass = NAMESPACE + '-default', + focusClass = NAMESPACE + '-focus', + hoverClass = NAMESPACE + '-hover', replaceSuffix = '_replacedByqTip', oldtitle = 'oldtitle', trackingBound; - - /* Thanks to Paul Irish for this one: http://paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/ */ - function log() { - log.history = log.history || []; - log.history.push(arguments); - - // Make sure console is present - if('object' === typeof console) { - - // Setup console and arguments - var c = console[ console.warn ? 'warn' : 'log' ], - args = Array.prototype.slice.call(arguments), a; - - // Add qTip2 marker to first argument if it's a string - if(typeof arguments[0] === 'string') { args[0] = 'qTip2: ' + args[0]; } - - // Apply console.warn or .log if not supported - a = c.apply ? c.apply(console, args) : c(args); - } - } - -// Option object sanitizer -function sanitizeOptions(opts) -{ - var content; - - if(!opts || 'object' !== typeof opts) { return FALSE; } - if(opts.metadata === NULL || 'object' !== typeof opts.metadata) { - opts.metadata = { - type: opts.metadata + // Store mouse coordinates + function storeMouse(event) + { + MOUSE = { + pageX: event.pageX, + pageY: event.pageY, + type: 'mousemove', + scrollX: window.pageXOffset || document.body.scrollLeft || document.documentElement.scrollLeft, + scrollY: window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop }; } +// Option object sanitizer +function sanitizeOptions(opts) +{ + var invalid = function(a) { return a === NULL || 'object' !== typeof a; }, + invalidContent = function(c) { return !$.isFunction(c) && ((!c && !c.attr) || c.length < 1 || ('object' === typeof c && !c.jquery && !c.then)); }; + + if(!opts || 'object' !== typeof opts) { return FALSE; } + + if(invalid(opts.metadata)) { + opts.metadata = { type: opts.metadata }; + } + + if('content' in opts) { + if(invalid(opts.content) || opts.content.jquery) { + opts.content = { text: opts.content }; + } + + if(invalidContent(opts.content.text || FALSE)) { + opts.content.text = FALSE; + } + + if('title' in opts.content) { + if(invalid(opts.content.title)) { + opts.content.title = { text: opts.content.title }; + } + + if(invalidContent(opts.content.title.text || FALSE)) { + opts.content.title.text = FALSE; + } + } + } + + if('position' in opts && invalid(opts.position)) { + opts.position = { my: opts.position, at: opts.position }; + } + + if('show' in opts && invalid(opts.show)) { + opts.show = opts.show.jquery ? { target: opts.show } : { event: opts.show }; + } + + if('hide' in opts && invalid(opts.hide)) { + opts.hide = opts.hide.jquery ? { target: opts.hide } : { event: opts.hide }; + } + + if('style' in opts && invalid(opts.style)) { + opts.style = { classes: opts.style }; + } + + // Sanitize plugin options + $.each(PLUGINS, function() { + if(this.sanitize) { this.sanitize(opts); } + }); + + return opts; +} + +/* +* Core plugin implementation +*/ +function QTip(target, options, id, attr) +{ + // Declare this reference + var self = this, + docBody = document.body, + tooltipID = NAMESPACE + '-' + id, + isPositioning = 0, + isDrawing = 0, + tooltip = $(), + namespace = '.qtip-' + id, + disabledClass = 'qtip-disabled', + elements, cache; + + // Setup class attributes + self.id = id; + self.rendered = FALSE; + self.destroyed = FALSE; + self.elements = elements = { target: target }; + self.timers = { img: {} }; + self.options = options; + self.checks = {}; + self.plugins = {}; + self.cache = cache = { + event: {}, + target: $(), + disabled: FALSE, + attr: attr, + onTarget: FALSE, + lastClass: '' + }; + + function convertNotation(notation) + { + var i = 0, obj, option = options, + + // Split notation into array + levels = notation.split('.'); + + // Loop through + while( option = option[ levels[i++] ] ) { + if(i < levels.length) { obj = option; } + } + + return [obj || options, levels.pop()]; + } + + function createWidgetClass(cls) + { + return widget.concat('').join(cls ? '-'+cls+' ' : ' '); + } + + function setWidget() + { + var on = options.style.widget, + disabled = tooltip.hasClass(disabledClass); + + tooltip.removeClass(disabledClass); + disabledClass = on ? 'ui-state-disabled' : 'qtip-disabled'; + tooltip.toggleClass(disabledClass, disabled); + + tooltip.toggleClass('ui-helper-reset '+createWidgetClass(), on).toggleClass(defaultClass, options.style.def && !on); + + if(elements.content) { + elements.content.toggleClass( createWidgetClass('content'), on); + } + if(elements.titlebar) { + elements.titlebar.toggleClass( createWidgetClass('header'), on); + } + if(elements.button) { + elements.button.toggleClass(NAMESPACE+'-icon', !on); + } + } + + function removeTitle(reposition) + { + if(elements.title) { + elements.titlebar.remove(); + elements.titlebar = elements.title = elements.button = NULL; + + // Reposition if enabled + if(reposition !== FALSE) { self.reposition(); } + } + } + + function createButton() + { + var button = options.content.title.button, + isString = typeof button === 'string', + close = isString ? button : 'Close tooltip'; + + if(elements.button) { elements.button.remove(); } + + // Use custom button if one was supplied by user, else use default + if(button.jquery) { + elements.button = button; + } + else { + elements.button = $('', { + 'class': 'qtip-close ' + (options.style.widget ? '' : NAMESPACE+'-icon'), + 'title': close, + 'aria-label': close + }) + .prepend( + $('', { + 'class': 'ui-icon ui-icon-close', + 'html': '×' + }) + ); + } + + // Create button and setup attributes + elements.button.appendTo(elements.titlebar || tooltip) + .attr('role', 'button') + .click(function(event) { + if(!tooltip.hasClass(disabledClass)) { self.hide(event); } + return FALSE; + }); + } + + function createTitle() + { + var id = tooltipID+'-title'; + + // Destroy previous title element, if present + if(elements.titlebar) { removeTitle(); } + + // Create title bar and title elements + elements.titlebar = $('
', { + 'class': NAMESPACE + '-titlebar ' + (options.style.widget ? createWidgetClass('header') : '') + }) + .append( + elements.title = $('
', { + 'id': id, + 'class': NAMESPACE + '-title', + 'aria-atomic': TRUE + }) + ) + .insertBefore(elements.content) + + // Button-specific events + .delegate('.qtip-close', 'mousedown keydown mouseup keyup mouseout', function(event) { + $(this).toggleClass('ui-state-active ui-state-focus', event.type.substr(-4) === 'down'); + }) + .delegate('.qtip-close', 'mouseover mouseout', function(event){ + $(this).toggleClass('ui-state-hover', event.type === 'mouseover'); + }); + + // Create button if enabled + if(options.content.title.button) { createButton(); } + } + + function updateButton(button) + { + var elem = elements.button; + + // Make sure tooltip is rendered and if not, return + if(!self.rendered) { return FALSE; } + + if(!button) { + elem.remove(); + } + else { + createButton(); + } + } + + function updateTitle(content, reposition) + { + var elem = elements.title; + + // Make sure tooltip is rendered and if not, return + if(!self.rendered || !content) { return FALSE; } + + // Use function to parse content + if($.isFunction(content)) { + content = content.call(target, cache.event, self); + } + + // Remove title if callback returns false or null/undefined (but not '') + if(content === FALSE || (!content && content !== '')) { return removeTitle(FALSE); } + + // Append new content if its a DOM array and show it if hidden + else if(content.jquery && content.length > 0) { + elem.empty().append(content.css({ display: 'block' })); + } + + // Content is a regular string, insert the new content + else { elem.html(content); } + + // Reposition if rnedered + if(reposition !== FALSE && self.rendered && tooltip[0].offsetWidth > 0) { + self.reposition(cache.event); + } + } + + function deferredContent(deferred) + { + if(deferred && $.isFunction(deferred.done)) { + deferred.done(function(c) { + updateContent(c, null, FALSE); + }); + } + } + + function updateContent(content, reposition, checkDeferred) + { + var elem = elements.content; + + // Make sure tooltip is rendered and content is defined. If not return + if(!self.rendered || !content) { return FALSE; } + + // Use function to parse content + if($.isFunction(content)) { + content = content.call(target, cache.event, self) || ''; + } + + // Handle deferred content + if(checkDeferred !== FALSE) { + deferredContent(options.content.deferred); + } + + // Append new content if its a DOM array and show it if hidden + if(content.jquery && content.length > 0) { + elem.empty().append(content.css({ display: 'block' })); + } + + // Content is a regular string, insert the new content + else { elem.html(content); } + + // Image detection + function detectImages(next) { + var images, srcs = {}; + + function imageLoad(image) { + // Clear src from object and any timers and events associated with the image + if(image) { + delete srcs[image.src]; + clearTimeout(self.timers.img[image.src]); + $(image).unbind(namespace); + } + + // If queue is empty after image removal, update tooltip and continue the queue + if($.isEmptyObject(srcs)) { + if(reposition !== FALSE) { + self.reposition(cache.event); + } + + next(); + } + } + + // Find all content images without dimensions, and if no images were found, continue + if((images = elem.find('img[src]:not([height]):not([width])')).length === 0) { return imageLoad(); } + + // Apply timer to each image to poll for dimensions + images.each(function(i, elem) { + // Skip if the src is already present + if(srcs[elem.src] !== undefined) { return; } + + // Keep track of how many times we poll for image dimensions. + // If it doesn't return in a reasonable amount of time, it's better + // to display the tooltip, rather than hold up the queue. + var iterations = 0, maxIterations = 3; + + (function timer(){ + // When the dimensions are found, remove the image from the queue + if(elem.height || elem.width || (iterations > maxIterations)) { return imageLoad(elem); } + + // Increase iterations and restart timer + iterations += 1; + self.timers.img[elem.src] = setTimeout(timer, 700); + }()); + + // Also apply regular load/error event handlers + $(elem).bind('error'+namespace+' load'+namespace, function(){ imageLoad(this); }); + + // Store the src and element in our object + srcs[elem.src] = elem; + }); + } + + /* + * If we're still rendering... insert into 'fx' queue our image dimension + * checker which will halt the showing of the tooltip until image dimensions + * can be detected properly. + */ + if(self.rendered < 0) { tooltip.queue('fx', detectImages); } + + // We're fully rendered, so reset isDrawing flag and proceed without queue delay + else { isDrawing = 0; detectImages($.noop); } + + return self; + } + + function assignEvents() + { + var posOptions = options.position, + targets = { + show: options.show.target, + hide: options.hide.target, + viewport: $(posOptions.viewport), + document: $(document), + body: $(document.body), + window: $(window) + }, + events = { + show: $.trim('' + options.show.event).split(' '), + hide: $.trim('' + options.hide.event).split(' ') + }, + IE6 = $.browser.msie && parseInt($.browser.version, 10) === 6; + + // Define show event method + function showMethod(event) + { + if(tooltip.hasClass(disabledClass)) { return FALSE; } + + // Clear hide timers + clearTimeout(self.timers.show); + clearTimeout(self.timers.hide); + + // Start show timer + var callback = function(){ self.toggle(TRUE, event); }; + if(options.show.delay > 0) { + self.timers.show = setTimeout(callback, options.show.delay); + } + else{ callback(); } + } + + // Define hide method + function hideMethod(event) + { + if(tooltip.hasClass(disabledClass) || isPositioning || isDrawing) { return FALSE; } + + // Check if new target was actually the tooltip element + var relatedTarget = $(event.relatedTarget || event.target), + ontoTooltip = relatedTarget.closest(selector)[0] === tooltip[0], + ontoTarget = relatedTarget[0] === targets.show[0]; + + // Clear timers and stop animation queue + clearTimeout(self.timers.show); + clearTimeout(self.timers.hide); + + // Prevent hiding if tooltip is fixed and event target is the tooltip. Or if mouse positioning is enabled and cursor momentarily overlaps + if((posOptions.target === 'mouse' && ontoTooltip) || (options.hide.fixed && ((/mouse(out|leave|move)/).test(event.type) && (ontoTooltip || ontoTarget)))) { + try { event.preventDefault(); event.stopImmediatePropagation(); } catch(e) {} return; + } + + // If tooltip has displayed, start hide timer + if(options.hide.delay > 0) { + self.timers.hide = setTimeout(function(){ self.hide(event); }, options.hide.delay); + } + else{ self.hide(event); } + } + + // Define inactive method + function inactiveMethod(event) + { + if(tooltip.hasClass(disabledClass)) { return FALSE; } + + // Clear timer + clearTimeout(self.timers.inactive); + self.timers.inactive = setTimeout(function(){ self.hide(event); }, options.hide.inactive); + } + + function repositionMethod(event) { + if(self.rendered && tooltip[0].offsetWidth > 0) { self.reposition(event); } + } + + // On mouseenter/mouseleave... + tooltip.bind('mouseenter'+namespace+' mouseleave'+namespace, function(event) { + var state = event.type === 'mouseenter'; + + // Focus the tooltip on mouseenter (z-index stacking) + if(state) { self.focus(event); } + + // Add hover class + tooltip.toggleClass(hoverClass, state); + }); + + // If using mouseout/mouseleave as a hide event... + if(/mouse(out|leave)/i.test(options.hide.event)) { + // Hide tooltips when leaving current window/frame (but not select/option elements) + if(options.hide.leave === 'window') { + targets.window.bind('mouseout'+namespace+' blur'+namespace, function(event) { + if(!/select|option/.test(event.target.nodeName) && !event.relatedTarget) { self.hide(event); } + }); + } + } + + // Enable hide.fixed + if(options.hide.fixed) { + // Add tooltip as a hide target + targets.hide = targets.hide.add(tooltip); + + // Clear hide timer on tooltip hover to prevent it from closing + tooltip.bind('mouseover'+namespace, function() { + if(!tooltip.hasClass(disabledClass)) { clearTimeout(self.timers.hide); } + }); + } + + /* + * Make sure hoverIntent functions properly by using mouseleave to clear show timer if + * mouseenter/mouseout is used for show.event, even if it isn't in the users options. + */ + else if(/mouse(over|enter)/i.test(options.show.event)) { + targets.hide.bind('mouseleave'+namespace, function(event) { + clearTimeout(self.timers.show); + }); + } + + // Hide tooltip on document mousedown if unfocus events are enabled + if(('' + options.hide.event).indexOf('unfocus') > -1) { + posOptions.container.closest('html').bind('mousedown'+namespace+' touchstart'+namespace, function(event) { + var elem = $(event.target), + enabled = self.rendered && !tooltip.hasClass(disabledClass) && tooltip[0].offsetWidth > 0, + isAncestor = elem.parents(selector).filter(tooltip[0]).length > 0; + + if(elem[0] !== target[0] && elem[0] !== tooltip[0] && !isAncestor && + !target.has(elem[0]).length && !elem.attr('disabled') + ) { + self.hide(event); + } + }); + } + + // Check if the tooltip hides when inactive + if('number' === typeof options.hide.inactive) { + // Bind inactive method to target as a custom event + targets.show.bind('qtip-'+id+'-inactive', inactiveMethod); + + // Define events which reset the 'inactive' event handler + $.each(QTIP.inactiveEvents, function(index, type){ + targets.hide.add(elements.tooltip).bind(type+namespace+'-inactive', inactiveMethod); + }); + } + + // Apply hide events + $.each(events.hide, function(index, type) { + var showIndex = $.inArray(type, events.show), + targetHide = $(targets.hide); + + // Both events and targets are identical, apply events using a toggle + if((showIndex > -1 && targetHide.add(targets.show).length === targetHide.length) || type === 'unfocus') + { + targets.show.bind(type+namespace, function(event) { + if(tooltip[0].offsetWidth > 0) { hideMethod(event); } + else { showMethod(event); } + }); + + // Don't bind the event again + delete events.show[ showIndex ]; + } + + // Events are not identical, bind normally + else { targets.hide.bind(type+namespace, hideMethod); } + }); + + // Apply show events + $.each(events.show, function(index, type) { + targets.show.bind(type+namespace, showMethod); + }); + + // Check if the tooltip hides when mouse is moved a certain distance + if('number' === typeof options.hide.distance) { + // Bind mousemove to target to detect distance difference + targets.show.add(tooltip).bind('mousemove'+namespace, function(event) { + var origin = cache.origin || {}, + limit = options.hide.distance, + abs = Math.abs; + + // Check if the movement has gone beyond the limit, and hide it if so + if(abs(event.pageX - origin.pageX) >= limit || abs(event.pageY - origin.pageY) >= limit) { + self.hide(event); + } + }); + } + + // Mouse positioning events + if(posOptions.target === 'mouse') { + // Cache mousemove coords on show targets + targets.show.bind('mousemove'+namespace, storeMouse); + + // If mouse adjustment is on... + if(posOptions.adjust.mouse) { + // Apply a mouseleave event so we don't get problems with overlapping + if(options.hide.event) { + // Hide when we leave the tooltip and not onto the show target + tooltip.bind('mouseleave'+namespace, function(event) { + if((event.relatedTarget || event.target) !== targets.show[0]) { self.hide(event); } + }); + + // Track if we're on the target or not + elements.target.bind('mouseenter'+namespace+' mouseleave'+namespace, function(event) { + cache.onTarget = event.type === 'mouseenter'; + }); + } + + // Update tooltip position on mousemove + targets.document.bind('mousemove'+namespace, function(event) { + // Update the tooltip position only if the tooltip is visible and adjustment is enabled + if(self.rendered && cache.onTarget && !tooltip.hasClass(disabledClass) && tooltip[0].offsetWidth > 0) { + self.reposition(event || MOUSE); + } + }); + } + } + + // Adjust positions of the tooltip on window resize if enabled + if(posOptions.adjust.resize || targets.viewport.length) { + ($.event.special.resize ? targets.viewport : targets.window).bind('resize'+namespace, repositionMethod); + } + + // Adjust tooltip position on scroll of the window or viewport element if present + targets.window.bind('scroll'+namespace, repositionMethod); + } + + function unassignEvents() + { + var targets = [ + options.show.target[0], + options.hide.target[0], + self.rendered && elements.tooltip[0], + options.position.container[0], + options.position.viewport[0], + options.position.container.closest('html')[0], // unfocus + window, + document + ]; + + // Check if tooltip is rendered + if(self.rendered) { + $([]).pushStack( $.grep(targets, function(i){ return typeof i === 'object'; }) ).unbind(namespace); + } + + // Tooltip isn't yet rendered, remove render event + else { options.show.target.unbind(namespace+'-create'); } + } + + // Setup builtin .set() option checks + self.checks.builtin = { + // Core checks + '^id$': function(obj, o, v) { + var id = v === TRUE ? QTIP.nextid : v, + tooltipID = NAMESPACE + '-' + id; + + if(id !== FALSE && id.length > 0 && !$('#'+tooltipID).length) { + tooltip[0].id = tooltipID; + elements.content[0].id = tooltipID + '-content'; + elements.title[0].id = tooltipID + '-title'; + } + }, + + // Content checks + '^content.text$': function(obj, o, v) { updateContent(options.content.text); }, + '^content.deferred$': function(obj, o, v) { deferredContent(options.content.deferred); }, + '^content.title.text$': function(obj, o, v) { + // Remove title if content is null + if(!v) { return removeTitle(); } + + // If title isn't already created, create it now and update + if(!elements.title && v) { createTitle(); } + updateTitle(v); + }, + '^content.title.button$': function(obj, o, v){ updateButton(v); }, + + // Position checks + '^position.(my|at)$': function(obj, o, v){ + // Parse new corner value into Corner objecct + if('string' === typeof v) { + obj[o] = new PLUGINS.Corner(v); + } + }, + '^position.container$': function(obj, o, v){ + if(self.rendered) { tooltip.appendTo(v); } + }, + + // Show checks + '^show.ready$': function() { + if(!self.rendered) { self.render(1); } + else { self.toggle(TRUE); } + }, + + // Style checks + '^style.classes$': function(obj, o, v) { + tooltip.attr('class', NAMESPACE + ' qtip ' + v); + }, + '^style.width|height': function(obj, o, v) { + tooltip.css(o, v); + }, + '^style.widget|content.title': setWidget, + + // Events check + '^events.(render|show|move|hide|focus|blur)$': function(obj, o, v) { + tooltip[($.isFunction(v) ? '' : 'un') + 'bind']('tooltip'+o, v); + }, + + // Properties which require event reassignment + '^(show|hide|position).(event|target|fixed|inactive|leave|distance|viewport|adjust)': function() { + var posOptions = options.position; + + // Set tracking flag + tooltip.attr('tracking', posOptions.target === 'mouse' && posOptions.adjust.mouse); + + // Reassign events + unassignEvents(); assignEvents(); + } + }; + + $.extend(self, { + /* + * Psuedo-private API methods + */ + _triggerEvent: function(type, args, event) + { + var callback = $.Event('tooltip'+type); + callback.originalEvent = (event ? $.extend({}, event) : NULL) || cache.event || NULL; + tooltip.trigger(callback, [self].concat(args || [])); + + return !callback.isDefaultPrevented(); + }, + + /* + * Public API methods + */ + render: function(show) + { + if(self.rendered) { return self; } // If tooltip has already been rendered, exit + + var text = options.content.text, + title = options.content.title, + posOptions = options.position; + + // Add ARIA attributes to target + $.attr(target[0], 'aria-describedby', tooltipID); + + // Create tooltip element + tooltip = elements.tooltip = $('
', { + 'id': tooltipID, + 'class': [ NAMESPACE, defaultClass, options.style.classes, NAMESPACE + '-pos-' + options.position.my.abbrev() ].join(' '), + 'width': options.style.width || '', + 'height': options.style.height || '', + 'tracking': posOptions.target === 'mouse' && posOptions.adjust.mouse, + + /* ARIA specific attributes */ + 'role': 'alert', + 'aria-live': 'polite', + 'aria-atomic': FALSE, + 'aria-describedby': tooltipID + '-content', + 'aria-hidden': TRUE + }) + .toggleClass(disabledClass, cache.disabled) + .data('qtip', self) + .appendTo(options.position.container) + .append( + // Create content element + elements.content = $('
', { + 'class': NAMESPACE + '-content', + 'id': tooltipID + '-content', + 'aria-atomic': TRUE + }) + ); + + // Set rendered flag and prevent redundant reposition calls for now + self.rendered = -1; + isPositioning = 1; + + // Create title... + if(title.text) { + createTitle(); + + // Update title only if its not a callback (called in toggle if so) + if(!$.isFunction(title.text)) { updateTitle(title.text, FALSE); } + } + + // Create button + else if(title.button) { createButton(); } + + // Set proper rendered flag and update content if not a callback function (called in toggle) + if(!$.isFunction(text) || text.then) { updateContent(text, FALSE); } + self.rendered = TRUE; + + // Setup widget classes + setWidget(); + + // Assign passed event callbacks (before plugins!) + $.each(options.events, function(name, callback) { + if($.isFunction(callback)) { + tooltip.bind(name === 'toggle' ? 'tooltipshow tooltiphide' : 'tooltip'+name, callback); + } + }); + + // Initialize 'render' plugins + $.each(PLUGINS, function() { + if(this.initialize === 'render') { this(self); } + }); + + // Assign events + assignEvents(); + + /* Queue this part of the render process in our fx queue so we can + * load images before the tooltip renders fully. + * + * See: updateContent method + */ + tooltip.queue('fx', function(next) { + // tooltiprender event + self._triggerEvent('render'); + + // Reset flags + isPositioning = 0; + + // Show tooltip if needed + if(options.show.ready || show) { + self.toggle(TRUE, cache.event, FALSE); + } + + next(); // Move on to next method in queue + }); + + return self; + }, + + get: function(notation) + { + var result, o; + + switch(notation.toLowerCase()) + { + case 'dimensions': + result = { + height: tooltip.outerHeight(FALSE), + width: tooltip.outerWidth(FALSE) + }; + break; + + case 'offset': + result = PLUGINS.offset(tooltip, options.position.container); + break; + + default: + o = convertNotation(notation.toLowerCase()); + result = o[0][ o[1] ]; + result = result.precedance ? result.string() : result; + break; + } + + return result; + }, + + set: function(option, value) + { + var rmove = /^position\.(my|at|adjust|target|container)|style|content|show\.ready/i, + rdraw = /^content\.(title|attr)|style/i, + reposition = FALSE, + checks = self.checks, + name; + + function callback(notation, args) { + var category, rule, match; + + for(category in checks) { + for(rule in checks[category]) { + if(match = (new RegExp(rule, 'i')).exec(notation)) { + args.push(match); + checks[category][rule].apply(self, args); + } + } + } + } + + // Convert singular option/value pair into object form + if('string' === typeof option) { + name = option; option = {}; option[name] = value; + } + else { option = $.extend(TRUE, {}, option); } + + // Set all of the defined options to their new values + $.each(option, function(notation, value) { + var obj = convertNotation( notation.toLowerCase() ), previous; + + // Set new obj value + previous = obj[0][ obj[1] ]; + obj[0][ obj[1] ] = 'object' === typeof value && value.nodeType ? $(value) : value; + + // Set the new params for the callback + option[notation] = [obj[0], obj[1], value, previous]; + + // Also check if we need to reposition + reposition = rmove.test(notation) || reposition; + }); + + // Re-sanitize options + sanitizeOptions(options); + + /* + * Execute any valid callbacks for the set options + * Also set isPositioning/isDrawing so we don't get loads of redundant repositioning calls. + */ + isPositioning = 1; $.each(option, callback); isPositioning = 0; + + // Update position if needed + if(self.rendered && tooltip[0].offsetWidth > 0 && reposition) { + self.reposition( options.position.target === 'mouse' ? NULL : cache.event ); + } + + return self; + }, + + toggle: function(state, event) + { + // Try to prevent flickering when tooltip overlaps show element + if(event) { + if((/over|enter/).test(event.type) && (/out|leave/).test(cache.event.type) && + options.show.target.add(event.target).length === options.show.target.length && + tooltip.has(event.relatedTarget).length) { + return self; + } + + // Cache event + cache.event = $.extend({}, event); + } + + // Render the tooltip if showing and it isn't already + if(!self.rendered) { return state ? self.render(1) : self; } + + var type = state ? 'show' : 'hide', + opts = options[type], + otherOpts = options[ !state ? 'show' : 'hide' ], + posOptions = options.position, + contentOptions = options.content, + visible = tooltip[0].offsetWidth > 0, + animate = state || opts.target.length === 1, + sameTarget = !event || opts.target.length < 2 || cache.target[0] === event.target, + showEvent, delay; + + // Detect state if valid one isn't provided + if((typeof state).search('boolean|number')) { state = !visible; } + + // Return if element is already in correct state + if(!tooltip.is(':animated') && visible === state && sameTarget) { return self; } + + // tooltipshow/tooltiphide events + if(!self._triggerEvent(type, [90])) { return self; } + + // Set ARIA hidden status attribute + $.attr(tooltip[0], 'aria-hidden', !!!state); + + // Execute state specific properties + if(state) { + // Store show origin coordinates + cache.origin = $.extend({}, MOUSE); + + // Focus the tooltip + self.focus(event); + + // Update tooltip content & title if it's a dynamic function + if($.isFunction(contentOptions.text)) { updateContent(contentOptions.text, FALSE); } + if($.isFunction(contentOptions.title.text)) { updateTitle(contentOptions.title.text, FALSE); } + + // Cache mousemove events for positioning purposes (if not already tracking) + if(!trackingBound && posOptions.target === 'mouse' && posOptions.adjust.mouse) { + $(document).bind('mousemove.qtip', storeMouse); + trackingBound = TRUE; + } + + // Update the tooltip position + self.reposition(event, arguments[2]); + + // Hide other tooltips if tooltip is solo + if(!!opts.solo) { + $(selector, opts.solo).not(tooltip).qtip('hide', $.Event('tooltipsolo')); + } + } + else { + // Clear show timer if we're hiding + clearTimeout(self.timers.show); + + // Remove cached origin on hide + delete cache.origin; + + // Remove mouse tracking event if not needed (all tracking qTips are hidden) + if(trackingBound && !$(selector+'[tracking="true"]:visible', opts.solo).not(tooltip).length) { + $(document).unbind('mousemove.qtip'); + trackingBound = FALSE; + } + + // Blur the tooltip + self.blur(event); + } + + // Define post-animation, state specific properties + function after() { + if(state) { + // Prevent antialias from disappearing in IE by removing filter + if($.browser.msie) { tooltip[0].style.removeAttribute('filter'); } + + // Remove overflow setting to prevent tip bugs + tooltip.css('overflow', ''); + + // Autofocus elements if enabled + if('string' === typeof opts.autofocus) { + $(opts.autofocus, tooltip).focus(); + } + + // If set, hide tooltip when inactive for delay period + opts.target.trigger('qtip-'+id+'-inactive'); + } + else { + // Reset CSS states + tooltip.css({ + display: '', + visibility: '', + opacity: '', + left: '', + top: '' + }); + } + + // tooltipvisible/tooltiphidden events + self._triggerEvent(state ? 'visible' : 'hidden'); + } + + // If no effect type is supplied, use a simple toggle + if(opts.effect === FALSE || animate === FALSE) { + tooltip[ type ](); + after.call(tooltip); + } + + // Use custom function if provided + else if($.isFunction(opts.effect)) { + tooltip.stop(1, 1); + opts.effect.call(tooltip, self); + tooltip.queue('fx', function(n){ after(); n(); }); + } + + // Use basic fade function by default + else { tooltip.fadeTo(90, state ? 1 : 0, after); } + + // If inactive hide method is set, active it + if(state) { opts.target.trigger('qtip-'+id+'-inactive'); } + + return self; + }, + + show: function(event){ return self.toggle(TRUE, event); }, + + hide: function(event){ return self.toggle(FALSE, event); }, + + focus: function(event) + { + if(!self.rendered) { return self; } + + var qtips = $(selector), + curIndex = parseInt(tooltip[0].style.zIndex, 10), + newIndex = QTIP.zindex + qtips.length, + cachedEvent = $.extend({}, event), + focusedElem; + + // Only update the z-index if it has changed and tooltip is not already focused + if(!tooltip.hasClass(focusClass)) + { + // tooltipfocus event + if(self._triggerEvent('focus', [newIndex], cachedEvent)) { + // Only update z-index's if they've changed + if(curIndex !== newIndex) { + // Reduce our z-index's and keep them properly ordered + qtips.each(function() { + if(this.style.zIndex > curIndex) { + this.style.zIndex = this.style.zIndex - 1; + } + }); + + // Fire blur event for focused tooltip + qtips.filter('.' + focusClass).qtip('blur', cachedEvent); + } + + // Set the new z-index + tooltip.addClass(focusClass)[0].style.zIndex = newIndex; + } + } + + return self; + }, + + blur: function(event) { + // Set focused status to FALSE + tooltip.removeClass(focusClass); + + // tooltipblur event + self._triggerEvent('blur', [tooltip.css('zIndex')], event); + + return self; + }, + + reposition: function(event, effect) + { + if(!self.rendered || isPositioning) { return self; } + + // Set positioning flag + isPositioning = 1; + + var target = options.position.target, + posOptions = options.position, + my = posOptions.my, + at = posOptions.at, + adjust = posOptions.adjust, + method = adjust.method.split(' '), + elemWidth = tooltip.outerWidth(FALSE), + elemHeight = tooltip.outerHeight(FALSE), + targetWidth = 0, + targetHeight = 0, + fixed = tooltip.css('position') === 'fixed', + viewport = posOptions.viewport, + position = { left: 0, top: 0 }, + container = posOptions.container, + visible = tooltip[0].offsetWidth > 0, + isScroll = event && event.type === 'scroll', + win = $(window), + adjusted, offset; + + // Check if absolute position was passed + if($.isArray(target) && target.length === 2) { + // Force left top and set position + at = { x: LEFT, y: TOP }; + position = { left: target[0], top: target[1] }; + } + + // Check if mouse was the target + else if(target === 'mouse' && ((event && event.pageX) || cache.event.pageX)) { + // Force left top to allow flipping + at = { x: LEFT, y: TOP }; + + // Use cached event if one isn't available for positioning + event = MOUSE && MOUSE.pageX && (adjust.mouse || !event || !event.pageX) ? { pageX: MOUSE.pageX, pageY: MOUSE.pageY } : + (event && (event.type === 'resize' || event.type === 'scroll') ? cache.event : + event && event.pageX && event.type === 'mousemove' ? event : + !adjust.mouse && cache.origin && cache.origin.pageX && options.show.distance ? cache.origin : + event) || event || cache.event || MOUSE || {}; + + // Use event coordinates for position + position = { top: event.pageY, left: event.pageX }; + + // Scroll events are a pain, some browsers + if(adjust.mouse && isScroll) { + position.left -= MOUSE.scrollX - win.scrollLeft(); + position.top -= MOUSE.scrollY - win.scrollTop(); + } + } + + // Target wasn't mouse or absolute... + else { + // Check if event targetting is being used + if(target === 'event' && event && event.target && event.type !== 'scroll' && event.type !== 'resize') { + cache.target = $(event.target); + } + else if(target !== 'event'){ + cache.target = $(target.jquery ? target : elements.target); + } + target = cache.target; + + // Parse the target into a jQuery object and make sure there's an element present + target = $(target).eq(0); + if(target.length === 0) { return self; } + + // Check if window or document is the target + else if(target[0] === document || target[0] === window) { + targetWidth = PLUGINS.iOS ? window.innerWidth : target.width(); + targetHeight = PLUGINS.iOS ? window.innerHeight : target.height(); + + if(target[0] === window) { + position = { + top: (viewport || target).scrollTop(), + left: (viewport || target).scrollLeft() + }; + } + } + + // Use Imagemap/SVG plugins if needed + else if(PLUGINS.imagemap && target.is('area')) { + adjusted = PLUGINS.imagemap(self, target, at, PLUGINS.viewport ? method : FALSE); + } + else if(PLUGINS.svg && target[0].ownerSVGElement) { + adjusted = PLUGINS.svg(self, target, at, PLUGINS.viewport ? method : FALSE); + } + + else { + targetWidth = target.outerWidth(FALSE); + targetHeight = target.outerHeight(FALSE); + + position = PLUGINS.offset(target, container); + } + + // Parse returned plugin values into proper variables + if(adjusted) { + targetWidth = adjusted.width; + targetHeight = adjusted.height; + offset = adjusted.offset; + position = adjusted.position; + } + + // Adjust for position.fixed tooltips (and also iOS scroll bug in v3.2-4.0 & v4.3-4.3.2) + if((PLUGINS.iOS > 3.1 && PLUGINS.iOS < 4.1) || + (PLUGINS.iOS >= 4.3 && PLUGINS.iOS < 4.33) || + (!PLUGINS.iOS && fixed) + ){ + position.left -= win.scrollLeft(); + position.top -= win.scrollTop(); + } + + // Adjust position relative to target + position.left += at.x === RIGHT ? targetWidth : at.x === CENTER ? targetWidth / 2 : 0; + position.top += at.y === BOTTOM ? targetHeight : at.y === CENTER ? targetHeight / 2 : 0; + } + + // Adjust position relative to tooltip + position.left += adjust.x + (my.x === RIGHT ? -elemWidth : my.x === CENTER ? -elemWidth / 2 : 0); + position.top += adjust.y + (my.y === BOTTOM ? -elemHeight : my.y === CENTER ? -elemHeight / 2 : 0); + + // Use viewport adjustment plugin if enabled + if(PLUGINS.viewport) { + position.adjusted = PLUGINS.viewport( + self, position, posOptions, targetWidth, targetHeight, elemWidth, elemHeight + ); + + // Apply offsets supplied by positioning plugin (if used) + if(offset && position.adjusted.left) { position.left += offset.left; } + if(offset && position.adjusted.top) { position.top += offset.top; } + } + + // Viewport adjustment is disabled, set values to zero + else { position.adjusted = { left: 0, top: 0 }; } + + // tooltipmove event + if(!self._triggerEvent('move', [position, viewport.elem || viewport], event)) { return self; } + delete position.adjusted; + + // If effect is disabled, target it mouse, no animation is defined or positioning gives NaN out, set CSS directly + if(effect === FALSE || !visible || isNaN(position.left) || isNaN(position.top) || target === 'mouse' || !$.isFunction(posOptions.effect)) { + tooltip.css(position); + } + + // Use custom function if provided + else if($.isFunction(posOptions.effect)) { + posOptions.effect.call(tooltip, self, $.extend({}, position)); + tooltip.queue(function(next) { + // Reset attributes to avoid cross-browser rendering bugs + $(this).css({ opacity: '', height: '' }); + if($.browser.msie) { this.style.removeAttribute('filter'); } + + next(); + }); + } + + // Set positioning flagwtf + isPositioning = 0; + + return self; + }, + + disable: function(state) + { + if('boolean' !== typeof state) { + state = !(tooltip.hasClass(disabledClass) || cache.disabled); + } + + if(self.rendered) { + tooltip.toggleClass(disabledClass, state); + $.attr(tooltip[0], 'aria-disabled', state); + } + else { + cache.disabled = !!state; + } + + return self; + }, + + enable: function() { return self.disable(FALSE); }, + + destroy: function() + { + var t = target[0], + title = $.attr(t, oldtitle), + elemAPI = target.data('qtip'); + + // Set flag the signify destroy is taking place to plugins + self.destroyed = TRUE; + + // Destroy tooltip and any associated plugins if rendered + if(self.rendered) { + tooltip.stop(1,0).remove(); + + $.each(self.plugins, function() { + if(this.destroy) { this.destroy(); } + }); + } + + // Clear timers and remove bound events + clearTimeout(self.timers.show); + clearTimeout(self.timers.hide); + unassignEvents(); + + // If the API if actually this qTip API... + if(!elemAPI || self === elemAPI) { + // Remove api object + $.removeData(t, 'qtip'); + + // Reset old title attribute if removed + if(options.suppress && title) { + $.attr(t, 'title', title); + target.removeAttr(oldtitle); + } + + // Remove ARIA attributes + target.removeAttr('aria-describedby'); + } + + // Remove qTip events associated with this API + target.unbind('.qtip-'+id); + + // Remove ID from sued id object + delete usedIDs[self.id]; + + return target; + } + }); +} + +// Initialization method +function init(id, opts) +{ + var obj, posOptions, attr, config, title, + + // Setup element references + elem = $(this), + docBody = $(document.body), + + // Use document body instead of document element if needed + newTarget = this === document ? docBody : elem, + + // Grab metadata from element if plugin is present + metadata = (elem.metadata) ? elem.metadata(opts.metadata) : NULL, + + // If metadata type if HTML5, grab 'name' from the object instead, or use the regular data object otherwise + metadata5 = opts.metadata.type === 'html5' && metadata ? metadata[opts.metadata.name] : NULL, + + // Grab data from metadata.name (or data-qtipopts as fallback) using .data() method, + html5 = elem.data(opts.metadata.name || 'qtipopts'); + + // If we don't get an object returned attempt to parse it manualyl without parseJSON + try { html5 = typeof html5 === 'string' ? $.parseJSON(html5) : html5; } catch(e) {} + + // Merge in and sanitize metadata + config = $.extend(TRUE, {}, QTIP.defaults, opts, + typeof html5 === 'object' ? sanitizeOptions(html5) : NULL, + sanitizeOptions(metadata5 || metadata)); + + // Re-grab our positioning options now we've merged our metadata and set id to passed value + posOptions = config.position; + config.id = id; + + // Setup missing content if none is detected + if('boolean' === typeof config.content.text) { + attr = elem.attr(config.content.attr); + + // Grab from supplied attribute if available + if(config.content.attr !== FALSE && attr) { config.content.text = attr; } + + // No valid content was found, abort render + else { return FALSE; } + } + + // Setup target options + if(!posOptions.container.length) { posOptions.container = docBody; } + if(posOptions.target === FALSE) { posOptions.target = newTarget; } + if(config.show.target === FALSE) { config.show.target = newTarget; } + if(config.show.solo === TRUE) { config.show.solo = posOptions.container.closest('body'); } + if(config.hide.target === FALSE) { config.hide.target = newTarget; } + if(config.position.viewport === TRUE) { config.position.viewport = posOptions.container; } + + // Ensure we only use a single container + posOptions.container = posOptions.container.eq(0); + + // Convert position corner values into x and y strings + posOptions.at = new PLUGINS.Corner(posOptions.at); + posOptions.my = new PLUGINS.Corner(posOptions.my); + + // Destroy previous tooltip if overwrite is enabled, or skip element if not + if($.data(this, 'qtip')) { + if(config.overwrite) { + elem.qtip('destroy'); + } + else if(config.overwrite === FALSE) { + return FALSE; + } + } + + // Remove title attribute and store it if present + if(config.suppress && (title = $.attr(this, 'title'))) { + // Final attr call fixes event delegatiom and IE default tooltip showing problem + $(this).removeAttr('title').attr(oldtitle, title).attr('title', ''); + } + + // Initialize the tooltip and add API reference + obj = new QTip(elem, config, id, !!attr); + $.data(this, 'qtip', obj); + + // Catch remove/removeqtip events on target element to destroy redundant tooltip + elem.bind('remove.qtip-'+id+' removeqtip.qtip-'+id, function(){ obj.destroy(); }); + + return obj; +} + +// jQuery $.fn extension method +QTIP = $.fn.qtip = function(options, notation, newValue) +{ + var command = ('' + options).toLowerCase(), // Parse command + returned = NULL, + args = $.makeArray(arguments).slice(1), + event = args[args.length - 1], + opts = this[0] ? $.data(this[0], 'qtip') : NULL; + + // Check for API request + if((!arguments.length && opts) || command === 'api') { + return opts; + } + + // Execute API command if present + else if('string' === typeof options) + { + this.each(function() + { + var api = $.data(this, 'qtip'); + if(!api) { return TRUE; } + + // Cache the event if possible + if(event && event.timeStamp) { api.cache.event = event; } + + // Check for specific API commands + if((command === 'option' || command === 'options') && notation) { + if($.isPlainObject(notation) || newValue !== undefined) { + api.set(notation, newValue); + } + else { + returned = api.get(notation); + return FALSE; + } + } + + // Execute API command + else if(api[command]) { + api[command].apply(api[command], args); + } + }); + + return returned !== NULL ? returned : this; + } + + // No API commands. validate provided options and setup qTips + else if('object' === typeof options || !arguments.length) + { + opts = sanitizeOptions($.extend(TRUE, {}, options)); + + // Bind the qTips + return QTIP.bind.call(this, opts, event); + } +}; + +// $.fn.qtip Bind method +QTIP.bind = function(opts, event) +{ + return this.each(function(i) { + var options, targets, events, namespace, api, id; + + // Find next available ID, or use custom ID if provided + id = $.isArray(opts.id) ? opts.id[i] : opts.id; + id = !id || id === FALSE || id.length < 1 || usedIDs[id] ? QTIP.nextid++ : (usedIDs[id] = id); + + // Setup events namespace + namespace = '.qtip-'+id+'-create'; + + // Initialize the qTip and re-grab newly sanitized options + api = init.call(this, id, opts); + if(api === FALSE) { return TRUE; } + options = api.options; + + // Initialize plugins + $.each(PLUGINS, function() { + if(this.initialize === 'initialize') { this(api); } + }); + + // Determine hide and show targets + targets = { show: options.show.target, hide: options.hide.target }; + events = { + show: $.trim('' + options.show.event).replace(/ /g, namespace+' ') + namespace, + hide: $.trim('' + options.hide.event).replace(/ /g, namespace+' ') + namespace + }; + + /* + * Make sure hoverIntent functions properly by using mouseleave as a hide event if + * mouseenter/mouseout is used for show.event, even if it isn't in the users options. + */ + if(/mouse(over|enter)/i.test(events.show) && !/mouse(out|leave)/i.test(events.hide)) { + events.hide += ' mouseleave' + namespace; + } + + /* + * Also make sure initial mouse targetting works correctly by caching mousemove coords + * on show targets before the tooltip has rendered. + * + * Also set onTarget when triggered to keep mouse tracking working + */ + targets.show.bind('mousemove'+namespace, function(event) { + storeMouse(event); + api.cache.onTarget = TRUE; + }); + + // Define hoverIntent function + function hoverIntent(event) { + function render() { + // Cache mouse coords,render and render the tooltip + api.render(typeof event === 'object' || options.show.ready); + + // Unbind show and hide events + targets.show.add(targets.hide).unbind(namespace); + } + + // Only continue if tooltip isn't disabled + if(api.cache.disabled) { return FALSE; } + + // Cache the event data + api.cache.event = $.extend({}, event); + api.cache.target = event ? $(event.target) : [undefined]; + + // Start the event sequence + if(options.show.delay > 0) { + clearTimeout(api.timers.show); + api.timers.show = setTimeout(render, options.show.delay); + if(events.show !== events.hide) { + targets.hide.bind(events.hide, function() { clearTimeout(api.timers.show); }); + } + } + else { render(); } + } + + // Bind show events to target + targets.show.bind(events.show, hoverIntent); + + // Prerendering is enabled, create tooltip now + if(options.show.ready || options.prerender) { hoverIntent(event); } + }) + .attr('data-hasqtip', TRUE); +}; + +// Setup base plugins +PLUGINS = QTIP.plugins = { + // Corner object parser + Corner: function(corner) { + corner = ('' + corner).replace(/([A-Z])/, ' $1').replace(/middle/gi, CENTER).toLowerCase(); + this.x = (corner.match(/left|right/i) || corner.match(/center/) || ['inherit'])[0].toLowerCase(); + this.y = (corner.match(/top|bottom|center/i) || ['inherit'])[0].toLowerCase(); + + var f = corner.charAt(0); this.precedance = (f === 't' || f === 'b' ? Y : X); + + this.string = function() { return this.precedance === Y ? this.y+this.x : this.x+this.y; }; + this.abbrev = function() { + var x = this.x.substr(0,1), y = this.y.substr(0,1); + return x === y ? x : this.precedance === Y ? y + x : x + y; + }; + + this.invertx = function(center) { this.x = this.x === LEFT ? RIGHT : this.x === RIGHT ? LEFT : center || this.x; }; + this.inverty = function(center) { this.y = this.y === TOP ? BOTTOM : this.y === BOTTOM ? TOP : center || this.y; }; + + this.clone = function() { + return { + x: this.x, y: this.y, precedance: this.precedance, + string: this.string, abbrev: this.abbrev, clone: this.clone, + invertx: this.invertx, inverty: this.inverty + }; + }; + }, + + // Custom (more correct for qTip!) offset calculator + offset: function(elem, container) { + var pos = elem.offset(), + docBody = elem.closest('body'), + quirks = $.browser.msie && document.compatMode !== 'CSS1Compat', + parent = container, scrolled, + coffset, overflow; + + function scroll(e, i) { + pos.left += i * e.scrollLeft(); + pos.top += i * e.scrollTop(); + } + + if(parent) { + // Compensate for non-static containers offset + do { + if(parent.css('position') !== 'static') { + coffset = parent.position(); + + // Account for element positioning, borders and margins + pos.left -= coffset.left + (parseInt(parent.css('borderLeftWidth'), 10) || 0) + (parseInt(parent.css('marginLeft'), 10) || 0); + pos.top -= coffset.top + (parseInt(parent.css('borderTopWidth'), 10) || 0) + (parseInt(parent.css('marginTop'), 10) || 0); + + // If this is the first parent element with an overflow of "scroll" or "auto", store it + if(!scrolled && (overflow = parent.css('overflow')) !== 'hidden' && overflow !== 'visible') { scrolled = parent; } + } + } + while((parent = $(parent[0].offsetParent)).length); + + // Compensate for containers scroll if it also has an offsetParent (or in IE quirks mode) + if(scrolled && scrolled[0] !== docBody[0] || quirks) { + scroll( scrolled || docBody, 1 ); + } + } + + return pos; + }, + + /* + * iOS version detection + */ + iOS: parseFloat( + ('' + (/CPU.*OS ([0-9_]{1,5})|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent) || [0,''])[1]) + .replace('undefined', '3_2').replace('_', '.').replace('_', '') + ) || FALSE, + + /* + * jQuery-specific $.fn overrides + */ + fn: { + /* Allow other plugins to successfully retrieve the title of an element with a qTip applied */ + attr: function(attr, val) { + if(this.length) { + var self = this[0], + title = 'title', + api = $.data(self, 'qtip'); + + if(attr === title && api && 'object' === typeof api && api.options.suppress) { + if(arguments.length < 2) { + return $.attr(self, oldtitle); + } + + // If qTip is rendered and title was originally used as content, update it + if(api && api.options.content.attr === title && api.cache.attr) { + api.set('content.text', val); + } + + // Use the regular attr method to set, then cache the result + return this.attr(oldtitle, val); + } + } + + return $.fn['attr'+replaceSuffix].apply(this, arguments); + }, + + /* Allow clone to correctly retrieve cached title attributes */ + clone: function(keepData) { + var titles = $([]), title = 'title', + + // Clone our element using the real clone method + elems = $.fn['clone'+replaceSuffix].apply(this, arguments); + + // Grab all elements with an oldtitle set, and change it to regular title attribute, if keepData is false + if(!keepData) { + elems.filter('['+oldtitle+']').attr('title', function() { + return $.attr(this, oldtitle); + }) + .removeAttr(oldtitle); + } + + return elems; + } + } +}; + +// Apply the fn overrides above +$.each(PLUGINS.fn, function(name, func) { + if(!func || $.fn[name+replaceSuffix]) { return TRUE; } + + var old = $.fn[name+replaceSuffix] = $.fn[name]; + $.fn[name] = function() { + return func.apply(this, arguments) || old.apply(this, arguments); + }; +}); + +/* Fire off 'removeqtip' handler in $.cleanData if jQuery UI not present (it already does similar). + * This snippet is taken directly from jQuery UI source code found here: + * http://code.jquery.com/ui/jquery-ui-git.js + */ +if(!$.ui) { + $['cleanData'+replaceSuffix] = $.cleanData; + $.cleanData = function( elems ) { + for(var i = 0, elem; (elem = elems[i]) !== undefined; i++) { + try { $( elem ).triggerHandler('removeqtip'); } + catch( e ) {} + } + $['cleanData'+replaceSuffix]( elems ); + }; +} + +// Set global qTip properties +QTIP.version = '2.0.0pre-nightly-214951b9f3'; +QTIP.nextid = 0; +QTIP.inactiveEvents = 'click dblclick mousedown mouseup mousemove mouseleave mouseenter'.split(' '); +QTIP.zindex = 15000; + +// Define configuration defaults +QTIP.defaults = { + prerender: FALSE, + id: FALSE, + overwrite: TRUE, + suppress: TRUE, + content: { + text: TRUE, + attr: 'title', + deferred: FALSE, + title: { + text: FALSE, + button: FALSE + } + }, + position: { + my: 'top left', + at: 'bottom right', + target: FALSE, + container: FALSE, + viewport: FALSE, + adjust: { + x: 0, y: 0, + mouse: TRUE, + resize: TRUE, + method: 'flipinvert flipinvert' + }, + effect: function(api, pos, viewport) { + $(this).animate(pos, { + duration: 200, + queue: FALSE + }); + } + }, + show: { + target: FALSE, + event: 'mouseenter', + effect: TRUE, + delay: 90, + solo: FALSE, + ready: FALSE, + autofocus: FALSE + }, + hide: { + target: FALSE, + event: 'mouseleave', + effect: TRUE, + delay: 0, + fixed: FALSE, + inactive: FALSE, + leave: 'window', + distance: FALSE + }, + style: { + classes: '', + widget: FALSE, + width: FALSE, + height: FALSE, + def: TRUE + }, + events: { + render: NULL, + move: NULL, + show: NULL, + hide: NULL, + toggle: NULL, + visible: NULL, + hidden: NULL, + focus: NULL, + blur: NULL + } +}; + + +PLUGINS.svg = function(api, svg, corner, adjustMethod) +{ + var doc = $(document), + elem = svg[0], + result = { + width: 0, height: 0, + position: { top: 1e10, left: 1e10 } + }, + box, mtx, root, point, tPoint; - if('content' in opts) { - if(opts.content === NULL || 'object' !== typeof opts.content || opts.content.jquery) { - opts.content = { - text: opts.content - }; - } + // Ascend the parentNode chain until we find an element with getBBox() + while(!elem.getBBox) { elem = elem.parentNode; } - content = opts.content.text || FALSE; - if(!$.isFunction(content) && ((!content && !content.attr) || content.length < 1 || ('object' === typeof content && !content.jquery))) { - opts.content.text = FALSE; - } + // Check for a valid bounding box method + if (elem.getBBox && elem.parentNode) { + box = elem.getBBox(); + mtx = elem.getScreenCTM(); + root = elem.farthestViewportElement || elem; - if('title' in opts.content) { - if(opts.content.title === NULL || 'object' !== typeof opts.content.title) { - opts.content.title = { - text: opts.content.title - }; - } + // Return if no method is found + if(!root.createSVGPoint) { return result; } - content = opts.content.title.text || FALSE; - if(!$.isFunction(content) && ((!content && !content.attr) || content.length < 1 || ('object' === typeof content && !content.jquery))) { - opts.content.title.text = FALSE; - } - } - } + // Create our point var + point = root.createSVGPoint(); - if('position' in opts) { - if(opts.position === NULL || 'object' !== typeof opts.position) { - opts.position = { - my: opts.position, - at: opts.position - }; - } - } + // Adjust top and left + point.x = box.x; + point.y = box.y; + tPoint = point.matrixTransform(mtx); + result.position.left = tPoint.x; + result.position.top = tPoint.y; - if('show' in opts) { - if(opts.show === NULL || 'object' !== typeof opts.show) { - if(opts.show.jquery) { - opts.show = { target: opts.show }; - } - else { - opts.show = { event: opts.show }; - } - } - } + console.log(result, point, tPoint); - if('hide' in opts) { - if(opts.hide === NULL || 'object' !== typeof opts.hide) { - if(opts.hide.jquery) { - opts.hide = { target: opts.hide }; - } - else { - opts.hide = { event: opts.hide }; - } - } - } + // Adjust width and height + point.x += box.width; + point.y += box.height; + tPoint = point.matrixTransform(mtx); + result.width = tPoint.x - result.position.left; + result.height = tPoint.y - result.position.top; - if('style' in opts) { - if(opts.style === NULL || 'object' !== typeof opts.style) { - opts.style = { - classes: opts.style - }; - } + // Adjust by scroll offset + result.position.left += doc.scrollLeft(); + result.position.top += doc.scrollTop(); } - // Sanitize plugin options - $.each(PLUGINS, function() { - if(this.sanitize) { this.sanitize(opts); } - }); + return result; +}; - return opts; -} -/* -* Core plugin implementation -*/ -function QTip(target, options, id, attr) +function Ajax(api) { - // Declare this reference var self = this, - docBody = document.body, - tooltipID = uitooltip + '-' + id, - isPositioning = 0, - isDrawing = 0, - tooltip = $(), - namespace = '.qtip-' + id, - elements, cache; - - // Setup class attributes - self.id = id; - self.rendered = FALSE; - self.destroyed = FALSE; - self.elements = elements = { target: target }; - self.timers = { img: {} }; - self.options = options; - self.checks = {}; - self.plugins = {}; - self.cache = cache = { - event: {}, - target: $(), - disabled: FALSE, - attr: attr, - onTarget: FALSE - }; - - /* - * Private core functions - */ - function convertNotation(notation) - { - var i = 0, obj, option = options, + tooltip = api.elements.tooltip, + opts = api.options.content.ajax, + defaults = QTIP.defaults.content.ajax, + namespace = '.qtip-ajax', + rscript = /)<[^<]*)*<\/script>/gi, + first = TRUE, + stop = FALSE, + xhr; - // Split notation into array - levels = notation.split('.'); + api.checks.ajax = { + '^content.ajax': function(obj, name, v) { + // If content.ajax object was reset, set our local var + if(name === 'ajax') { opts = v; } - // Loop through - while( option = option[ levels[i++] ] ) { - if(i < levels.length) { obj = option; } + if(name === 'once') { + self.init(); + } + else if(opts && opts.url) { + self.load(); + } + else { + tooltip.unbind(namespace); + } } + }; - return [obj || options, levels.pop()]; - } + $.extend(self, { + init: function() { + // Make sure ajax options are enabled and bind event + if(opts && opts.url) { + tooltip.unbind(namespace)[ opts.once ? 'one' : 'bind' ]('tooltipshow'+namespace, self.load); + } - function setWidget() { - var on = options.style.widget; + return self; + }, - tooltip.toggleClass(widget, on).toggleClass(defaultClass, options.style.def && !on); - elements.content.toggleClass(widget+'-content', on); + load: function(event) { + if(stop) {stop = FALSE; return; } - if(elements.titlebar){ - elements.titlebar.toggleClass(widget+'-header', on); - } - if(elements.button){ - elements.button.toggleClass(uitooltip+'-icon', !on); - } - } + var hasSelector = opts.url.lastIndexOf(' '), + url = opts.url, + selector, + hideFirst = !opts.loading && first; - function removeTitle(reposition) - { - if(elements.title) { - elements.titlebar.remove(); - elements.titlebar = elements.title = elements.button = NULL; + // If loading option is disabled, prevent the tooltip showing until we've completed the request + if(hideFirst) { try{ event.preventDefault(); } catch(e) {} } - // Reposition if enabled - if(reposition !== FALSE) { self.reposition(); } - } - } + // Make sure default event hasn't been prevented + else if(event && event.isDefaultPrevented()) { return self; } - function createButton() - { - var button = options.content.title.button, - isString = typeof button === 'string', - close = isString ? button : 'Close tooltip'; + // Cancel old request + if(xhr && xhr.abort) { xhr.abort(); } + + // Check if user delcared a content selector like in .load() + if(hasSelector > -1) { + selector = url.substr(hasSelector); + url = url.substr(0, hasSelector); + } - if(elements.button) { elements.button.remove(); } + // Define common after callback for both success/error handlers + function after() { + var complete; - // Use custom button if one was supplied by user, else use default - if(button.jquery) { - elements.button = button; - } - else { - elements.button = $('', { - 'class': 'ui-state-default ui-tooltip-close ' + (options.style.widget ? '' : uitooltip+'-icon'), - 'title': close, - 'aria-label': close - }) - .prepend( - $('', { - 'class': 'ui-icon ui-icon-close', - 'html': '×' - }) - ); - } + // Don't proceed if tooltip is destroyed + if(api.destroyed) { return; } - // Create button and setup attributes - elements.button.appendTo(elements.titlebar) - .attr('role', 'button') - .click(function(event) { - if(!tooltip.hasClass(disabled)) { self.hide(event); } - return FALSE; - }); + // Set first flag to false + first = FALSE; - // Redraw the tooltip when we're done - self.redraw(); - } + // Re-display tip if loading and first time, and reset first flag + if(hideFirst) { stop = TRUE; api.show(event.originalEvent); } - function createTitle() - { - var id = tooltipID+'-title'; - - // Destroy previous title element, if present - if(elements.titlebar) { removeTitle(); } - - // Create title bar and title elements - elements.titlebar = $('
', { - 'class': uitooltip + '-titlebar ' + (options.style.widget ? 'ui-widget-header' : '') - }) - .append( - elements.title = $('
', { - 'id': id, - 'class': uitooltip + '-title', - 'aria-atomic': TRUE - }) - ) - .insertBefore(elements.content) - - // Button-specific events - .delegate('.ui-tooltip-close', 'mousedown keydown mouseup keyup mouseout', function(event) { - $(this).toggleClass('ui-state-active ui-state-focus', event.type.substr(-4) === 'down'); - }) - .delegate('.ui-tooltip-close', 'mouseover mouseout', function(event){ - $(this).toggleClass('ui-state-hover', event.type === 'mouseover'); - }); + // Call users complete method if it was defined + if((complete = defaults.complete || opts.complete) && $.isFunction(complete)) { + complete.apply(opts.context || api, arguments); + } + } - // Create button if enabled - if(options.content.title.button) { createButton(); } + // Define success handler + function successHandler(content, status, jqXHR) { + var success; - // Redraw the tooltip dimensions if it's rendered - else if(self.rendered){ self.redraw(); } - } + // Don't proceed if tooltip is destroyed + if(api.destroyed) { return; } - function updateButton(button) - { - var elem = elements.button, - title = elements.title; + // If URL contains a selector + if(selector && 'string' === typeof content) { + // Create a dummy div to hold the results and grab the selector element + content = $('
') + // inject the contents of the document in, removing the scripts + // to avoid any 'Permission Denied' errors in IE + .append(content.replace(rscript, "")) + + // Locate the specified elements + .find(selector); + } - // Make sure tooltip is rendered and if not, return - if(!self.rendered) { return FALSE; } + // Call the success function if one is defined + if((success = defaults.success || opts.success) && $.isFunction(success)) { + success.call(opts.context || api, content, status, jqXHR); + } - if(!button) { - elem.remove(); - } - else { - if(!title) { - createTitle(); + // Otherwise set the content + else { api.set('content.text', content); } } - createButton(); - } - } - - function updateTitle(content, reposition) - { - var elem = elements.title; - // Make sure tooltip is rendered and if not, return - if(!self.rendered || !content) { return FALSE; } + // Error handler + function errorHandler(xhr, status, error) { + if(api.destroyed || xhr.status === 0) { return; } + api.set('content.text', status + ': ' + error); + } - // Use function to parse content - if($.isFunction(content)) { - content = content.call(target, cache.event, self); - } + // Setup $.ajax option object and process the request + xhr = $.ajax( + $.extend({ + error: defaults.error || errorHandler, + context: api + }, + opts, { url: url, success: successHandler, complete: after }) + ); + }, - // Remove title if callback returns false or null/undefined (but not '') - if(content === FALSE || (!content && content !== '')) { return removeTitle(FALSE); } + destroy: function() { + // Cancel ajax request if possible + if(xhr && xhr.abort) { xhr.abort(); } - // Append new content if its a DOM array and show it if hidden - else if(content.jquery && content.length > 0) { - elem.empty().append(content.css({ display: 'block' })); + // Set api.destroyed flag + api.destroyed = TRUE; } + }); - // Content is a regular string, insert the new content - else { elem.html(content); } + self.init(); +} - // Redraw and reposition - self.redraw(); - if(reposition !== FALSE && self.rendered && tooltip[0].offsetWidth > 0) { - self.reposition(cache.event); - } - } - function updateContent(content, reposition) - { - var elem = elements.content; +PLUGINS.ajax = function(api) +{ + var self = api.plugins.ajax; + + return 'object' === typeof self ? self : (api.plugins.ajax = new Ajax(api)); +}; - // Make sure tooltip is rendered and content is defined. If not return - if(!self.rendered || !content) { return FALSE; } +PLUGINS.ajax.initialize = 'render'; - // Use function to parse content - if($.isFunction(content)) { - content = content.call(target, cache.event, self) || ''; - } +// Setup plugin sanitization +PLUGINS.ajax.sanitize = function(options) +{ + var content = options.content, opts; + if(content && 'ajax' in content) { + opts = content.ajax; + if(typeof opts !== 'object') { opts = options.content.ajax = { url: opts }; } + if('boolean' !== typeof opts.once && opts.once) { opts.once = !!opts.once; } + } +}; - // Append new content if its a DOM array and show it if hidden - if(content.jquery && content.length > 0) { - elem.empty().append(content.css({ display: 'block' })); +// Extend original api defaults +$.extend(TRUE, QTIP.defaults, { + content: { + ajax: { + loading: TRUE, + once: TRUE } + } +}); - // Content is a regular string, insert the new content - else { elem.html(content); } - // Image detection - function detectImages(next) { - var images, srcs = {}; +// Tip coordinates calculator +function calculateTip(corner, width, height) +{ + var width2 = Math.ceil(width / 2), height2 = Math.ceil(height / 2), - function imageLoad(image) { - // Clear src from object and any timers and events associated with the image - if(image) { - delete srcs[image.src]; - clearTimeout(self.timers.img[image.src]); - $(image).unbind(namespace); - } + // Define tip coordinates in terms of height and width values + tips = { + bottomright: [[0,0], [width,height], [width,0]], + bottomleft: [[0,0], [width,0], [0,height]], + topright: [[0,height], [width,0], [width,height]], + topleft: [[0,0], [0,height], [width,height]], + topcenter: [[0,height], [width2,0], [width,height]], + bottomcenter: [[0,0], [width,0], [width2,height]], + rightcenter: [[0,0], [width,height2], [0,height]], + leftcenter: [[width,0], [width,height], [0,height2]] + }; - // If queue is empty after image removal, update tooltip and continue the queue - if($.isEmptyObject(srcs)) { - self.redraw(); - if(reposition !== FALSE) { - self.reposition(cache.event); - } + // Set common side shapes + tips.lefttop = tips.bottomright; tips.righttop = tips.bottomleft; + tips.leftbottom = tips.topright; tips.rightbottom = tips.topleft; - next(); - } - } - - // Find all content images without dimensions, and if no images were found, continue - if((images = elem.find('img[src]:not([height]):not([width])')).length === 0) { return imageLoad(); } + return tips[ corner.string() ]; +} - // Apply timer to each image to poll for dimensions - images.each(function(i, elem) { - // Skip if the src is already present - if(srcs[elem.src] !== undefined) { return; } - // Keep track of how many times we poll for image dimensions. - // If it doesn't return in a reasonable amount of time, it's better - // to display the tooltip, rather than hold up the queue. - var iterations = 0, maxIterations = 3; +function Tip(qTip, command) +{ + var self = this, + opts = qTip.options.style.tip, + elems = qTip.elements, + tooltip = elems.tooltip, + cache = { top: 0, left: 0 }, + size = { + width: opts.width, + height: opts.height + }, + color = { }, + border = opts.border || 0, + namespace = '.qtip-tip', + hasCanvas = !!($('')[0] || {}).getContext, + tiphtml; - (function timer(){ - // When the dimensions are found, remove the image from the queue - if(elem.height || elem.width || (iterations > maxIterations)) { return imageLoad(elem); } + self.corner = NULL; + self.mimic = NULL; + self.border = border; + self.offset = opts.offset; + self.size = size; - // Increase iterations and restart timer - iterations += 1; - self.timers.img[elem.src] = setTimeout(timer, 700); - }()); + // Add new option checks for the plugin + qTip.checks.tip = { + '^position.my|style.tip.(corner|mimic|border)$': function() { + // Make sure a tip can be drawn + if(!self.init()) { + self.destroy(); + } - // Also apply regular load/error event handlers - $(elem).bind('error'+namespace+' load'+namespace, function(){ imageLoad(this); }); + // Reposition the tooltip + qTip.reposition(); + }, + '^style.tip.(height|width)$': function() { + // Re-set dimensions and redraw the tip + size = { + width: opts.width, + height: opts.height + }; + self.create(); + self.update(); - // Store the src and element in our object - srcs[elem.src] = elem; - }); + // Reposition the tooltip + qTip.reposition(); + }, + '^content.title.text|style.(classes|widget)$': function() { + if(elems.tip && elems.tip.length) { + self.update(); + } } + }; - /* - * If we're still rendering... insert into 'fx' queue our image dimension - * checker which will halt the showing of the tooltip until image dimensions - * can be detected properly. - */ - if(self.rendered < 0) { tooltip.queue('fx', detectImages); } + function whileVisible(callback) { + var visible = tooltip.is(':visible'); + tooltip.show(); callback(); tooltip.toggle(visible); + } - // We're fully rendered, so reset isDrawing flag and proceed without queue delay - else { isDrawing = 0; detectImages($.noop); } + function swapDimensions() { + size.width = opts.height; + size.height = opts.width; + } - return self; + function resetDimensions() { + size.width = opts.width; + size.height = opts.height; } - function assignEvents() - { - var posOptions = options.position, - targets = { - show: options.show.target, - hide: options.hide.target, - viewport: $(posOptions.viewport), - document: $(document), - body: $(document.body), - window: $(window) - }, - events = { - show: $.trim('' + options.show.event).split(' '), - hide: $.trim('' + options.hide.event).split(' ') - }, - IE6 = $.browser.msie && parseInt($.browser.version, 10) === 6; - - // Define show event method - function showMethod(event) - { - if(tooltip.hasClass(disabled)) { return FALSE; } + function reposition(event, api, pos, viewport) { + if(!elems.tip) { return; } - // Clear hide timers - clearTimeout(self.timers.show); - clearTimeout(self.timers.hide); + var newCorner = self.corner.clone(), + adjust = pos.adjusted, + method = qTip.options.position.adjust.method.split(' '), + horizontal = method[0], + vertical = method[1] || method[0], + shift = { left: FALSE, top: FALSE, x: 0, y: 0 }, + offset, css = {}, props; - // Start show timer - var callback = function(){ self.toggle(TRUE, event); }; - if(options.show.delay > 0) { - self.timers.show = setTimeout(callback, options.show.delay); + // If our tip position isn't fixed e.g. doesn't adjust with viewport... + if(self.corner.fixed !== TRUE) { + // Horizontal - Shift or flip method + if(horizontal === SHIFT && newCorner.precedance === X && adjust.left && newCorner.y !== CENTER) { + newCorner.precedance = newCorner.precedance === X ? Y : X; } - else{ callback(); } - } - - // Define hide method - function hideMethod(event) - { - if(tooltip.hasClass(disabled) || isPositioning || isDrawing) { return FALSE; } - - // Check if new target was actually the tooltip element - var relatedTarget = $(event.relatedTarget || event.target), - ontoTooltip = relatedTarget.closest(selector)[0] === tooltip[0], - ontoTarget = relatedTarget[0] === targets.show[0]; - - // Clear timers and stop animation queue - clearTimeout(self.timers.show); - clearTimeout(self.timers.hide); - - // Prevent hiding if tooltip is fixed and event target is the tooltip. Or if mouse positioning is enabled and cursor momentarily overlaps - if((posOptions.target === 'mouse' && ontoTooltip) || (options.hide.fixed && ((/mouse(out|leave|move)/).test(event.type) && (ontoTooltip || ontoTarget)))) { - try { event.preventDefault(); event.stopImmediatePropagation(); } catch(e) {} return; + else if(horizontal !== SHIFT && adjust.left){ + newCorner.x = newCorner.x === CENTER ? (adjust.left > 0 ? LEFT : RIGHT) : (newCorner.x === LEFT ? RIGHT : LEFT); } - // If tooltip has displayed, start hide timer - if(options.hide.delay > 0) { - self.timers.hide = setTimeout(function(){ self.hide(event); }, options.hide.delay); + // Vertical - Shift or flip method + if(vertical === SHIFT && newCorner.precedance === Y && adjust.top && newCorner.x !== CENTER) { + newCorner.precedance = newCorner.precedance === Y ? X : Y; + } + else if(vertical !== SHIFT && adjust.top) { + newCorner.y = newCorner.y === CENTER ? (adjust.top > 0 ? TOP : BOTTOM) : (newCorner.y === TOP ? BOTTOM : TOP); } - else{ self.hide(event); } - } - - // Define inactive method - function inactiveMethod(event) - { - if(tooltip.hasClass(disabled)) { return FALSE; } - - // Clear timer - clearTimeout(self.timers.inactive); - self.timers.inactive = setTimeout(function(){ self.hide(event); }, options.hide.inactive); - } - function repositionMethod(event) { - if(self.rendered && tooltip[0].offsetWidth > 0) { self.reposition(event); } + // Update and redraw the tip if needed (check cached details of last drawn tip) + if(newCorner.string() !== cache.corner.string() && (cache.top !== adjust.top || cache.left !== adjust.left)) { + self.update(newCorner, FALSE); + } } - // On mouseenter/mouseleave... - tooltip.bind('mouseenter'+namespace+' mouseleave'+namespace, function(event) { - var state = event.type === 'mouseenter'; - - // Focus the tooltip on mouseenter (z-index stacking) - if(state) { self.focus(event); } - - // Add hover class - tooltip.toggleClass(hoverClass, state); - }); - - // Enable hide.fixed - if(options.hide.fixed) { - // Add tooltip as a hide target - targets.hide = targets.hide.add(tooltip); + // Setup tip offset properties + offset = self.position(newCorner, adjust); + offset[ newCorner.x ] += parseWidth(newCorner, newCorner.x); + offset[ newCorner.y ] += parseWidth(newCorner, newCorner.y); - // Clear hide timer on tooltip hover to prevent it from closing - tooltip.bind('mouseover'+namespace, function() { - if(!tooltip.hasClass(disabled)) { clearTimeout(self.timers.hide); } - }); - } + // Readjust offset object to make it left/top + if(offset.right !== undefined) { offset.left = -offset.right; } + if(offset.bottom !== undefined) { offset.top = -offset.bottom; } + offset.user = Math.max(0, opts.offset); - // If using mouseout/mouseleave as a hide event... - if(/mouse(out|leave)/i.test(options.hide.event)) { - // Hide tooltips when leaving current window/frame (but not select/option elements) - if(options.hide.leave === 'window') { - targets.window.bind('mouseout'+namespace+' blur'+namespace, function(event) { - if(/select|option/.test(event.target) && !event.relatedTarget) { self.hide(event); } - }); + // Viewport "shift" specific adjustments + if(shift.left = (horizontal === SHIFT && !!adjust.left)) { + if(newCorner.x === CENTER) { + css['margin-left'] = shift.x = offset['margin-left'] - adjust.left; } - } - - /* - * Make sure hoverIntent functions properly by using mouseleave to clear show timer if - * mouseenter/mouseout is used for show.event, even if it isn't in the users options. - */ - else if(/mouse(over|enter)/i.test(options.show.event)) { - targets.hide.bind('mouseleave'+namespace, function(event) { - clearTimeout(self.timers.show); - }); - } + else { + props = offset.right !== undefined ? + [ adjust.left, -offset.left ] : [ -adjust.left, offset.left ]; - // Hide tooltip on document mousedown if unfocus events are enabled - if(('' + options.hide.event).indexOf('unfocus') > -1) { - posOptions.container.closest('html').bind('mousedown'+namespace, function(event) { - var elem = $(event.target), - enabled = self.rendered && !tooltip.hasClass(disabled) && tooltip[0].offsetWidth > 0, - isAncestor = elem.parents(selector).filter(tooltip[0]).length > 0; - - if(elem[0] !== target[0] && elem[0] !== tooltip[0] && !isAncestor && - !target.has(elem[0]).length && !elem.attr('disabled') - ) { - self.hide(event); + if( (shift.x = Math.max(props[0], props[1])) > props[0] ) { + pos.left -= adjust.left; + shift.left = FALSE; } - }); + + css[ offset.right !== undefined ? RIGHT : LEFT ] = shift.x; + } } + if(shift.top = (vertical === SHIFT && !!adjust.top)) { + if(newCorner.y === CENTER) { + css['margin-top'] = shift.y = offset['margin-top'] - adjust.top; + } + else { + props = offset.bottom !== undefined ? + [ adjust.top, -offset.top ] : [ -adjust.top, offset.top ]; - // Check if the tooltip hides when inactive - if('number' === typeof options.hide.inactive) { - // Bind inactive method to target as a custom event - targets.show.bind('qtip-'+id+'-inactive', inactiveMethod); + if( (shift.y = Math.max(props[0], props[1])) > props[0] ) { + pos.top -= adjust.top; + shift.top = FALSE; + } - // Define events which reset the 'inactive' event handler - $.each(QTIP.inactiveEvents, function(index, type){ - targets.hide.add(elements.tooltip).bind(type+namespace+'-inactive', inactiveMethod); - }); + css[ offset.bottom !== undefined ? BOTTOM : TOP ] = shift.y; + } } - // Apply hide events - $.each(events.hide, function(index, type) { - var showIndex = $.inArray(type, events.show), - targetHide = $(targets.hide); - - // Both events and targets are identical, apply events using a toggle - if((showIndex > -1 && targetHide.add(targets.show).length === targetHide.length) || type === 'unfocus') - { - targets.show.bind(type+namespace, function(event) { - if(tooltip[0].offsetWidth > 0) { hideMethod(event); } - else { showMethod(event); } - }); + /* + * If the tip is adjusted in both dimensions, or in a + * direction that would cause it to be anywhere but the + * outer border, hide it! + */ + elems.tip.css(css).toggle( + !((shift.x && shift.y) || (newCorner.x === CENTER && shift.y) || (newCorner.y === CENTER && shift.x)) + ); - // Don't bind the event again - delete events.show[ showIndex ]; - } + // Adjust position to accomodate tip dimensions + pos.left -= offset.left.charAt ? offset.user : horizontal !== SHIFT || shift.top || !shift.left && !shift.top ? offset.left : 0; + pos.top -= offset.top.charAt ? offset.user : vertical !== SHIFT || shift.left || !shift.left && !shift.top ? offset.top : 0; - // Events are not identical, bind normally - else { targets.hide.bind(type+namespace, hideMethod); } - }); + // Cache details + cache.left = adjust.left; cache.top = adjust.top; + cache.corner = newCorner.clone(); + } - // Apply show events - $.each(events.show, function(index, type) { - targets.show.bind(type+namespace, showMethod); - }); + function parseCorner() { + var corner = opts.corner, + posOptions = qTip.options.position, + at = posOptions.at, + my = posOptions.my.string ? posOptions.my.string() : posOptions.my; - // Check if the tooltip hides when mouse is moved a certain distance - if('number' === typeof options.hide.distance) { - // Bind mousemove to target to detect distance difference - targets.show.add(tooltip).bind('mousemove'+namespace, function(event) { - var origin = cache.origin || {}, - limit = options.hide.distance, - abs = Math.abs; - - // Check if the movement has gone beyond the limit, and hide it if so - if(abs(event.pageX - origin.pageX) >= limit || abs(event.pageY - origin.pageY) >= limit) { - self.hide(event); - } - }); + // Detect corner and mimic properties + if(corner === FALSE || (my === FALSE && at === FALSE)) { + return FALSE; } - - // Mouse positioning events - if(posOptions.target === 'mouse') { - // Cache mousemove coords on show targets - targets.show.bind('mousemove'+namespace, function(event) { - MOUSE = { pageX: event.pageX, pageY: event.pageY, type: 'mousemove' }; - }); - - // If mouse adjustment is on... - if(posOptions.adjust.mouse) { - // Apply a mouseleave event so we don't get problems with overlapping - if(options.hide.event) { - // Hide when we leave the tooltip and not onto the show target - tooltip.bind('mouseleave'+namespace, function(event) { - if((event.relatedTarget || event.target) !== targets.show[0]) { self.hide(event); } - }); - - // Track if we're on the target or not - elements.target.bind('mouseenter'+namespace+' mouseleave'+namespace, function(event) { - cache.onTarget = event.type === 'mouseenter'; - }); - } - - // Update tooltip position on mousemove - targets.document.bind('mousemove'+namespace, function(event) { - // Update the tooltip position only if the tooltip is visible and adjustment is enabled - if(self.rendered && cache.onTarget && !tooltip.hasClass(disabled) && tooltip[0].offsetWidth > 0) { - self.reposition(event || MOUSE); - } - }); + else { + if(corner === TRUE) { + self.corner = new PLUGINS.Corner(my); + } + else if(!corner.string) { + self.corner = new PLUGINS.Corner(corner); + self.corner.fixed = TRUE; } } - // Adjust positions of the tooltip on window resize if enabled - if(posOptions.adjust.resize || targets.viewport.length) { - ($.event.special.resize ? targets.viewport : targets.window).bind('resize'+namespace, repositionMethod); - } + // Cache it + cache.corner = new PLUGINS.Corner( self.corner.string() ); - // Adjust tooltip position on scroll if screen adjustment is enabled - if(targets.viewport.length || (IE6 && tooltip.css('position') === 'fixed')) { - targets.viewport.bind('scroll'+namespace, repositionMethod); - } + return self.corner.string() !== 'centercenter'; } - function unassignEvents() - { - var targets = [ - options.show.target[0], - options.hide.target[0], - self.rendered && elements.tooltip[0], - options.position.container[0], - options.position.viewport[0], - window, - document - ]; - - // Check if tooltip is rendered - if(self.rendered) { - $([]).pushStack( $.grep(targets, function(i){ return typeof i === 'object'; }) ).unbind(namespace); - } + /* border width calculator */ + function parseWidth(corner, side, use) { + side = !side ? corner[corner.precedance] : side; + + var isTitleTop = elems.titlebar && corner.y === TOP, + elem = isTitleTop ? elems.titlebar : tooltip, + borderSide = 'border-' + side + '-width', + css = function(elem) { return parseInt(elem.css(borderSide), 10); }, + val; - // Tooltip isn't yet rendered, remove render event - else { options.show.target.unbind(namespace+'-create'); } + // Grab the border-width value (make tooltip visible first) + whileVisible(function() { + val = (use ? css(use) : (css(elems.content) || css(elem) || css(tooltip))) || 0; + }); + return val; } - // Setup builtin .set() option checks - self.checks.builtin = { - // Core checks - '^id$': function(obj, o, v) { - var id = v === TRUE ? QTIP.nextid : v, - tooltipID = uitooltip + '-' + id; - - if(id !== FALSE && id.length > 0 && !$('#'+tooltipID).length) { - tooltip[0].id = tooltipID; - elements.content[0].id = tooltipID + '-content'; - elements.title[0].id = tooltipID + '-title'; - } - }, - - // Content checks - '^content.text$': function(obj, o, v){ updateContent(v); }, - '^content.title.text$': function(obj, o, v) { - // Remove title if content is null - if(!v) { return removeTitle(); } - - // If title isn't already created, create it now and update - if(!elements.title && v) { createTitle(); } - updateTitle(v); - }, - '^content.title.button$': function(obj, o, v){ updateButton(v); }, - - // Position checks - '^position.(my|at)$': function(obj, o, v){ - // Parse new corner value into Corner objecct - if('string' === typeof v) { - obj[o] = new PLUGINS.Corner(v); - } - }, - '^position.container$': function(obj, o, v){ - if(self.rendered) { tooltip.appendTo(v); } - }, - - // Show checks - '^show.ready$': function() { - if(!self.rendered) { self.render(1); } - else { self.toggle(TRUE); } - }, - - // Style checks - '^style.classes$': function(obj, o, v) { - tooltip.attr('class', uitooltip + ' qtip ui-helper-reset ' + v); - }, - '^style.widget|content.title': setWidget, + function parseRadius(corner) { + var isTitleTop = elems.titlebar && corner.y === TOP, + elem = isTitleTop ? elems.titlebar : elems.content, + moz = $.browser.mozilla, + prefix = moz ? '-moz-' : $.browser.webkit ? '-webkit-' : '', + nonStandard = 'border-radius-' + corner.y + corner.x, + standard = 'border-' + corner.y + '-' + corner.x + '-radius', + css = function(c) { return parseInt(elem.css(c), 10) || parseInt(tooltip.css(c), 10); }, + val; - // Events check - '^events.(render|show|move|hide|focus|blur)$': function(obj, o, v) { - tooltip[($.isFunction(v) ? '' : 'un') + 'bind']('tooltip'+o, v); - }, + whileVisible(function() { + val = css(standard) || css(prefix + standard) || css(prefix + nonStandard) || css(nonStandard) || 0; + }); + return val; + } - // Properties which require event reassignment - '^(show|hide|position).(event|target|fixed|inactive|leave|distance|viewport|adjust)': function() { - var posOptions = options.position; + function parseColours(actual) { + var i, fill, border, + tip = elems.tip.css('cssText', ''), + corner = actual || self.corner, + invalid = /rgba?\(0, 0, 0(, 0)?\)|transparent|#123456/i, + borderSide = 'border-' + corner[ corner.precedance ] + '-color', + bgColor = 'background-color', + transparent = 'transparent', + important = ' !important', - // Set tracking flag - tooltip.attr('tracking', posOptions.target === 'mouse' && posOptions.adjust.mouse); + titlebar = elems.titlebar, + useTitle = titlebar && (corner.y === TOP || (corner.y === CENTER && tip.position().top + (size.height / 2) + opts.offset < titlebar.outerHeight(TRUE))), + colorElem = useTitle ? titlebar : elems.content; - // Reassign events - unassignEvents(); assignEvents(); + function css(elem, prop, compare) { + var val = elem.css(prop) || transparent; + if(compare && val === elem.css(compare)) { return FALSE; } + else { return invalid.test(val) ? FALSE : val; } } - }; - - /* - * Public API methods - */ - $.extend(self, { - render: function(show) - { - if(self.rendered) { return self; } // If tooltip has already been rendered, exit - - var text = options.content.text, - title = options.content.title.text, - posOptions = options.position, - callback = $.Event('tooltiprender'); - - // Add ARIA attributes to target - $.attr(target[0], 'aria-describedby', tooltipID); - - // Create tooltip element - tooltip = elements.tooltip = $('
', { - 'id': tooltipID, - 'class': uitooltip + ' qtip ui-helper-reset ' + defaultClass + ' ' + options.style.classes + ' '+ uitooltip + '-pos-' + options.position.my.abbrev(), - 'width': options.style.width || '', - 'height': options.style.height || '', - 'tracking': posOptions.target === 'mouse' && posOptions.adjust.mouse, - - /* ARIA specific attributes */ - 'role': 'alert', - 'aria-live': 'polite', - 'aria-atomic': FALSE, - 'aria-describedby': tooltipID + '-content', - 'aria-hidden': TRUE - }) - .toggleClass(disabled, cache.disabled) - .data('qtip', self) - .appendTo(options.position.container) - .append( - // Create content element - elements.content = $('
', { - 'class': uitooltip + '-content', - 'id': tooltipID + '-content', - 'aria-atomic': TRUE - }) - ); - - // Set rendered flag and prevent redundant redraw/reposition calls for now - self.rendered = -1; - isDrawing = 1; isPositioning = 1; - - // Create title... - if(title) { - createTitle(); - - // Update title only if its not a callback (called in toggle if so) - if(!$.isFunction(title)) { updateTitle(title, FALSE); } - } - // Set proper rendered flag and update content if not a callback function (called in toggle) - if(!$.isFunction(text)) { updateContent(text, FALSE); } - self.rendered = TRUE; + // Ensure tooltip is visible then... + whileVisible(function() { + // Attempt to detect the background colour from various elements, left-to-right precedance + color.fill = css(tip, bgColor) || css(colorElem, bgColor) || css(elems.content, bgColor) || + css(tooltip, bgColor) || tip.css(bgColor); - // Setup widget classes - setWidget(); + // Attempt to detect the correct border side colour from various elements, left-to-right precedance + color.border = css(tip, borderSide, 'color') || css(colorElem, borderSide, 'color') || + css(elems.content, borderSide, 'color') || css(tooltip, borderSide, 'color') || tooltip.css(borderSide); - // Assign passed event callbacks (before plugins!) - $.each(options.events, function(name, callback) { - if($.isFunction(callback)) { - tooltip.bind(name === 'toggle' ? 'tooltipshow tooltiphide' : 'tooltip'+name, callback); - } - }); + // Reset background and border colours + $('*', tip).add(tip).css('cssText', bgColor+':'+transparent+important+';border:0'+important+';'); + }); + } - // Initialize 'render' plugins - $.each(PLUGINS, function() { - if(this.initialize === 'render') { this(self); } - }); + function calculateSize(corner) { + var y = corner.precedance === Y, + width = size [ y ? WIDTH : HEIGHT ], + height = size [ y ? HEIGHT : WIDTH ], + isCenter = corner.string().indexOf(CENTER) > -1, + base = width * (isCenter ? 0.5 : 1), + pow = Math.pow, + round = Math.round, + bigHyp, ratio, result, - // Assign events - assignEvents(); + smallHyp = Math.sqrt( pow(base, 2) + pow(height, 2) ), + + hyp = [ + (border / base) * smallHyp, (border / height) * smallHyp + ]; + hyp[2] = Math.sqrt( pow(hyp[0], 2) - pow(border, 2) ); + hyp[3] = Math.sqrt( pow(hyp[1], 2) - pow(border, 2) ); - /* Queue this part of the render process in our fx queue so we can - * load images before the tooltip renders fully. - * - * See: updateContent method - */ - tooltip.queue('fx', function(next) { - // Trigger tooltiprender event and pass original triggering event as original - callback.originalEvent = cache.event; - tooltip.trigger(callback, [self]); + bigHyp = smallHyp + hyp[2] + hyp[3] + (isCenter ? 0 : hyp[0]); + ratio = bigHyp / smallHyp; - // Reset flags - isDrawing = 0; isPositioning = 0; + result = [ round(ratio * height), round(ratio * width) ]; + return { height: result[ y ? 0 : 1 ], width: result[ y ? 1 : 0 ] }; + } - // Redraw the tooltip manually now we're fully rendered - self.redraw(); + function createVML(tag, props, style) { + return ''; + } - // Show tooltip if needed - if(options.show.ready || show) { - self.toggle(TRUE, cache.event, FALSE); - } + $.extend(self, { + init: function() + { + var enabled = parseCorner() && (hasCanvas || $.browser.msie); - next(); // Move on to next method in queue - }); + // Determine tip corner and type + if(enabled) { + // Create a new tip and draw it + self.create(); + self.update(); - return self; + // Bind update events + tooltip.unbind(namespace).bind('tooltipmove'+namespace, reposition); + } + + return enabled; }, - get: function(notation) + create: function() { - var result, o; + var width = size.width, + height = size.height, + vml; - switch(notation.toLowerCase()) - { - case 'dimensions': - result = { - height: tooltip.outerHeight(), width: tooltip.outerWidth() - }; - break; - - case 'offset': - result = PLUGINS.offset(tooltip, options.position.container); - break; - - default: - o = convertNotation(notation.toLowerCase()); - result = o[0][ o[1] ]; - result = result.precedance ? result.string() : result; - break; - } + // Remove previous tip element if present + if(elems.tip) { elems.tip.remove(); } - return result; - }, + // Create tip element and prepend to the tooltip + elems.tip = $('
', { 'class': 'qtip-tip' }).css({ width: width, height: height }).prependTo(tooltip); - set: function(option, value) - { - var rmove = /^position\.(my|at|adjust|target|container)|style|content|show\.ready/i, - rdraw = /^content\.(title|attr)|style/i, - reposition = FALSE, - redraw = FALSE, - checks = self.checks, - name; - - function callback(notation, args) { - var category, rule, match; - - for(category in checks) { - for(rule in checks[category]) { - if(match = (new RegExp(rule, 'i')).exec(notation)) { - args.push(match); - checks[category][rule].apply(self, args); - } - } - } + // Create tip drawing element(s) + if(hasCanvas) { + // save() as soon as we create the canvas element so FF2 doesn't bork on our first restore()! + $('').appendTo(elems.tip)[0].getContext('2d').save(); } + else { + vml = createVML('shape', 'coordorigin="0,0"', 'position:absolute;'); + elems.tip.html(vml + vml); - // Convert singular option/value pair into object form - if('string' === typeof option) { - name = option; option = {}; option[name] = value; + // Prevent mousing down on the tip since it causes problems with .live() handling in IE due to VML + $('*', elems.tip).bind('click mousedown', function(event) { event.stopPropagation(); }); } - else { option = $.extend(TRUE, {}, option); } - - // Set all of the defined options to their new values - $.each(option, function(notation, value) { - var obj = convertNotation( notation.toLowerCase() ), previous; - - // Set new obj value - previous = obj[0][ obj[1] ]; - obj[0][ obj[1] ] = 'object' === typeof value && value.nodeType ? $(value) : value; + }, - // Set the new params for the callback - option[notation] = [obj[0], obj[1], value, previous]; - - // Also check if we need to reposition / redraw - reposition = rmove.test(notation) || reposition; - redraw = rdraw.test(notation) || redraw; - }); - - // Re-sanitize options - sanitizeOptions(options); - - /* - * Execute any valid callbacks for the set options - * Also set isPositioning/isDrawing so we don't get loads of redundant repositioning - * and redraw calls. - */ - isPositioning = isDrawing = 1; $.each(option, callback); isPositioning = isDrawing = 0; - - // Update position / redraw if needed - if(self.rendered && tooltip[0].offsetWidth > 0) { - if(reposition) { - self.reposition( options.position.target === 'mouse' ? NULL : cache.event ); - } - if(redraw) { self.redraw(); } - } - - return self; - }, - - toggle: function(state, event) + update: function(corner, position) { - // Render the tooltip if showing and it isn't already - if(!self.rendered) { return state ? self.render(1) : self; } - - var type = state ? 'show' : 'hide', - opts = options[type], - otherOpts = options[ !state ? 'show' : 'hide' ], - posOptions = options.position, - contentOptions = options.content, - visible = tooltip[0].offsetWidth > 0, - animate = state || opts.target.length === 1, - sameTarget = !event || opts.target.length < 2 || cache.target[0] === event.target, - delay, callback; - - // Detect state if valid one isn't provided - if((typeof state).search('boolean|number')) { state = !visible; } - - // Return if element is already in correct state - if(!tooltip.is(':animated') && visible === state && sameTarget) { return self; } - - // Try to prevent flickering when tooltip overlaps show element - if(event) { - if((/over|enter/).test(event.type) && (/out|leave/).test(cache.event.type) && - options.show.target.add(event.target).length === options.show.target.length && - tooltip.has(event.relatedTarget).length) { - return self; - } - - // Cache event - cache.event = $.extend({}, event); - } - - // Call API methods - callback = $.Event('tooltip'+type); - callback.originalEvent = event ? cache.event : NULL; - tooltip.trigger(callback, [self, 90]); - if(callback.isDefaultPrevented()){ return self; } - - // Set ARIA hidden status attribute - $.attr(tooltip[0], 'aria-hidden', !!!state); + var tip = elems.tip, + inner = tip.children(), + width = size.width, + height = size.height, + mimic = opts.mimic, + round = Math.round, + precedance, context, coords, translate, newSize; - // Execute state specific properties - if(state) { - // Store show origin coordinates - cache.origin = $.extend({}, MOUSE); - - // Focus the tooltip - self.focus(event); - - // Update tooltip content & title if it's a dynamic function - if($.isFunction(contentOptions.text)) { updateContent(contentOptions.text, FALSE); } - if($.isFunction(contentOptions.title.text)) { updateTitle(contentOptions.title.text, FALSE); } - - // Cache mousemove events for positioning purposes (if not already tracking) - if(!trackingBound && posOptions.target === 'mouse' && posOptions.adjust.mouse) { - $(document).bind('mousemove.qtip', function(event) { - MOUSE = { pageX: event.pageX, pageY: event.pageY, type: 'mousemove' }; - }); - trackingBound = TRUE; - } + // Re-determine tip if not already set + if(!corner) { corner = cache.corner || self.corner; } - // Update the tooltip position - self.reposition(event, arguments[2]); + // Use corner property if we detect an invalid mimic value + if(mimic === FALSE) { mimic = corner; } - // Hide other tooltips if tooltip is solo, using it as the context - if((callback.solo = !!opts.solo)) { $(selector, opts.solo).not(tooltip).qtip('hide', callback); } - } + // Otherwise inherit mimic properties from the corner object as necessary else { - // Clear show timer if we're hiding - clearTimeout(self.timers.show); - - // Remove cached origin on hide - delete cache.origin; + mimic = new PLUGINS.Corner(mimic); + mimic.precedance = corner.precedance; - // Remove mouse tracking event if not needed (all tracking qTips are hidden) - if(trackingBound && !$(selector+'[tracking="true"]:visible', opts.solo).not(tooltip).length) { - $(document).unbind('mousemove.qtip'); - trackingBound = FALSE; + if(mimic.x === 'inherit') { mimic.x = corner.x; } + else if(mimic.y === 'inherit') { mimic.y = corner.y; } + else if(mimic.x === mimic.y) { + mimic[ corner.precedance ] = corner[ corner.precedance ]; } - - // Blur the tooltip - self.blur(event); } + precedance = mimic.precedance; - // Define post-animation, state specific properties - function after() { - if(state) { - // Prevent antialias from disappearing in IE by removing filter - if($.browser.msie) { tooltip[0].style.removeAttribute('filter'); } + // Ensure the tip width.height are relative to the tip position + if(corner.precedance === X) { swapDimensions(); } + else { resetDimensions(); } - // Remove overflow setting to prevent tip bugs - tooltip.css('overflow', ''); + // Set the tip dimensions + elems.tip.css({ + width: (width = size.width), + height: (height = size.height) + }); - // Autofocus elements if enabled - if('string' === typeof opts.autofocus) { - $(opts.autofocus, tooltip).focus(); - } + // Update our colours + parseColours(corner); - // If set, hide tooltip when inactive for delay period - opts.target.trigger('qtip-'+id+'-inactive'); - } - else { - // Reset CSS states - tooltip.css({ - display: '', - visibility: '', - opacity: '', - left: '', - top: '' - }); - } + // Detect border width, taking into account colours + if(color.border !== 'transparent') { + // Grab border width + border = parseWidth(corner, NULL); - // Call API method - callback = $.Event('tooltip'+(state ? 'visible' : 'hidden')); - callback.originalEvent = event ? cache.event : NULL; - tooltip.trigger(callback, [self]); - } + // If border width isn't zero, use border color as fill (1.0 style tips) + if(opts.border === 0 && border > 0) { color.fill = color.border; } - // If no effect type is supplied, use a simple toggle - if(opts.effect === FALSE || animate === FALSE) { - tooltip[ type ](); - after.call(tooltip); + // Set border width (use detected border width if opts.border is true) + self.border = border = opts.border !== TRUE ? opts.border : border; } - // Use custom function if provided - else if($.isFunction(opts.effect)) { - tooltip.stop(1, 1); - opts.effect.call(tooltip, self); - tooltip.queue('fx', function(n){ after(); n(); }); - } + // Border colour was invalid, set border to zero + else { self.border = border = 0; } - // Use basic fade function by default - else { tooltip.fadeTo(90, state ? 1 : 0, after); } + // Calculate coordinates + coords = calculateTip(mimic, width , height); - // If inactive hide method is set, active it - if(state) { opts.target.trigger('qtip-'+id+'-inactive'); } + // Determine tip size + self.size = newSize = calculateSize(corner); + tip.css(newSize).css('line-height', newSize.height+'px'); - return self; - }, + // Calculate tip translation + if(corner.precedance === Y) { + translate = [ + round(mimic.x === LEFT ? border : mimic.x === RIGHT ? newSize.width - width - border : (newSize.width - width) / 2), + round(mimic.y === TOP ? newSize.height - height : 0) + ]; + } + else { + translate = [ + round(mimic.x === LEFT ? newSize.width - width : 0), + round(mimic.y === TOP ? border : mimic.y === BOTTOM ? newSize.height - height - border : (newSize.height - height) / 2) + ]; + } - show: function(event){ return self.toggle(TRUE, event); }, + // Canvas drawing implementation + if(hasCanvas) { + // Set the canvas size using calculated size + inner.attr(newSize); - hide: function(event){ return self.toggle(FALSE, event); }, + // Grab canvas context and clear/save it + context = inner[0].getContext('2d'); + context.restore(); context.save(); + context.clearRect(0,0,3000,3000); - focus: function(event) - { - if(!self.rendered) { return self; } + // Set properties + context.fillStyle = color.fill; + context.strokeStyle = color.border; + context.lineWidth = border * 2; + context.lineJoin = 'miter'; + context.miterLimit = 100; - var qtips = $(selector), - curIndex = parseInt(tooltip[0].style.zIndex, 10), - newIndex = QTIP.zindex + qtips.length, - cachedEvent = $.extend({}, event), - focusedElem, callback; + // Translate origin + context.translate(translate[0], translate[1]); - // Only update the z-index if it has changed and tooltip is not already focused - if(!tooltip.hasClass(focusClass)) - { - // Call API method - callback = $.Event('tooltipfocus'); - callback.originalEvent = cachedEvent; - tooltip.trigger(callback, [self, newIndex]); - - // If default action wasn't prevented... - if(!callback.isDefaultPrevented()) { - // Only update z-index's if they've changed - if(curIndex !== newIndex) { - // Reduce our z-index's and keep them properly ordered - qtips.each(function() { - if(this.style.zIndex > curIndex) { - this.style.zIndex = this.style.zIndex - 1; - } - }); + // Draw the tip + context.beginPath(); + context.moveTo(coords[0][0], coords[0][1]); + context.lineTo(coords[1][0], coords[1][1]); + context.lineTo(coords[2][0], coords[2][1]); + context.closePath(); - // Fire blur event for focused tooltip - qtips.filter('.' + focusClass).qtip('blur', cachedEvent); + // Apply fill and border + if(border) { + // Make sure transparent borders are supported by doing a stroke + // of the background colour before the stroke colour + if(tooltip.css('background-clip') === 'border-box') { + context.strokeStyle = color.fill; + context.stroke(); } - - // Set the new z-index - tooltip.addClass(focusClass)[0].style.zIndex = newIndex; + context.strokeStyle = color.border; + context.stroke(); } + context.fill(); } - return self; - }, - - blur: function(event) { - var cachedEvent = $.extend({}, event), - callback; + // VML (IE Proprietary implementation) + else { + // Setup coordinates string + coords = 'm' + coords[0][0] + ',' + coords[0][1] + ' l' + coords[1][0] + + ',' + coords[1][1] + ' ' + coords[2][0] + ',' + coords[2][1] + ' xe'; - // Set focused status to FALSE - tooltip.removeClass(focusClass); + // Setup VML-specific offset for pixel-perfection + translate[2] = border && /^(r|b)/i.test(corner.string()) ? + parseFloat($.browser.version, 10) === 8 ? 2 : 1 : 0; - // Trigger blur event - callback = $.Event('tooltipblur'); - callback.originalEvent = cachedEvent; - tooltip.trigger(callback, [self]); + // Set initial CSS + inner.css({ + coordsize: (width+border) + ' ' + (height+border), + antialias: ''+(mimic.string().indexOf(CENTER) > -1), + left: translate[0], + top: translate[1], + width: width + border, + height: height + border + }) + .each(function(i) { + var $this = $(this); - return self; - }, + // Set shape specific attributes + $this[ $this.prop ? 'prop' : 'attr' ]({ + coordsize: (width+border) + ' ' + (height+border), + path: coords, + fillcolor: color.fill, + filled: !!i, + stroked: !i + }) + .toggle(!!(border || i)); - reposition: function(event, effect) - { - if(!self.rendered || isPositioning) { return self; } - - // Set positioning flag - isPositioning = 1; - - var target = options.position.target, - posOptions = options.position, - my = posOptions.my, - at = posOptions.at, - adjust = posOptions.adjust, - method = adjust.method.split(' '), - elemWidth = tooltip.outerWidth(), - elemHeight = tooltip.outerHeight(), - targetWidth = 0, - targetHeight = 0, - callback = $.Event('tooltipmove'), - fixed = tooltip.css('position') === 'fixed', - viewport = posOptions.viewport, - position = { left: 0, top: 0 }, - container = posOptions.container, - flipoffset = FALSE, - tip = self.plugins.tip, - visible = tooltip[0].offsetWidth > 0, - readjust = { - // Axis detection and readjustment indicator - horizontal: method[0], - vertical: (method[1] = method[1] || method[0]), - enabled: viewport.jquery && target[0] !== window && target[0] !== docBody && adjust.method !== 'none', - - // Reposition methods - left: function(posLeft) { - var isShift = readjust.horizontal === 'shift', - adjustx = adjust.x * (readjust.horizontal.substr(-6) === 'invert' ? 2 : 0), - viewportScroll = -container.offset.left + viewport.offset.left + viewport.scrollLeft, - myWidth = my.x === 'left' ? elemWidth : my.x === 'right' ? -elemWidth : -elemWidth / 2, - atWidth = at.x === 'left' ? targetWidth : at.x === 'right' ? -targetWidth : -targetWidth / 2, - tipWidth = tip && tip.size ? tip.size.width || 0 : 0, - tipAdjust = tip && tip.corner && tip.corner.precedance === 'x' && !isShift ? tipWidth : 0, - overflowLeft = viewportScroll - posLeft + tipAdjust, - overflowRight = posLeft + elemWidth - viewport.width - viewportScroll + tipAdjust, - offset = myWidth - (my.precedance === 'x' || my.x === my.y ? atWidth : 0) - (at.x === 'center' ? targetWidth / 2 : 0), - isCenter = my.x === 'center'; - - // Optional 'shift' style repositioning - if(isShift) { - tipAdjust = tip && tip.corner && tip.corner.precedance === 'y' ? tipWidth : 0; - offset = (my.x === 'left' ? 1 : -1) * myWidth - tipAdjust; - - // Adjust position but keep it within viewport dimensions - position.left += overflowLeft > 0 ? overflowLeft : overflowRight > 0 ? -overflowRight : 0; - position.left = Math.max( - -container.offset.left + viewport.offset.left + (tipAdjust && tip.corner.x === 'center' ? tip.offset : 0), - posLeft - offset, - Math.min( - Math.max(-container.offset.left + viewport.offset.left + viewport.width, posLeft + offset), - position.left - ) - ); - } - - // Default 'flip' repositioning - else { - if(overflowLeft > 0 && (my.x !== 'left' || overflowRight > 0)) { - position.left -= offset + adjustx; - } - else if(overflowRight > 0 && (my.x !== 'right' || overflowLeft > 0) ) { - position.left -= (isCenter ? -offset : offset) + adjustx; - } - - // Make sure we haven't made things worse with the adjustment and return the adjusted difference - if(position.left < viewportScroll && -position.left > overflowRight) { position.left = posLeft; } - } - - return position.left - posLeft; - }, - top: function(posTop) { - var isShift = readjust.vertical === 'shift', - adjusty = adjust.y * (readjust.vertical.substr(-6) === 'invert' ? 2 : 0), - viewportScroll = -container.offset.top + viewport.offset.top + viewport.scrollTop, - myHeight = my.y === 'top' ? elemHeight : my.y === 'bottom' ? -elemHeight : -elemHeight / 2, - atHeight = at.y === 'top' ? targetHeight : at.y === 'bottom' ? -targetHeight : -targetHeight / 2, - tipHeight = tip && tip.size ? tip.size.height || 0 : 0, - tipAdjust = tip && tip.corner && tip.corner.precedance === 'y' && !isShift ? tipHeight : 0, - overflowTop = viewportScroll - posTop + tipAdjust, - overflowBottom = posTop + elemHeight - viewport.height - viewportScroll + tipAdjust, - offset = myHeight - (my.precedance === 'y' || my.x === my.y ? atHeight : 0) - (at.y === 'center' ? targetHeight / 2 : 0), - isCenter = my.y === 'center'; - - // Optional 'shift' style repositioning - if(isShift) { - tipAdjust = tip && tip.corner && tip.corner.precedance === 'x' ? tipHeight : 0; - offset = (my.y === 'top' ? 1 : -1) * myHeight - tipAdjust; - - // Adjust position but keep it within viewport dimensions - position.top += overflowTop > 0 ? overflowTop : overflowBottom > 0 ? -overflowBottom : 0; - position.top = Math.max( - -container.offset.top + viewport.offset.top + (tipAdjust && tip.corner.x === 'center' ? tip.offset : 0), - posTop - offset, - Math.min( - Math.max(-container.offset.top + viewport.offset.top + viewport.height, posTop + offset), - position.top - ) - ); - } - - // Default 'flip' repositioning - else { - if(overflowTop > 0 && (my.y !== 'top' || overflowBottom > 0)) { - position.top -= offset + adjusty; - } - else if(overflowBottom > 0 && (my.y !== 'bottom' || overflowTop > 0) ) { - position.top -= (isCenter ? -offset : offset) + adjusty; - } - - // Make sure we haven't made things worse with the adjustment and return the adjusted difference - if(position.top < 0 && -position.top > overflowBottom) { position.top = posTop; } - } - - return position.top - posTop; + // Check if border is enabled and add stroke element + if(!i && $this.html() === '') { + $this.html( + createVML('stroke', 'weight="'+(border*2)+'px" color="'+color.border+'" miterlimit="1000" joinstyle="miter"') + ); } - }, - win; - - // Check if absolute position was passed - if($.isArray(target) && target.length === 2) { - // Force left top and set position - at = { x: 'left', y: 'top' }; - position = { left: target[0], top: target[1] }; + }); } - // Check if mouse was the target - else if(target === 'mouse' && ((event && event.pageX) || cache.event.pageX)) { - // Force left top to allow flipping - at = { x: 'left', y: 'top' }; + // Position if needed + if(position !== FALSE) { self.position(corner); } + }, - // Use cached event if one isn't available for positioning - event = (event && (event.type === 'resize' || event.type === 'scroll') ? cache.event : - event && event.pageX && event.type === 'mousemove' ? event : - MOUSE && MOUSE.pageX && (adjust.mouse || !event || !event.pageX) ? { pageX: MOUSE.pageX, pageY: MOUSE.pageY } : - !adjust.mouse && cache.origin && cache.origin.pageX && options.show.distance ? cache.origin : - event) || event || cache.event || MOUSE || {}; + // Tip positioning method + position: function(corner) + { + var tip = elems.tip, + position = {}, + userOffset = Math.max(0, opts.offset), + precedance, dimensions, corners; - // Use event coordinates for position - position = { top: event.pageY, left: event.pageX }; - } + // Return if tips are disabled or tip is not yet rendered + if(opts.corner === FALSE || !tip) { return FALSE; } - // Target wasn't mouse or absolute... - else { - // Check if event targetting is being used - if(target === 'event') { - if(event && event.target && event.type !== 'scroll' && event.type !== 'resize') { - target = cache.target = $(event.target); - } - else { - target = cache.target; - } - } - else { - target = cache.target = $(target.jquery ? target : elements.target); - } + // Inherit corner if not provided + corner = corner || self.corner; + precedance = corner.precedance; - // Parse the target into a jQuery object and make sure there's an element present - target = $(target).eq(0); - if(target.length === 0) { return self; } + // Determine which tip dimension to use for adjustment + dimensions = calculateSize(corner); - // Check if window or document is the target - else if(target[0] === document || target[0] === window) { - targetWidth = PLUGINS.iOS ? window.innerWidth : target.width(); - targetHeight = PLUGINS.iOS ? window.innerHeight : target.height(); + // Setup corners and offset array + corners = [ corner.x, corner.y ]; + if(precedance === X) { corners.reverse(); } - if(target[0] === window) { - position = { - top: (viewport || target).scrollTop(), - left: (viewport || target).scrollLeft() - }; - } - } + // Calculate tip position + $.each(corners, function(i, side) { + var b, bc, br; - // Use Imagemap/SVG plugins if needed - else if(target.is('area') && PLUGINS.imagemap) { - position = PLUGINS.imagemap(target, at, readjust.enabled ? method : FALSE); - } - else if(target[0].namespaceURI === 'http://www.w3.org/2000/svg' && PLUGINS.svg) { - position = PLUGINS.svg(target, at); + if(side === CENTER) { + b = precedance === Y ? LEFT : TOP; + position[ b ] = '50%'; + position['margin-' + b] = -Math.round(dimensions[ precedance === Y ? WIDTH : HEIGHT ] / 2) + userOffset; } - else { - targetWidth = target.outerWidth(); - targetHeight = target.outerHeight(); - - position = PLUGINS.offset(target, container); - } + b = parseWidth(corner, side); + bc = parseWidth(corner, side, elems.content); + br = parseRadius(corner); - // Parse returned plugin values into proper variables - if(position.offset) { - targetWidth = position.width; - targetHeight = position.height; - flipoffset = position.flipoffset; - position = position.offset; + position[ side ] = i ? bc : (userOffset + (br > b ? br : -b)); } + }); - // Adjust for position.fixed tooltips (and also iOS scroll bug in v3.2 - v4.0) - if((PLUGINS.iOS < 4.1 && PLUGINS.iOS > 3.1) || PLUGINS.iOS == 4.3 || (!PLUGINS.iOS && fixed)) { - win = $(window); - position.left -= win.scrollLeft(); - position.top -= win.scrollTop(); - } + // Adjust for tip dimensions + position[ corner[precedance] ] -= dimensions[ precedance === X ? WIDTH : HEIGHT ]; - // Adjust position relative to target - position.left += at.x === 'right' ? targetWidth : at.x === 'center' ? targetWidth / 2 : 0; - position.top += at.y === 'bottom' ? targetHeight : at.y === 'center' ? targetHeight / 2 : 0; - } + // Set and return new position + tip.css({ top: '', bottom: '', left: '', right: '', margin: '' }).css(position); + return position; + }, + + destroy: function() + { + // Remove the tip element + if(elems.tip) { elems.tip.remove(); } + elems.tip = false; - // Adjust position relative to tooltip - position.left += adjust.x + (my.x === 'right' ? -elemWidth : my.x === 'center' ? -elemWidth / 2 : 0); - position.top += adjust.y + (my.y === 'bottom' ? -elemHeight : my.y === 'center' ? -elemHeight / 2 : 0); - - // Calculate collision offset values if viewport positioning is enabled - if(readjust.enabled) { - // Cache our viewport details - viewport = { - elem: viewport, - height: viewport[ (viewport[0] === window ? 'h' : 'outerH') + 'eight' ](), - width: viewport[ (viewport[0] === window ? 'w' : 'outerW') + 'idth' ](), - scrollLeft: fixed ? 0 : viewport.scrollLeft(), - scrollTop: fixed ? 0 : viewport.scrollTop(), - offset: viewport.offset() || { left: 0, top: 0 } - }; - container = { - elem: container, - scrollLeft: container.scrollLeft(), - scrollTop: container.scrollTop(), - offset: container.offset() || { left: 0, top: 0 } - }; + // Unbind events + tooltip.unbind(namespace); + } + }); - // Adjust position based onviewport and adjustment options - position.adjusted = { - left: readjust.horizontal !== 'none' ? readjust.left(position.left) : 0, - top: readjust.vertical !== 'none' ? readjust.top(position.top) : 0 - }; + self.init(); +} - // Set tooltip position class - if(position.adjusted.left + position.adjusted.top) { - tooltip.attr('class', tooltip[0].className.replace(/ui-tooltip-pos-\w+/i, uitooltip + '-pos-' + my.abbrev())); - } +PLUGINS.tip = function(api) +{ + var self = api.plugins.tip; + + return 'object' === typeof self ? self : (api.plugins.tip = new Tip(api)); +}; - // Apply flip offsets supplied by positioning plugins - if(flipoffset && position.adjusted.left) { position.left += flipoffset.left; } - if(flipoffset && position.adjusted.top) { position.top += flipoffset.top; } - } +// Initialize tip on render +PLUGINS.tip.initialize = 'render'; - //Viewport adjustment is disabled, set values to zero - else { position.adjusted = { left: 0, top: 0 }; } +// Setup plugin sanitization options +PLUGINS.tip.sanitize = function(options) +{ + var style = options.style, opts; + if(style && 'tip' in style) { + opts = options.style.tip; + if(typeof opts !== 'object'){ options.style.tip = { corner: opts }; } + if(!(/string|boolean/i).test(typeof opts['corner'])) { opts['corner'] = TRUE; } + if(typeof opts.width !== 'number'){ delete opts.width; } + if(typeof opts.height !== 'number'){ delete opts.height; } + if(typeof opts.border !== 'number' && opts.border !== TRUE){ delete opts.border; } + if(typeof opts.offset !== 'number'){ delete opts.offset; } + } +}; - // Call API method - callback.originalEvent = $.extend({}, event); - tooltip.trigger(callback, [self, position, viewport.elem || viewport]); - if(callback.isDefaultPrevented()){ return self; } - delete position.adjusted; +// Extend original qTip defaults +$.extend(TRUE, QTIP.defaults, { + style: { + tip: { + corner: TRUE, + mimic: FALSE, + width: 6, + height: 6, + border: TRUE, + offset: 0 + } + } +}); - // If effect is disabled, target it mouse, no animation is defined or positioning gives NaN out, set CSS directly - if(effect === FALSE || !visible || isNaN(position.left) || isNaN(position.top) || target === 'mouse' || !$.isFunction(posOptions.effect)) { - tooltip.css(position); - } - // Use custom function if provided - else if($.isFunction(posOptions.effect)) { - posOptions.effect.call(tooltip, self, $.extend({}, position)); - tooltip.queue(function(next) { - // Reset attributes to avoid cross-browser rendering bugs - $(this).css({ opacity: '', height: '' }); - if($.browser.msie) { this.style.removeAttribute('filter'); } +function Modal(api) +{ + var self = this, + options = api.options.show.modal, + elems = api.elements, + tooltip = elems.tooltip, + overlaySelector = '#qtip-overlay', + globalNamespace = '.qtipmodal', + namespace = globalNamespace + api.id, + attr = 'is-modal-qtip', + docBody = $(document.body), + focusableSelector = PLUGINS.modal.focusable.join(','), + focusableElems = {}, overlay; - next(); - }); - } + // Setup option set checks + api.checks.modal = { + '^show.modal.(on|blur)$': function() { + // Initialise + self.init(); + + // Show the modal if not visible already and tooltip is visible + elems.overlay.toggle( tooltip.is(':visible') ); + }, + '^content.text$': function() { + updateFocusable(); + } + }; - // Set positioning flag - isPositioning = 0; + function updateFocusable() { + focusableElems = $(focusableSelector, tooltip).not('[disabled]').map(function() { + return typeof this.focus === 'function' ? this : null; + }); + } - return self; - }, + function focusInputs(blurElems) { + // Blurring body element in IE causes window.open windows to unfocus! + if(focusableElems.length < 1 && blurElems.length) { blurElems.not('body').blur(); } - // Max/min width simulator function for all browsers.. yeaaah! - redraw: function() - { - if(self.rendered < 1 || isDrawing) { return self; } + // Focus the inputs + else { focusableElems.first().focus(); } + } - var container = options.position.container, - perc, width, max, min; + function stealFocus(event) { + var target = $(event.target), + container = target.closest('.qtip'), + targetOnTop; - // Set drawing flag - isDrawing = 1; + // Determine if input container target is above this + targetOnTop = container.length < 1 ? FALSE : + (parseInt(container[0].style.zIndex, 10) > parseInt(tooltip[0].style.zIndex, 10)); - // If tooltip has a set height, just set it... like a boss! - if(options.style.height) { tooltip.css('height', options.style.height); } + // If we're showing a modal, but focus has landed on an input below + // this modal, divert focus to the first visible input in this modal + // or if we can't find one... the tooltip itself + if(!targetOnTop && ($(event.target).closest(selector)[0] !== tooltip[0])) { + focusInputs(target); + } + } - // If tooltip has a set width, just set it... like a boss! - if(options.style.width) { tooltip.css('width', options.style.width); } + $.extend(self, { + init: function() + { + // If modal is disabled... return + if(!options.on) { return self; } - // Otherwise simualte max/min width... - else { - // Reset width and add fluid class - tooltip.css('width', '').addClass(fluidClass); + // Create the overlay if needed + overlay = self.create(); - // Grab our tooltip width (add 1 so we don't get wrapping problems.. huzzah!) - width = tooltip.width() + 1; + // Add unique attribute so we can grab modal tooltips easily via a selector + tooltip.attr(attr, TRUE) - // Grab our max/min properties - max = tooltip.css('max-width') || ''; - min = tooltip.css('min-width') || ''; + // Set z-index + .css('z-index', PLUGINS.modal.zindex + $(selector+'['+attr+']').length) + + // Remove previous bound events in globalNamespace + .unbind(globalNamespace).unbind(namespace) - // Parse into proper pixel values - perc = (max + min).indexOf('%') > -1 ? container.width() / 100 : 0; - max = ((max.indexOf('%') > -1 ? perc : 1) * parseInt(max, 10)) || width; - min = ((min.indexOf('%') > -1 ? perc : 1) * parseInt(min, 10)) || 0; + // Apply our show/hide/focus modal events + .bind('tooltipshow'+globalNamespace+' tooltiphide'+globalNamespace, function(event, api, duration) { + var oEvent = event.originalEvent; - // Determine new dimension size based on max/min/current values - width = max + min ? Math.min(Math.max(width, min), max) : width; + // Make sure mouseout doesn't trigger a hide when showing the modal and mousing onto backdrop + if(event.target === tooltip[0]) { + if(oEvent && event.type === 'tooltiphide' && /mouse(leave|enter)/.test(oEvent.type) && $(oEvent.relatedTarget).closest(overlay[0]).length) { + try { event.preventDefault(); } catch(e) {} + } + else if(!oEvent || (oEvent && !oEvent.solo)) { + self[ event.type.replace('tooltip', '') ](event, duration); + } + } + }) - // Set the newly calculated width and remvoe fluid class - tooltip.css('width', Math.round(width)).removeClass(fluidClass); - } + // Adjust modal z-index on tooltip focus + .bind('tooltipfocus'+globalNamespace, function(event) { + // If focus was cancelled before it reearch us, don't do anything + if(event.isDefaultPrevented() || event.target !== tooltip[0]) { return; } - // Set drawing flag - isDrawing = 0; + var qtips = $(selector).filter('['+attr+']'), - return self; - }, + // Keep the modal's lower than other, regular qtips + newIndex = PLUGINS.modal.zindex + qtips.length, + curIndex = parseInt(tooltip[0].style.zIndex, 10); - disable: function(state) - { - if('boolean' !== typeof state) { - state = !(tooltip.hasClass(disabled) || cache.disabled); - } + // Set overlay z-index + overlay[0].style.zIndex = newIndex - 2; - if(self.rendered) { - tooltip.toggleClass(disabled, state); - $.attr(tooltip[0], 'aria-disabled', state); - } - else { - cache.disabled = !!state; - } + // Reduce modal z-index's and keep them properly ordered + qtips.each(function() { + if(this.style.zIndex > curIndex) { + this.style.zIndex -= 1; + } + }); - return self; - }, + // Fire blur event for focused tooltip + qtips.end().filter('.' + focusClass).qtip('blur', event.originalEvent); - enable: function() { return self.disable(FALSE); }, + // Set the new z-index + tooltip.addClass(focusClass)[0].style.zIndex = newIndex; - destroy: function() - { - var t = target[0], - title = $.attr(t, oldtitle), - elemAPI = target.data('qtip'); + // Prevent default handling + try { event.preventDefault(); } catch(e) {} + }) - // Set flag the signify destroy is taking place to plugins - self.destroyed = TRUE; + // Focus any other visible modals when this one hides + .bind('tooltiphide'+globalNamespace, function(event) { + if(event.target === tooltip[0]) { + $('[' + attr + ']').filter(':visible').not(tooltip).last().qtip('focus', event); + } + }); - // Destroy tooltip and any associated plugins if rendered - if(self.rendered) { - tooltip.stop(1,0).remove(); + // Apply keyboard "Escape key" close handler + if(options.escape) { + $(document).unbind(namespace).bind('keydown'+namespace, function(event) { + if(event.keyCode === 27 && tooltip.hasClass(focusClass)) { + api.hide(event); + } + }); + } - $.each(self.plugins, function() { - if(this.destroy) { this.destroy(); } + // Apply click handler for blur option + if(options.blur) { + elems.overlay.unbind(namespace).bind('click'+namespace, function(event) { + if(tooltip.hasClass(focusClass)) { api.hide(event); } }); } - // Clear timers and remove bound events - clearTimeout(self.timers.show); - clearTimeout(self.timers.hide); - unassignEvents(); + // Update focusable elements + updateFocusable(); - // If the API if actually this qTip API... - if(!elemAPI || self === elemAPI) { - // Remove api object - $.removeData(t, 'qtip'); + return self; + }, - // Reset old title attribute if removed - if(options.suppress && title) { - $.attr(t, 'title', title); - target.removeAttr(oldtitle); - } + create: function() + { + var elem = $(overlaySelector), win = $(window); - // Remove ARIA attributes - target.removeAttr('aria-describedby'); + // Return if overlay is already rendered + if(elem.length) { + // Modal overlay should always be below all tooltips if possible + return (elems.overlay = elem.insertAfter( $(selector).last() )); } - // Remove qTip events associated with this API - target.unbind('.qtip-'+id); - - // Remove ID from sued id object - delete usedIDs[self.id]; - - return target; - } - }); -} - -// Initialization method -function init(id, opts) -{ - var obj, posOptions, attr, config, title, + // Create document overlay + overlay = elems.overlay = $('
', { + id: overlaySelector.substr(1), + html: '
', + mousedown: function() { return FALSE; } + }) + .hide() + .insertAfter( $(selector).last() ); - // Setup element references - elem = $(this), - docBody = $(document.body), + // Update position on window resize or scroll + function resize() { + overlay.css({ + height: win.height(), + width: win.width() + }); + } + win.unbind(globalNamespace).bind('resize'+globalNamespace, resize); + resize(); // Fire it initially too - // Use document body instead of document element if needed - newTarget = this === document ? docBody : elem, + return overlay; + }, - // Grab metadata from element if plugin is present - metadata = (elem.metadata) ? elem.metadata(opts.metadata) : NULL, + toggle: function(event, state, duration) + { + // Make sure default event hasn't been prevented + if(event && event.isDefaultPrevented()) { return self; } - // If metadata type if HTML5, grab 'name' from the object instead, or use the regular data object otherwise - metadata5 = opts.metadata.type === 'html5' && metadata ? metadata[opts.metadata.name] : NULL, + var effect = options.effect, + type = state ? 'show': 'hide', + visible = overlay.is(':visible'), + modals = $('[' + attr + ']').filter(':visible').not(tooltip), + zindex; - // Grab data from metadata.name (or data-qtipopts as fallback) using .data() method, - html5 = elem.data(opts.metadata.name || 'qtipopts'); + // Create our overlay if it isn't present already + if(!overlay) { overlay = self.create(); } - // If we don't get an object returned attempt to parse it manualyl without parseJSON - try { html5 = typeof html5 === 'string' ? (new Function("return " + html5))() : html5; } - catch(e) { log('Unable to parse HTML5 attribute data: ' + html5); } + // Prevent modal from conflicting with show.solo, and don't hide backdrop is other modals are visible + if((overlay.is(':animated') && visible === state && overlay.data('toggleState') !== FALSE) || (!state && modals.length)) { + return self; + } - // Merge in and sanitize metadata - config = $.extend(TRUE, {}, QTIP.defaults, opts, - typeof html5 === 'object' ? sanitizeOptions(html5) : NULL, - sanitizeOptions(metadata5 || metadata)); + // State specific... + if(state) { + // Set position + overlay.css({ left: 0, top: 0 }); - // Re-grab our positioning options now we've merged our metadata and set id to passed value - posOptions = config.position; - config.id = id; + // Toggle backdrop cursor style on show + overlay.toggleClass('blurs', options.blur); - // Setup missing content if none is detected - if('boolean' === typeof config.content.text) { - attr = elem.attr(config.content.attr); + // IF the modal can steal the focus + if(options.stealfocus !== FALSE) { + // Make sure we can't focus anything outside the tooltip + docBody.bind('focusin'+namespace, stealFocus); - // Grab from supplied attribute if available - if(config.content.attr !== FALSE && attr) { config.content.text = attr; } + // Blur the current item and focus anything in the modal we an + focusInputs( $('body :focus') ); + } + } + else { + // Undelegate focus handler + docBody.unbind('focusin'+namespace); + } - // No valid content was found, abort render - else { - log('Unable to locate content for tooltip! Aborting render of tooltip on element: ', elem); - return FALSE; - } - } + // Stop all animations + overlay.stop(TRUE, FALSE).data('toggleState', state); - // Setup target options - if(!posOptions.container.length) { posOptions.container = docBody; } - if(posOptions.target === FALSE) { posOptions.target = newTarget; } - if(config.show.target === FALSE) { config.show.target = newTarget; } - if(config.show.solo === TRUE) { config.show.solo = posOptions.container.closest('body'); } - if(config.hide.target === FALSE) { config.hide.target = newTarget; } - if(config.position.viewport === TRUE) { config.position.viewport = posOptions.container; } - - // Ensure we only use a single container - posOptions.container = posOptions.container.eq(0); - - // Convert position corner values into x and y strings - posOptions.at = new PLUGINS.Corner(posOptions.at); - posOptions.my = new PLUGINS.Corner(posOptions.my); - - // Destroy previous tooltip if overwrite is enabled, or skip element if not - if($.data(this, 'qtip')) { - if(config.overwrite) { - elem.qtip('destroy'); - } - else if(config.overwrite === FALSE) { - return FALSE; - } - } + // Use custom function if provided + if($.isFunction(effect)) { + effect.call(overlay, state); + } - // Remove title attribute and store it if present - if(config.suppress && (title = $.attr(this, 'title'))) { - $(this).removeAttr('title').attr(oldtitle, title); - } + // If no effect type is supplied, use a simple toggle + else if(effect === FALSE) { + overlay[ type ](); + } - // Initialize the tooltip and add API reference - obj = new QTip(elem, config, id, !!attr); - $.data(this, 'qtip', obj); + // Use basic fade function + else { + overlay.fadeTo( parseInt(duration, 10) || 90, state ? 1 : 0, function() { + if(!state) { $(this).hide(); } + }); + } - // Catch remove/removeqtip events on target element to destroy redundant tooltip - elem.bind('remove.qtip-'+id+' removeqtip.qtip-'+id, function(){ obj.destroy(); }); + // Reset position on hide + if(!state) { + overlay.queue(function(next) { + overlay.css({ left: '', top: '' }).removeData('toggleState'); + next(); + }); + } - return obj; -} + return self; + }, -// jQuery $.fn extension method -QTIP = $.fn.qtip = function(options, notation, newValue) -{ - var command = ('' + options).toLowerCase(), // Parse command - returned = NULL, - args = $.makeArray(arguments).slice(1), - event = args[args.length - 1], - opts = this[0] ? $.data(this[0], 'qtip') : NULL; - - // Check for API request - if((!arguments.length && opts) || command === 'api') { - return opts; - } + show: function(event, duration) { return self.toggle(event, TRUE, duration); }, + hide: function(event, duration) { return self.toggle(event, FALSE, duration); }, - // Execute API command if present - else if('string' === typeof options) - { - this.each(function() + destroy: function() { - var api = $.data(this, 'qtip'); - if(!api) { return TRUE; } + var delBlanket = overlay; - // Cache the event if possible - if(event && event.timeStamp) { api.cache.event = event; } + if(delBlanket) { + // Check if any other modal tooltips are present + delBlanket = $('[' + attr + ']').not(tooltip).length < 1; - // Check for specific API commands - if((command === 'option' || command === 'options') && notation) { - if($.isPlainObject(notation) || newValue !== undefined) { - api.set(notation, newValue); + // Remove overlay if needed + if(delBlanket) { + elems.overlay.remove(); + $(document).unbind(globalNamespace); } else { - returned = api.get(notation); - return FALSE; + elems.overlay.unbind(globalNamespace+api.id); } - } - // Execute API command - else if(api[command]) { - api[command].apply(api[command], args); + // Undelegate focus handler + docBody.unbind('focusin'+namespace); } - }); - - return returned !== NULL ? returned : this; - } - // No API commands. validate provided options and setup qTips - else if('object' === typeof options || !arguments.length) - { - opts = sanitizeOptions($.extend(TRUE, {}, options)); - - // Bind the qTips - return QTIP.bind.call(this, opts, event); - } -}; - -// $.fn.qtip Bind method -QTIP.bind = function(opts, event) -{ - return this.each(function(i) { - var options, targets, events, namespace, api, id; + // Remove bound events + return tooltip.removeAttr(attr).unbind(globalNamespace); + } + }); - // Find next available ID, or use custom ID if provided - id = $.isArray(opts.id) ? opts.id[i] : opts.id; - id = !id || id === FALSE || id.length < 1 || usedIDs[id] ? QTIP.nextid++ : (usedIDs[id] = id); + self.init(); +} - // Setup events namespace - namespace = '.qtip-'+id+'-create'; +PLUGINS.modal = function(api) { + var self = api.plugins.modal; - // Initialize the qTip and re-grab newly sanitized options - api = init.call(this, id, opts); - if(api === FALSE) { return TRUE; } - options = api.options; + return 'object' === typeof self ? self : (api.plugins.modal = new Modal(api)); +}; - // Initialize plugins - $.each(PLUGINS, function() { - if(this.initialize === 'initialize') { this(api); } - }); +// Plugin needs to be initialized on render +PLUGINS.modal.initialize = 'render'; - // Determine hide and show targets - targets = { show: options.show.target, hide: options.hide.target }; - events = { - show: $.trim('' + options.show.event).replace(/ /g, namespace+' ') + namespace, - hide: $.trim('' + options.hide.event).replace(/ /g, namespace+' ') + namespace - }; +// Setup sanitiztion rules +PLUGINS.modal.sanitize = function(opts) { + if(opts.show) { + if(typeof opts.show.modal !== 'object') { opts.show.modal = { on: !!opts.show.modal }; } + else if(typeof opts.show.modal.on === 'undefined') { opts.show.modal.on = TRUE; } + } +}; - /* - * Make sure hoverIntent functions properly by using mouseleave as a hide event if - * mouseenter/mouseout is used for show.event, even if it isn't in the users options. - */ - if(/mouse(over|enter)/i.test(events.show) && !/mouse(out|leave)/i.test(events.hide)) { - events.hide += ' mouseleave' + namespace; - } +// Base z-index for all modal tooltips (use qTip core z-index as a base) +PLUGINS.modal.zindex = QTIP.zindex - 200; - /* - * Also make sure initial mouse targetting works correctly by caching mousemove coords - * on show targets before the tooltip has rendered. - * - * Also set onTarget when triggered to keep mouse tracking working - */ - targets.show.bind('mousemove'+namespace, function(event) { - MOUSE = { pageX: event.pageX, pageY: event.pageY, type: 'mousemove' }; - api.cache.onTarget = TRUE; - }); +// Defines the selector used to select all 'focusable' elements within the modal when using the show.modal.stealfocus option. +// Selectors initially taken from http://stackoverflow.com/questions/7668525/is-there-a-jquery-selector-to-get-all-elements-that-can-get-focus +PLUGINS.modal.focusable = ['a[href]', 'area[href]', 'input', 'select', 'textarea', 'button', 'iframe', 'object', 'embed', '[tabindex]', '[contenteditable]']; - // Define hoverIntent function - function hoverIntent(event) { - function render() { - // Cache mouse coords,render and render the tooltip - api.render(typeof event === 'object' || options.show.ready); +// Extend original api defaults +$.extend(TRUE, QTIP.defaults, { + show: { + modal: { + on: FALSE, + effect: TRUE, + blur: TRUE, + stealfocus: TRUE, + escape: TRUE + } + } +}); - // Unbind show and hide events - targets.show.add(targets.hide).unbind(namespace); - } - // Only continue if tooltip isn't disabled - if(api.cache.disabled) { return FALSE; } +PLUGINS.viewport = function(api, position, posOptions, targetWidth, targetHeight, elemWidth, elemHeight) +{ + var target = posOptions.target, + tooltip = api.elements.tooltip, + my = posOptions.my, + at = posOptions.at, + adjust = posOptions.adjust, + method = adjust.method.split(' '), + methodX = method[0], + methodY = method[1] || method[0], + viewport = posOptions.viewport, + container = posOptions.container, + cache = api.cache, + tip = api.plugins.tip, + adjusted = { left: 0, top: 0 }, + fixed, newMy, newClass; + + // If viewport is not a jQuery element, or it's the window/document or no adjustment method is used... return + if(!viewport.jquery || target[0] === window || target[0] === document.body || adjust.method === 'none') { + return adjusted; + } - // Cache the event data - api.cache.event = $.extend({}, event); - api.cache.target = event ? $(event.target) : [undefined]; + // Cache our viewport details + fixed = tooltip.css('position') === 'fixed'; + viewport = { + elem: viewport, + height: viewport[ (viewport[0] === window ? 'h' : 'outerH') + 'eight' ](), + width: viewport[ (viewport[0] === window ? 'w' : 'outerW') + 'idth' ](), + scrollleft: fixed ? 0 : viewport.scrollLeft(), + scrolltop: fixed ? 0 : viewport.scrollTop(), + offset: viewport.offset() || { left: 0, top: 0 } + }; + container = { + elem: container, + scrollLeft: container.scrollLeft(), + scrollTop: container.scrollTop(), + offset: container.offset() || { left: 0, top: 0 } + }; - // Start the event sequence - if(options.show.delay > 0) { - clearTimeout(api.timers.show); - api.timers.show = setTimeout(render, options.show.delay); - if(events.show !== events.hide) { - targets.hide.bind(events.hide, function() { clearTimeout(api.timers.show); }); - } - } - else { render(); } + // Generic calculation method + function calculate(side, otherSide, type, adjust, side1, side2, lengthName, targetLength, elemLength) { + var initialPos = position[side1], + mySide = my[side], atSide = at[side], + isShift = type === SHIFT, + viewportScroll = -container.offset[side1] + viewport.offset[side1] + viewport['scroll'+side1], + myLength = mySide === side1 ? elemLength : mySide === side2 ? -elemLength : -elemLength / 2, + atLength = atSide === side1 ? targetLength : atSide === side2 ? -targetLength : -targetLength / 2, + tipLength = tip && tip.size ? tip.size[lengthName] || 0 : 0, + tipAdjust = tip && tip.corner && tip.corner.precedance === side && !isShift ? tipLength : 0, + overflow1 = viewportScroll - initialPos + tipAdjust, + overflow2 = initialPos + elemLength - viewport[lengthName] - viewportScroll + tipAdjust, + offset = myLength - (my.precedance === side || mySide === my[otherSide] ? atLength : 0) - (atSide === CENTER ? targetLength / 2 : 0); + + // shift + if(isShift) { + tipAdjust = tip && tip.corner && tip.corner.precedance === otherSide ? tipLength : 0; + offset = (mySide === side1 ? 1 : -1) * myLength - tipAdjust; + + // Adjust position but keep it within viewport dimensions + position[side1] += overflow1 > 0 ? overflow1 : overflow2 > 0 ? -overflow2 : 0; + position[side1] = Math.max( + -container.offset[side1] + viewport.offset[side1] + (tipAdjust && tip.corner[side] === CENTER ? tip.offset : 0), + initialPos - offset, + Math.min( + Math.max(-container.offset[side1] + viewport.offset[side1] + viewport[lengthName], initialPos + offset), + position[side1] + ) + ); } - // Bind show events to target - targets.show.bind(events.show, hoverIntent); + // flip/flipinvert + else { + // Update adjustment amount depending on if using flipinvert or flip + adjust *= (type === FLIPINVERT ? 2 : 0); - // Prerendering is enabled, create tooltip now - if(options.show.ready || options.prerender) { hoverIntent(event); } - }); -}; + // Check for overflow on the left/top + if(overflow1 > 0 && (mySide !== side1 || overflow2 > 0)) { + position[side1] -= offset + adjust; + newMy['invert'+side](side1); + } -// Setup base plugins -PLUGINS = QTIP.plugins = { - // Corner object parser - Corner: function(corner) { - corner = ('' + corner).replace(/([A-Z])/, ' $1').replace(/middle/gi, 'center').toLowerCase(); - this.x = (corner.match(/left|right/i) || corner.match(/center/) || ['inherit'])[0].toLowerCase(); - this.y = (corner.match(/top|bottom|center/i) || ['inherit'])[0].toLowerCase(); + // Check for overflow on the bottom/right + else if(overflow2 > 0 && (mySide !== side2 || overflow1 > 0) ) { + position[side1] -= (mySide === CENTER ? -offset : offset) + adjust; + newMy['invert'+side](side2); + } - var f = corner.charAt(0); this.precedance = (f === 't' || f === 'b' ? 'y' : 'x'); + // Make sure we haven't made things worse with the adjustment and reset if so + if(position[side1] < viewportScroll && -position[side1] > overflow2) { + position[side1] = initialPos; newMy = my.clone(); + } + } - this.string = function() { return this.precedance === 'y' ? this.y+this.x : this.x+this.y; }; - this.abbrev = function() { - var x = this.x.substr(0,1), y = this.y.substr(0,1); - return x === y ? x : (x === 'c' || (x !== 'c' && y !== 'c')) ? y + x : x + y; - }; + return position[side1] - initialPos; + } - this.clone = function() { - return { x: this.x, y: this.y, precedance: this.precedance, string: this.string, abbrev: this.abbrev, clone: this.clone }; - }; - }, - - // Custom (more correct for qTip!) offset calculator - offset: function(elem, container) { - var pos = elem.offset(), - docBody = elem.closest('body')[0], - parent = container, scrolled, - coffset, overflow; - - function scroll(e, i) { - pos.left += i * e.scrollLeft(); - pos.top += i * e.scrollTop(); - } + // Set newMy if using flip or flipinvert methods + if(methodX !== 'shift' || methodY !== 'shift') { newMy = my.clone(); } + + // Adjust position based onviewport and adjustment options + adjusted = { + left: methodX !== 'none' ? calculate( X, Y, methodX, adjust.x, LEFT, RIGHT, WIDTH, targetWidth, elemWidth ) : 0, + top: methodY !== 'none' ? calculate( Y, X, methodY, adjust.y, TOP, BOTTOM, HEIGHT, targetHeight, elemHeight ) : 0 + }; - if(parent) { - // Compensate for non-static containers offset - do { - if(parent.css('position') !== 'static') { - coffset = parent.position(); + // Set tooltip position class if it's changed + if(newMy && cache.lastClass !== (newClass = NAMESPACE + '-pos-' + newMy.abbrev())) { + tooltip.removeClass(api.cache.lastClass).addClass( (api.cache.lastClass = newClass) ); + } - // Account for element positioning, borders and margins - pos.left -= coffset.left + (parseInt(parent.css('borderLeftWidth'), 10) || 0) + (parseInt(parent.css('marginLeft'), 10) || 0); - pos.top -= coffset.top + (parseInt(parent.css('borderTopWidth'), 10) || 0) + (parseInt(parent.css('marginTop'), 10) || 0); + return adjusted; +}; +PLUGINS.imagemap = function(api, area, corner, adjustMethod) +{ + if(!area.jquery) { area = $(area); } - // If this is the first parent element with an overflow of "scroll" or "auto", store it - if(!scrolled && (overflow = parent.css('overflow')) !== 'hidden' && overflow !== 'visible') { scrolled = parent; } - } + var cache = (api.cache.areas = {}), + shape = (area[0].shape || area.attr('shape')).toLowerCase(), + coordsString = area[0].coords || area.attr('coords'), + baseCoords = coordsString.split(','), + coords = [], + image = $('img[usemap="#'+area.parent('map').attr('name')+'"]'), + imageOffset = image.offset(), + result = { + width: 0, height: 0, + position: { + top: 1e10, right: 0, + bottom: 0, left: 1e10 } - while((parent = $(parent[0].offsetParent)).length); + }, + i = 0, next = 0, dimensions; - // Compensate for containers scroll if it also has an offsetParent - if(scrolled && scrolled[0] !== docBody) { scroll( scrolled, 1 ); } - } + // POLY area coordinate calculator + // Special thanks to Ed Cradock for helping out with this. + // Uses a binary search algorithm to find suitable coordinates. + function polyCoordinates(result, coords, corner) + { + var i = 0, + compareX = 1, compareY = 1, + realX = 0, realY = 0, + newWidth = result.width, + newHeight = result.height; - return pos; - }, - - /* - * iOS 3.2 - 4.0 scroll fix detection used in offset() function. - */ - iOS: parseFloat( - ('' + (/CPU.*OS ([0-9_]{1,3})|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent) || [0,''])[1]) - .replace('undefined', '3_2').replace('_','.') - ) || FALSE, - - /* - * jQuery-specific $.fn overrides - */ - fn: { - /* Allow other plugins to successfully retrieve the title of an element with a qTip applied */ - attr: function(attr, val) { - if(this.length) { - var self = this[0], - title = 'title', - api = $.data(self, 'qtip'); - - if(attr === title && api && 'object' === typeof api && api.options.suppress) { - if(arguments.length < 2) { - return $.attr(self, oldtitle); - } - else { - // If qTip is rendered and title was originally used as content, update it - if(api && api.options.content.attr === title && api.cache.attr) { - api.set('content.text', val); - } - - // Use the regular attr method to set, then cache the result - return this.attr(oldtitle, val); - } - } - } + // Use a binary search algorithm to locate most suitable coordinate (hopefully) + while(newWidth > 0 && newHeight > 0 && compareX > 0 && compareY > 0) + { + newWidth = Math.floor(newWidth / 2); + newHeight = Math.floor(newHeight / 2); - return $.fn['attr'+replaceSuffix].apply(this, arguments); - }, + if(corner.x === LEFT){ compareX = newWidth; } + else if(corner.x === RIGHT){ compareX = result.width - newWidth; } + else{ compareX += Math.floor(newWidth / 2); } - /* Allow clone to correctly retrieve cached title attributes */ - clone: function(keepData) { - var titles = $([]), title = 'title', + if(corner.y === TOP){ compareY = newHeight; } + else if(corner.y === BOTTOM){ compareY = result.height - newHeight; } + else{ compareY += Math.floor(newHeight / 2); } - // Clone our element using the real clone method - elems = $.fn['clone'+replaceSuffix].apply(this, arguments); + i = coords.length; while(i--) + { + if(coords.length < 2){ break; } - // Grab all elements with an oldtitle set, and change it to regular title attribute, if keepData is false - if(!keepData) { - elems.filter('['+oldtitle+']').attr('title', function() { - return $.attr(this, oldtitle); - }) - .removeAttr(oldtitle); - } + realX = coords[i][0] - result.position.left; + realY = coords[i][1] - result.position.top; - return elems; + if((corner.x === LEFT && realX >= compareX) || + (corner.x === RIGHT && realX <= compareX) || + (corner.x === CENTER && (realX < compareX || realX > (result.width - compareX))) || + (corner.y === TOP && realY >= compareY) || + (corner.y === BOTTOM && realY <= compareY) || + (corner.y === CENTER && (realY < compareY || realY > (result.height - compareY)))) { + coords.splice(i, 1); + } + } } + + return { left: coords[0][0], top: coords[0][1] }; } -}; -// Apply the fn overrides above -$.each(PLUGINS.fn, function(name, func) { - if(!func || $.fn[name+replaceSuffix]) { return TRUE; } + // Make sure we account for padding and borders on the image + imageOffset.left += Math.ceil((image.outerWidth() - image.width()) / 2); + imageOffset.top += Math.ceil((image.outerHeight() - image.height()) / 2); - var old = $.fn[name+replaceSuffix] = $.fn[name]; - $.fn[name] = function() { - return func.apply(this, arguments) || old.apply(this, arguments); - }; -}); + // Parse coordinates into proper array + if(shape === 'poly') { + i = baseCoords.length; while(i--) + { + next = [ parseInt(baseCoords[--i], 10), parseInt(baseCoords[i+1], 10) ]; -/* Fire off 'removeqtip' handler in $.cleanData if jQuery UI not present (it already does similar). - * This snippet is taken directly from jQuery UI source code found here: - * http://code.jquery.com/ui/jquery-ui-git.js - */ -if(!$.ui) { - $['cleanData'+replaceSuffix] = $.cleanData; - $.cleanData = function( elems ) { - for(var i = 0, elem; (elem = elems[i]) !== undefined; i++) { - try { $( elem ).triggerHandler('removeqtip'); } - catch( e ) {} - } - $['cleanData'+replaceSuffix]( elems ); - }; -} + if(next[0] > result.position.right){ result.position.right = next[0]; } + if(next[0] < result.position.left){ result.position.left = next[0]; } + if(next[1] > result.position.bottom){ result.position.bottom = next[1]; } + if(next[1] < result.position.top){ result.position.top = next[1]; } -// Set global qTip properties -QTIP.version = '2.0.0pre'; -QTIP.nextid = 0; -QTIP.inactiveEvents = 'click dblclick mousedown mouseup mousemove mouseleave mouseenter'.split(' '); -QTIP.zindex = 15000; - -// Define configuration defaults -QTIP.defaults = { - prerender: FALSE, - id: FALSE, - overwrite: TRUE, - suppress: TRUE, - content: { - text: TRUE, - attr: 'title', - title: { - text: FALSE, - button: FALSE + coords.push(next); } - }, - position: { - my: 'top left', - at: 'bottom right', - target: FALSE, - container: FALSE, - viewport: FALSE, - adjust: { - x: 0, y: 0, - mouse: TRUE, - resize: TRUE, - method: 'flip flip' - }, - effect: function(api, pos, viewport) { - $(this).animate(pos, { - duration: 200, - queue: FALSE - }); + } + else { + i = -1; while(i++ < baseCoords.length) { + coords.push( parseInt(baseCoords[i], 10) ); } - }, - show: { - target: FALSE, - event: 'mouseenter', - effect: TRUE, - delay: 90, - solo: FALSE, - ready: FALSE, - autofocus: FALSE - }, - hide: { - target: FALSE, - event: 'mouseleave', - effect: TRUE, - delay: 0, - fixed: FALSE, - inactive: FALSE, - leave: 'window', - distance: FALSE - }, - style: { - classes: '', - widget: FALSE, - width: FALSE, - height: FALSE, - def: TRUE - }, - events: { - render: NULL, - move: NULL, - show: NULL, - hide: NULL, - toggle: NULL, - visible: NULL, - hidden: NULL, - focus: NULL, - blur: NULL } -}; -function Ajax(api) -{ - var self = this, - tooltip = api.elements.tooltip, - opts = api.options.content.ajax, - defaults = QTIP.defaults.content.ajax, - namespace = '.qtip-ajax', - rscript = /)<[^<]*)*<\/script>/gi, - first = TRUE, - stop = FALSE, - xhr; + // Calculate details + switch(shape) + { + case 'rect': + result = { + width: Math.abs(coords[2] - coords[0]), + height: Math.abs(coords[3] - coords[1]), + position: { + left: Math.min(coords[0], coords[2]), + top: Math.min(coords[1], coords[3]) + } + }; + break; - api.checks.ajax = { - '^content.ajax': function(obj, name, v) { - // If content.ajax object was reset, set our local var - if(name === 'ajax') { opts = v; } + case 'circle': + result = { + width: coords[2] + 2, + height: coords[2] + 2, + position: { left: coords[0], top: coords[1] } + }; + break; - if(name === 'once') { - self.init(); - } - else if(opts && opts.url) { - self.load(); + case 'poly': + result.width = Math.abs(result.position.right - result.position.left); + result.height = Math.abs(result.position.bottom - result.position.top); + + if(corner.abbrev() === 'c') { + result.position = { + left: result.position.left + (result.width / 2), + top: result.position.top + (result.height / 2) + }; } else { - tooltip.unbind(namespace); - } - } - }; + // Calculate if we can't find a cached value + if(!cache[corner+coordsString]) { + result.position = polyCoordinates(result, coords.slice(), corner); + + // If flip adjustment is enabled, also calculate the closest opposite point + if(adjustMethod && (adjustMethod[0] === 'flip' || adjustMethod[1] === 'flip')) { + result.offset = polyCoordinates(result, coords.slice(), { + x: corner.x === LEFT ? RIGHT : corner.x === RIGHT ? LEFT : CENTER, + y: corner.y === TOP ? BOTTOM : corner.y === BOTTOM ? TOP : CENTER + }); - $.extend(self, { - init: function() { - // Make sure ajax options are enabled and bind event - if(opts && opts.url) { - tooltip.unbind(namespace)[ opts.once ? 'one' : 'bind' ]('tooltipshow'+namespace, self.load); - } + result.offset.left -= result.position.left; + result.offset.top -= result.position.top; + } - return self; - }, + // Store the result + cache[corner+coordsString] = result; + } - load: function(event) { - if(stop) {stop = FALSE; return; } + // Grab the cached result + result = cache[corner+coordsString]; + } - var hasSelector = opts.url.indexOf(' '), - url = opts.url, - selector, - hideFirst = !opts.loading && first; + result.width = result.height = 0; + break; + } - // If loading option is disabled, prevent the tooltip showing until we've completed the request - if(hideFirst) { try{ event.preventDefault(); } catch(e) {} } + // Add image position to offset coordinates + result.position.left += imageOffset.left; + result.position.top += imageOffset.top; - // Make sure default event hasn't been prevented - else if(event && event.isDefaultPrevented()) { return self; } + return result; +}; - // Cancel old request - if(xhr && xhr.abort) { xhr.abort(); } - - // Check if user delcared a content selector like in .load() - if(hasSelector > -1) { - selector = url.substr(hasSelector); - url = url.substr(0, hasSelector); - } - // Define common after callback for both success/error handlers - function after() { - var complete; +/* + * BGIFrame adaption (http://plugins.jquery.com/project/bgiframe) + * Special thanks to Brandon Aaron + */ +function IE6(api) +{ + var self = this, + elems = api.elements, + options = api.options, + tooltip = elems.tooltip, + namespace = '.ie6-' + api.id, + bgiframe = $('select, object').length < 1, + isDrawing = 0, + modalProcessed = FALSE, + redrawContainer; - // Don't proceed if tooltip is destroyed - if(api.destroyed) { return; } + api.checks.ie6 = { + '^content|style$': function(obj, o, v){ redraw(); } + }; - // Set first flag to false - first = FALSE; + $.extend(self, { + init: function() + { + var win = $(window), scroll; - // Re-display tip if loading and first time, and reset first flag - if(hideFirst) { stop = TRUE; api.show(event.originalEvent); } + // Create the BGIFrame element if needed + if(bgiframe) { + elems.bgiframe = $(''); - // Call users complete method if it was defined - if((complete = defaults.complete || opts.complete) && $.isFunction(complete)) { - complete.apply(opts.context || api, arguments); - } - } + // Append the new element to the tooltip + elems.bgiframe.appendTo(tooltip); - // Define success handler - function successHandler(content, status, jqXHR) { - var success; + // Update BGIFrame on tooltip move + tooltip.bind('tooltipmove'+namespace, self.adjustBGIFrame); + } - // Don't proceed if tooltip is destroyed - if(api.destroyed) { return; } + // redraw() container for width/height calculations + redrawContainer = $('
', { id: 'qtip-rcontainer' }) + .appendTo(document.body); - if(selector) { - // Create a dummy div to hold the results and grab the selector element - content = $('
') - // inject the contents of the document in, removing the scripts - // to avoid any 'Permission Denied' errors in IE - .append(content.replace(rscript, "")) - - // Locate the specified elements - .find(selector); - } + // Set dimensions + self.redraw(); - // Call the success function if one is defined - if((success = defaults.success || opts.success) && $.isFunction(success)) { - success.call(opts.context || api, content, status, jqXHR); - } + // Fixup modal plugin if present too + if(elems.overlay && !modalProcessed) { + scroll = function() { + elems.overlay[0].style.top = win.scrollTop() + 'px'; + }; + win.bind('scroll.qtip-ie6, resize.qtip-ie6', scroll); + scroll(); // Fire it initially too - // Otherwise set the content - else { api.set('content.text', content); } - } + elems.overlay.addClass('qtipmodal-ie6fix'); // Add fix class - // Error handler - function errorHandler(xhr, status, error) { - if(api.destroyed || xhr.status === 0) { return; } - api.set('content.text', status + ': ' + error); + modalProcessed = TRUE; // Set flag } - - // Setup $.ajax option object and process the request - xhr = $.ajax( - $.extend({ - error: defaults.error || errorHandler, - context: api - }, - opts, { url: url, success: successHandler, complete: after }) - ); }, - destroy: function() { - // Cancel ajax request if possible - if(xhr && xhr.abort) { xhr.abort(); } - - // Set api.destroyed flag - api.destroyed = TRUE; - } - }); - - self.init(); -} - - -PLUGINS.ajax = function(api) -{ - var self = api.plugins.ajax; - - return 'object' === typeof self ? self : (api.plugins.ajax = new Ajax(api)); -}; - -PLUGINS.ajax.initialize = 'render'; - -// Setup plugin sanitization -PLUGINS.ajax.sanitize = function(options) -{ - var content = options.content, opts; - if(content && 'ajax' in content) { - opts = content.ajax; - if(typeof opts !== 'object') { opts = options.content.ajax = { url: opts }; } - if('boolean' !== typeof opts.once && opts.once) { opts.once = !!opts.once; } - } -}; - -// Extend original api defaults -$.extend(TRUE, QTIP.defaults, { - content: { - ajax: { - loading: TRUE, - once: TRUE - } - } -}); - -/* - * BGIFrame adaption (http://plugins.jquery.com/project/bgiframe) - * Special thanks to Brandon Aaron - */ -function BGIFrame(api) -{ - var self = this, - elems = api.elements, - tooltip = elems.tooltip, - namespace = '.bgiframe-' + api.id; - - $.extend(self, { - init: function() - { - // Create the BGIFrame element - elems.bgiframe = $(''); - - // Append the new element to the tooltip - elems.bgiframe.appendTo(tooltip); - - // Update BGIFrame on tooltip move - tooltip.bind('tooltipmove'+namespace, self.adjust); - }, - - adjust: function() - { - var dimensions = api.get('dimensions'), // Determine current tooltip dimensions - plugin = api.plugins.tip, - tip = elems.tip, - tipAdjust, offset; + adjustBGIFrame: function() + { + var dimensions = api.get('dimensions'), // Determine current tooltip dimensions + plugin = api.plugins.tip, + tip = elems.tip, + tipAdjust, offset; // Adjust border offset offset = parseInt(tooltip.css('border-left-width'), 10) || 0; @@ -2207,1131 +3323,82 @@ function BGIFrame(api) elems.bgiframe.css(offset).css(dimensions); }, - destroy: function() + // Max/min width simulator function + redraw: function() { - // Remove iframe - elems.bgiframe.remove(); - - // Remove bound events - tooltip.unbind(namespace); - } - }); - - self.init(); -} - -PLUGINS.bgiframe = function(api) -{ - var browser = $.browser, - self = api.plugins.bgiframe; - - // Proceed only if the browser is IE6 and offending elements are present - if($('select, object').length < 1 || !(browser.msie && (''+browser.version).charAt(0) === '6')) { - return FALSE; - } - - return 'object' === typeof self ? self : (api.plugins.bgiframe = new BGIFrame(api)); -}; - -// Plugin needs to be initialized on render -PLUGINS.bgiframe.initialize = 'render'; + if(api.rendered < 1 || isDrawing) { return self; } -PLUGINS.imagemap = function(area, corner, flip) -{ - if(!area.jquery) { area = $(area); } + var style = options.style, + container = options.position.container, + perc, width, max, min; - var shape = (area[0].shape || area.attr('shape')).toLowerCase(), - baseCoords = (area[0].coords || area.attr('coords')).split(','), - coords = [], - image = $('img[usemap="#'+area.parent('map').attr('name')+'"]'), - imageOffset = image.offset(), - result = { - width: 0, height: 0, - offset: { top: 1e10, right: 0, bottom: 0, left: 1e10 } - }, - i = 0, next = 0, dimensions; + // Set drawing flag + isDrawing = 1; - // POLY area coordinate calculator - // Special thanks to Ed Cradock for helping out with this. - // Uses a binary search algorithm to find suitable coordinates. - function polyCoordinates(result, coords, corner) - { - var i = 0, - compareX = 1, compareY = 1, - realX = 0, realY = 0, - newWidth = result.width, - newHeight = result.height; + // If tooltip has a set height/width, just set it... like a boss! + if(style.height) { tooltip.css(HEIGHT, style.height); } + if(style.width) { tooltip.css(WIDTH, style.width); } - // Use a binary search algorithm to locate most suitable coordinate (hopefully) - while(newWidth > 0 && newHeight > 0 && compareX > 0 && compareY > 0) - { - newWidth = Math.floor(newWidth / 2); - newHeight = Math.floor(newHeight / 2); + // Simulate max/min width if not set width present... + else { + // Reset width and add fluid class + tooltip.css(WIDTH, '').appendTo(redrawContainer); - if(corner.x === 'left'){ compareX = newWidth; } - else if(corner.x === 'right'){ compareX = result.width - newWidth; } - else{ compareX += Math.floor(newWidth / 2); } + // Grab our tooltip width (add 1 if odd so we don't get wrapping problems.. huzzah!) + width = tooltip.width(); + if(width % 2 < 1) { width += 1; } - if(corner.y === 'top'){ compareY = newHeight; } - else if(corner.y === 'bottom'){ compareY = result.height - newHeight; } - else{ compareY += Math.floor(newHeight / 2); } + // Grab our max/min properties + max = tooltip.css('max-width') || ''; + min = tooltip.css('min-width') || ''; - i = coords.length; while(i--) - { - if(coords.length < 2){ break; } + // Parse into proper pixel values + perc = (max + min).indexOf('%') > -1 ? container.width() / 100 : 0; + max = ((max.indexOf('%') > -1 ? perc : 1) * parseInt(max, 10)) || width; + min = ((min.indexOf('%') > -1 ? perc : 1) * parseInt(min, 10)) || 0; - realX = coords[i][0] - result.offset.left; - realY = coords[i][1] - result.offset.top; + // Determine new dimension size based on max/min/current values + width = max + min ? Math.min(Math.max(width, min), max) : width; - if((corner.x === 'left' && realX >= compareX) || - (corner.x === 'right' && realX <= compareX) || - (corner.x === 'center' && (realX < compareX || realX > (result.width - compareX))) || - (corner.y === 'top' && realY >= compareY) || - (corner.y === 'bottom' && realY <= compareY) || - (corner.y === 'center' && (realY < compareY || realY > (result.height - compareY)))) { - coords.splice(i, 1); - } + // Set the newly calculated width and remvoe fluid class + tooltip.css(WIDTH, Math.round(width)).appendTo(container); } - } - return { left: coords[0][0], top: coords[0][1] }; - } + // Set drawing flag + isDrawing = 0; - // Make sure we account for padding and borders on the image - imageOffset.left += Math.ceil((image.outerWidth() - image.width()) / 2); - imageOffset.top += Math.ceil((image.outerHeight() - image.height()) / 2); + return self; + }, - // Parse coordinates into proper array - if(shape === 'poly') { - i = baseCoords.length; while(i--) + destroy: function() { - next = [ parseInt(baseCoords[--i], 10), parseInt(baseCoords[i+1], 10) ]; - - if(next[0] > result.offset.right){ result.offset.right = next[0]; } - if(next[0] < result.offset.left){ result.offset.left = next[0]; } - if(next[1] > result.offset.bottom){ result.offset.bottom = next[1]; } - if(next[1] < result.offset.top){ result.offset.top = next[1]; } + // Remove iframe + if(bgiframe) { elems.bgiframe.remove(); } - coords.push(next); + // Remove bound events + tooltip.unbind(namespace); } - } - else { - coords = $.map(baseCoords, function(coord){ return parseInt(coord, 10); }); - } - - // Calculate details - switch(shape) - { - case 'rect': - result = { - width: Math.abs(coords[2] - coords[0]), - height: Math.abs(coords[3] - coords[1]), - offset: { - left: Math.min(coords[0], coords[2]), - top: Math.min(coords[1], coords[3]) - } - }; - break; - - case 'circle': - result = { - width: coords[2] + 2, - height: coords[2] + 2, - offset: { left: coords[0], top: coords[1] } - }; - break; - - case 'poly': - $.extend(result, { - width: Math.abs(result.offset.right - result.offset.left), - height: Math.abs(result.offset.bottom - result.offset.top) - }); - - if(corner.string() === 'centercenter') { - result.offset = { - left: result.offset.left + (result.width / 2), - top: result.offset.top + (result.height / 2) - }; - } - else { - result.offset = polyCoordinates(result, coords.slice(), corner); - - // If flip adjustment is enabled, also calculate the closest opposite point - if(flip && (flip[0] === 'flip' || flip[1] === 'flip')) { - result.flipoffset = polyCoordinates(result, coords.slice(), { - x: corner.x === 'left' ? 'right' : corner.x === 'right' ? 'left' : 'center', - y: corner.y === 'top' ? 'bottom' : corner.y === 'bottom' ? 'top' : 'center' - }); + }); - result.flipoffset.left -= result.offset.left; - result.flipoffset.top -= result.offset.top; - } - } + self.init(); +} - result.width = result.height = 0; - break; +PLUGINS.ie6 = function(api) +{ + var browser = $.browser, + self = api.plugins.ie6; + + // Proceed only if the browser is IE6 + if(!(browser.msie && (''+browser.version).charAt(0) === '6')) { + return FALSE; } - // Add image position to offset coordinates - result.offset.left += imageOffset.left; - result.offset.top += imageOffset.top; - - return result; -}; - -function Modal(api) -{ - var self = this, - options = api.options.show.modal, - elems = api.elements, - tooltip = elems.tooltip, - overlaySelector = '#qtip-overlay', - globalNamespace = '.qtipmodal', - namespace = globalNamespace + api.id, - attr = 'is-modal-qtip', - docBody = $(document.body), - overlay; - - // Setup option set checks - api.checks.modal = { - '^show.modal.(on|blur)$': function() { - // Initialise - self.init(); - - // Show the modal if not visible already and tooltip is visible - elems.overlay.toggle( tooltip.is(':visible') ); - } - }; - - $.extend(self, { - init: function() - { - // If modal is disabled... return - if(!options.on) { return self; } - - // Create the overlay if needed - overlay = self.create(); - - // Add unique attribute so we can grab modal tooltips easily via a selector - tooltip.attr(attr, TRUE) - - // Set z-index - .css('z-index', PLUGINS.modal.zindex + $(selector+'['+attr+']').length) - - // Remove previous bound events in globalNamespace - .unbind(globalNamespace).unbind(namespace) - - // Apply our show/hide/focus modal events - .bind('tooltipshow'+globalNamespace+' tooltiphide'+globalNamespace, function(event, api, duration) { - var oEvent = event.originalEvent; - - // Make sure mouseout doesn't trigger a hide when showing the modal and mousing onto backdrop - if(event.target === tooltip[0]) { - if(oEvent && event.type === 'tooltiphide' && /mouse(leave|enter)/.test(oEvent.type) && $(oEvent.relatedTarget).closest(overlay[0]).length) { - try { event.preventDefault(); } catch(e) {} - } - else if(!oEvent || (oEvent && !oEvent.solo)) { - self[ event.type.replace('tooltip', '') ](event, duration); - } - } - }) - - // Adjust modal z-index on tooltip focus - .bind('tooltipfocus'+globalNamespace, function(event) { - // If focus was cancelled before it reearch us, don't do anything - if(event.isDefaultPrevented() || event.target !== tooltip[0]) { return; } - - var qtips = $(selector).filter('['+attr+']'), - - // Keep the modal's lower than other, regular qtips - newIndex = PLUGINS.modal.zindex + qtips.length, - curIndex = parseInt(tooltip[0].style.zIndex, 10); - - // Set overlay z-index - overlay[0].style.zIndex = newIndex - 1; - - // Reduce modal z-index's and keep them properly ordered - qtips.each(function() { - if(this.style.zIndex > curIndex) { - this.style.zIndex -= 1; - } - }); - - // Fire blur event for focused tooltip - qtips.end().filter('.' + focusClass).qtip('blur', event.originalEvent); - - // Set the new z-index - tooltip.addClass(focusClass)[0].style.zIndex = newIndex; - - // Prevent default handling - try { event.preventDefault(); } catch(e) {} - }) - - // Focus any other visible modals when this one hides - .bind('tooltiphide'+globalNamespace, function(event) { - if(event.target === tooltip[0]) { - $('[' + attr + ']').filter(':visible').not(tooltip).last().qtip('focus', event); - } - }); - - // Apply keyboard "Escape key" close handler - if(options.escape) { - $(window).unbind(namespace).bind('keydown'+namespace, function(event) { - if(event.keyCode === 27 && tooltip.hasClass(focusClass)) { - api.hide(event); - } - }); - } - - // Apply click handler for blur option - if(options.blur) { - elems.overlay.unbind(namespace).bind('click'+namespace, function(event) { - if(tooltip.hasClass(focusClass)) { api.hide(event); } - }); - } - - return self; - }, - - create: function() - { - var elem = $(overlaySelector); - - // Return if overlay is already rendered - if(elem.length) { - // Modal overlay should always be below all tooltips if possible - return (elems.overlay = elem.insertAfter( $(selector).last() )); - } - - // Create document overlay - overlay = elems.overlay = $('
', { - id: overlaySelector.substr(1), - html: '
', - mousedown: function() { return FALSE; } - }) - .insertAfter( $(selector).last() ); - - // Update position on window resize or scroll - function resize() { - overlay.css({ - height: $(window).height(), - width: $(window).width() - }); - } - $(window).unbind(globalNamespace).bind('resize'+globalNamespace, resize); - resize(); // Fire it initially too - - return overlay; - }, - - toggle: function(event, state, duration) - { - // Make sure default event hasn't been prevented - if(event && event.isDefaultPrevented()) { return self; } - - var effect = options.effect, - type = state ? 'show': 'hide', - visible = overlay.is(':visible'), - modals = $('[' + attr + ']').filter(':visible').not(tooltip), - zindex; - - // Create our overlay if it isn't present already - if(!overlay) { overlay = self.create(); } - - // Prevent modal from conflicting with show.solo, and don't hide backdrop is other modals are visible - if((overlay.is(':animated') && visible === state) || (!state && modals.length)) { return self; } - - // State specific... - if(state) { - // Set position - overlay.css({ left: 0, top: 0 }); - - // Toggle backdrop cursor style on show - overlay.toggleClass('blurs', options.blur); - - // Make sure we can't focus anything outside the tooltip - docBody.bind('focusin'+namespace, function(event) { - var target = $(event.target), - container = target.closest('.qtip'), - - // Determine if input container target is above this - targetOnTop = container.length < 1 ? FALSE : - (parseInt(container[0].style.zIndex, 10) > parseInt(tooltip[0].style.zIndex, 10)); - - // If we're showing a modal, but focus has landed on an input below - // this modal, divert focus to the first visible input in this modal - if(!targetOnTop && ($(event.target).closest(selector)[0] !== tooltip[0])) { - tooltip.find('input:visible').filter(':first').focus(); - } - }); - } - else { - // Undelegate focus handler - docBody.undelegate('*', 'focusin'+namespace); - } - - // Stop all animations - overlay.stop(TRUE, FALSE); - - // Use custom function if provided - if($.isFunction(effect)) { - effect.call(overlay, state); - } - - // If no effect type is supplied, use a simple toggle - else if(effect === FALSE) { - overlay[ type ](); - } - - // Use basic fade function - else { - overlay.fadeTo( parseInt(duration, 10) || 90, state ? 1 : 0, function() { - if(!state) { $(this).hide(); } - }); - } - - // Reset position on hide - if(!state) { - overlay.queue(function(next) { - overlay.css({ left: '', top: '' }); - next(); - }); - } - - return self; - }, - - show: function(event, duration) { return self.toggle(event, TRUE, duration); }, - hide: function(event, duration) { return self.toggle(event, FALSE, duration); }, - - destroy: function() - { - var delBlanket = overlay; - - if(delBlanket) { - // Check if any other modal tooltips are present - delBlanket = $('[' + attr + ']').not(tooltip).length < 1; - - // Remove overlay if needed - if(delBlanket) { - elems.overlay.remove(); - $(window).unbind(globalNamespace); - } - else { - elems.overlay.unbind(globalNamespace+api.id); - } - - // Undelegate focus handler - docBody.undelegate('*', 'focusin'+namespace); - } - - // Remove bound events - return tooltip.removeAttr(attr).unbind(globalNamespace); - } - }); - - self.init(); -} - -PLUGINS.modal = function(api) { - var self = api.plugins.modal; - - return 'object' === typeof self ? self : (api.plugins.modal = new Modal(api)); + return 'object' === typeof self ? self : (api.plugins.ie6 = new IE6(api)); }; // Plugin needs to be initialized on render -PLUGINS.modal.initialize = 'render'; - -// Setup sanitiztion rules -PLUGINS.modal.sanitize = function(opts) { - if(opts.show) { - if(typeof opts.show.modal !== 'object') { opts.show.modal = { on: !!opts.show.modal }; } - else if(typeof opts.show.modal.on === 'undefined') { opts.show.modal.on = TRUE; } - } -}; - -// Base z-index for all modal tooltips (use qTip core z-index as a base) -PLUGINS.modal.zindex = QTIP.zindex + 1000; - -// Extend original api defaults -$.extend(TRUE, QTIP.defaults, { - show: { - modal: { - on: FALSE, - effect: TRUE, - blur: TRUE, - escape: TRUE - } - } -}); - -PLUGINS.svg = function(svg, corner) -{ - var doc = $(document), - elem = svg[0], - result = { - width: 0, height: 0, - offset: { top: 1e10, left: 1e10 } - }, - box, mtx, root, point, tPoint; - - if (elem.getBBox && elem.parentNode) { - box = elem.getBBox(); - mtx = elem.getScreenCTM(); - root = elem.farthestViewportElement || elem; - - // Return if no method is found - if(!root.createSVGPoint) { return result; } - - // Create our point var - point = root.createSVGPoint(); - - // Adjust top and left - point.x = box.x; - point.y = box.y; - tPoint = point.matrixTransform(mtx); - result.offset.left = tPoint.x; - result.offset.top = tPoint.y; - - // Adjust width and height - point.x += box.width; - point.y += box.height; - tPoint = point.matrixTransform(mtx); - result.width = tPoint.x - result.offset.left; - result.height = tPoint.y - result.offset.top; - - // Adjust by scroll offset - result.offset.left += doc.scrollLeft(); - result.offset.top += doc.scrollTop(); - } - - return result; -}; - -// Tip coordinates calculator -function calculateTip(corner, width, height) -{ - var width2 = Math.ceil(width / 2), height2 = Math.ceil(height / 2), - - // Define tip coordinates in terms of height and width values - tips = { - bottomright: [[0,0], [width,height], [width,0]], - bottomleft: [[0,0], [width,0], [0,height]], - topright: [[0,height], [width,0], [width,height]], - topleft: [[0,0], [0,height], [width,height]], - topcenter: [[0,height], [width2,0], [width,height]], - bottomcenter: [[0,0], [width,0], [width2,height]], - rightcenter: [[0,0], [width,height2], [0,height]], - leftcenter: [[width,0], [width,height], [0,height2]] - }; - - // Set common side shapes - tips.lefttop = tips.bottomright; tips.righttop = tips.bottomleft; - tips.leftbottom = tips.topright; tips.rightbottom = tips.topleft; - - return tips[ corner.string() ]; -} - - -function Tip(qTip, command) -{ - var self = this, - opts = qTip.options.style.tip, - elems = qTip.elements, - tooltip = elems.tooltip, - cache = { top: 0, left: 0 }, - size = { - width: opts.width, - height: opts.height - }, - color = { }, - border = opts.border || 0, - namespace = '.qtip-tip', - hasCanvas = !!($('')[0] || {}).getContext; - - self.corner = NULL; - self.mimic = NULL; - self.border = border; - self.offset = opts.offset; - self.size = size; - - // Add new option checks for the plugin - qTip.checks.tip = { - '^position.my|style.tip.(corner|mimic|border)$': function() { - // Make sure a tip can be drawn - if(!self.init()) { - self.destroy(); - } - - // Reposition the tooltip - qTip.reposition(); - }, - '^style.tip.(height|width)$': function() { - // Re-set dimensions and redraw the tip - size = { - width: opts.width, - height: opts.height - }; - self.create(); - self.update(); - - // Reposition the tooltip - qTip.reposition(); - }, - '^content.title.text|style.(classes|widget)$': function() { - if(elems.tip && elems.tip.length) { - self.update(); - } - } - }; - - function swapDimensions() { - var temp = size.width; - size.width = size.height; - size.height = temp; - } - - function resetDimensions() { - size.width = opts.width; - size.height = opts.height; - } - - function reposition(event, api, pos, viewport) { - if(!elems.tip) { return; } - - var newCorner = self.corner.clone(), - adjust = pos.adjusted, - method = qTip.options.position.adjust.method.split(' '), - horizontal = method[0], - vertical = method[1] || method[0], - shift = { left: FALSE, top: FALSE, x: 0, y: 0 }, - offset, css = {}, props; - - // Make sure our tip position isn't fixed e.g. doesn't adjust with viewport - if(self.corner.fixed !== TRUE) { - // Horizontal - Shift or flip method - if(horizontal === 'shift' && newCorner.precedance === 'x' && adjust.left && newCorner.y !== 'center') { - newCorner.precedance = newCorner.precedance === 'x' ? 'y' : 'x'; - } - else if(horizontal !== 'shift' && adjust.left){ - newCorner.x = newCorner.x === 'center' ? (adjust.left > 0 ? 'left' : 'right') : (newCorner.x === 'left' ? 'right' : 'left'); - } - - // Vertical - Shift or flip method - if(vertical === 'shift' && newCorner.precedance === 'y' && adjust.top && newCorner.x !== 'center') { - newCorner.precedance = newCorner.precedance === 'y' ? 'x' : 'y'; - } - else if(vertical !== 'shift' && adjust.top) { - newCorner.y = newCorner.y === 'center' ? (adjust.top > 0 ? 'top' : 'bottom') : (newCorner.y === 'top' ? 'bottom' : 'top'); - } - - // Update and redraw the tip if needed (check cached details of last drawn tip) - if(newCorner.string() !== cache.corner.string() && (cache.top !== adjust.top || cache.left !== adjust.left)) { - self.update(newCorner, FALSE); - } - } - - // Setup tip offset properties - offset = self.position(newCorner, adjust); - if(offset.right !== undefined) { offset.left = -offset.right; } - if(offset.bottom !== undefined) { offset.top = -offset.bottom; } - offset.user = Math.max(0, opts.offset); - - // Viewport "shift" specific adjustments - if(shift.left = (horizontal === 'shift' && !!adjust.left)) { - if(newCorner.x === 'center') { - css['margin-left'] = shift.x = offset['margin-left'] - adjust.left; - } - else { - props = offset.right !== undefined ? - [ adjust.left, -offset.left ] : [ -adjust.left, offset.left ]; - - if( (shift.x = Math.max(props[0], props[1])) > props[0] ) { - pos.left -= adjust.left; - shift.left = FALSE; - } - - css[ offset.right !== undefined ? 'right' : 'left' ] = shift.x; - } - } - if(shift.top = (vertical === 'shift' && !!adjust.top)) { - if(newCorner.y === 'center') { - css['margin-top'] = shift.y = offset['margin-top'] - adjust.top; - } - else { - props = offset.bottom !== undefined ? - [ adjust.top, -offset.top ] : [ -adjust.top, offset.top ]; - - if( (shift.y = Math.max(props[0], props[1])) > props[0] ) { - pos.top -= adjust.top; - shift.top = FALSE; - } - - css[ offset.bottom !== undefined ? 'bottom' : 'top' ] = shift.y; - } - } - - /* - * If the tip is adjusted in both dimensions, or in a - * direction that would cause it to be anywhere but the - * outer border, hide it! - */ - elems.tip.css(css).toggle( - !((shift.x && shift.y) || (newCorner.x === 'center' && shift.y) || (newCorner.y === 'center' && shift.x)) - ); - - // Adjust position to accomodate tip dimensions - pos.left -= offset.left.charAt ? offset.user : horizontal !== 'shift' || shift.top || !shift.left && !shift.top ? offset.left : 0; - pos.top -= offset.top.charAt ? offset.user : vertical !== 'shift' || shift.left || !shift.left && !shift.top ? offset.top : 0; - - // Cache details - cache.left = adjust.left; cache.top = adjust.top; - cache.corner = newCorner.clone(); - } - - /* border width calculator */ - function borderWidth(corner, side, backup) { - side = !side ? corner[corner.precedance] : side; - - var isFluid = tooltip.hasClass(fluidClass), - isTitleTop = elems.titlebar && corner.y === 'top', - elem = isTitleTop ? elems.titlebar : elems.content, - css = 'border-' + side + '-width', - val; - - // Grab the border-width value (add fluid class if needed) - tooltip.addClass(fluidClass); - val = parseInt(elem.css(css), 10); - val = (backup ? val || parseInt(tooltip.css(css), 10) : val) || 0; - tooltip.toggleClass(fluidClass, isFluid); - - return val; - } - - function borderRadius(corner) { - var isTitleTop = elems.titlebar && corner.y === 'top', - elem = isTitleTop ? elems.titlebar : elems.content, - moz = $.browser.mozilla, - prefix = moz ? '-moz-' : $.browser.webkit ? '-webkit-' : '', - side = corner.y + (moz ? '' : '-') + corner.x, - css = prefix + (moz ? 'border-radius-' + side : 'border-' + side + '-radius'); - - return parseInt(elem.css(css), 10) || parseInt(tooltip.css(css), 10) || 0; - } - - function calculateSize(corner) { - var y = corner.precedance === 'y', - width = size [ y ? 'width' : 'height' ], - height = size [ y ? 'height' : 'width' ], - isCenter = corner.string().indexOf('center') > -1, - base = width * (isCenter ? 0.5 : 1), - pow = Math.pow, - round = Math.round, - bigHyp, ratio, result, - - smallHyp = Math.sqrt( pow(base, 2) + pow(height, 2) ), - - hyp = [ - (border / base) * smallHyp, (border / height) * smallHyp - ]; - hyp[2] = Math.sqrt( pow(hyp[0], 2) - pow(border, 2) ); - hyp[3] = Math.sqrt( pow(hyp[1], 2) - pow(border, 2) ); - - bigHyp = smallHyp + hyp[2] + hyp[3] + (isCenter ? 0 : hyp[0]); - ratio = bigHyp / smallHyp; - - result = [ round(ratio * height), round(ratio * width) ]; - return { height: result[ y ? 0 : 1 ], width: result[ y ? 1 : 0 ] }; - } - - $.extend(self, { - init: function() - { - var enabled = self.detectCorner() && (hasCanvas || $.browser.msie); - - // Determine tip corner and type - if(enabled) { - // Create a new tip and draw it - self.create(); - self.update(); - - // Bind update events - tooltip.unbind(namespace).bind('tooltipmove'+namespace, reposition); - } - - return enabled; - }, - - detectCorner: function() - { - var corner = opts.corner, - posOptions = qTip.options.position, - at = posOptions.at, - my = posOptions.my.string ? posOptions.my.string() : posOptions.my; - - // Detect corner and mimic properties - if(corner === FALSE || (my === FALSE && at === FALSE)) { - return FALSE; - } - else { - if(corner === TRUE) { - self.corner = new PLUGINS.Corner(my); - } - else if(!corner.string) { - self.corner = new PLUGINS.Corner(corner); - self.corner.fixed = TRUE; - } - } - - // Cache it - cache.corner = new PLUGINS.Corner( self.corner.string() ); - - return self.corner.string() !== 'centercenter'; - }, - - detectColours: function(actual) { - var i, fill, border, - tip = elems.tip.css('cssText', ''), - corner = actual || self.corner, - precedance = corner[ corner.precedance ], - - borderSide = 'border-' + precedance + '-color', - borderSideCamel = 'border' + precedance.charAt(0) + precedance.substr(1) + 'Color', - - invalid = /rgba?\(0, 0, 0(, 0)?\)|transparent|#123456/i, - backgroundColor = 'background-color', - transparent = 'transparent', - important = ' !important', - - bodyBorder = $(document.body).css('color'), - contentColour = qTip.elements.content.css('color'), - - useTitle = elems.titlebar && (corner.y === 'top' || (corner.y === 'center' && tip.position().top + (size.height / 2) + opts.offset < elems.titlebar.outerHeight(1))), - colorElem = useTitle ? elems.titlebar : elems.content; - - // Apply the fluid class so we can see our CSS values properly - tooltip.addClass(fluidClass); - - // Detect tip colours from CSS styles - color.fill = fill = tip.css(backgroundColor); - color.border = border = tip[0].style[ borderSideCamel ] || tip.css(borderSide) || tooltip.css(borderSide); - - // Make sure colours are valid - if(!fill || invalid.test(fill)) { - color.fill = colorElem.css(backgroundColor) || transparent; - if(invalid.test(color.fill)) { - color.fill = tooltip.css(backgroundColor) || fill; - } - } - if(!border || invalid.test(border) || border === bodyBorder) { - color.border = colorElem.css(borderSide) || transparent; - if(invalid.test(color.border)) { - color.border = border; - } - } - - // Reset background and border colours - $('*', tip).add(tip).css('cssText', backgroundColor+':'+transparent+important+';border:0'+important+';'); - - // Remove fluid class - tooltip.removeClass(fluidClass); - }, - - create: function() - { - var width = size.width, - height = size.height, - vml; - - // Remove previous tip element if present - if(elems.tip) { elems.tip.remove(); } - - // Create tip element and prepend to the tooltip - elems.tip = $('
', { 'class': 'ui-tooltip-tip' }).css({ width: width, height: height }).prependTo(tooltip); - - // Create tip drawing element(s) - if(hasCanvas) { - // save() as soon as we create the canvas element so FF2 doesn't bork on our first restore()! - $('').appendTo(elems.tip)[0].getContext('2d').save(); - } - else { - vml = ''; - elems.tip.html(vml + vml); - - // Prevent mousing down on the tip since it causes problems with .live() handling in IE due to VML - $('*', elems.tip).bind('click mousedown', function(event) { event.stopPropagation(); }); - } - }, - - update: function(corner, position) - { - var tip = elems.tip, - inner = tip.children(), - width = size.width, - height = size.height, - regular = 'px solid ', - transparent = 'px dashed transparent', // Dashed IE6 border-transparency hack. Awesome! - mimic = opts.mimic, - round = Math.round, - precedance, context, coords, translate, newSize; - - // Re-determine tip if not already set - if(!corner) { corner = cache.corner || self.corner; } - - // Use corner property if we detect an invalid mimic value - if(mimic === FALSE) { mimic = corner; } - - // Otherwise inherit mimic properties from the corner object as necessary - else { - mimic = new PLUGINS.Corner(mimic); - mimic.precedance = corner.precedance; - - if(mimic.x === 'inherit') { mimic.x = corner.x; } - else if(mimic.y === 'inherit') { mimic.y = corner.y; } - else if(mimic.x === mimic.y) { - mimic[ corner.precedance ] = corner[ corner.precedance ]; - } - } - precedance = mimic.precedance; - - // Ensure the tip width.height are relative to the tip position - if(corner.precedance === 'x') { swapDimensions(); } - else { resetDimensions(); } - - // Set the tip dimensions - elems.tip.css({ - width: (width = size.width), - height: (height = size.height) - }); - - // Update our colours - self.detectColours(corner); - - // Detect border width, taking into account colours - if(color.border !== 'transparent' && color.border !== '#123456') { - // Grab border width - border = borderWidth(corner, NULL, TRUE); - - // If border width isn't zero, use border color as fill (1.0 style tips) - if(opts.border === 0 && border > 0) { color.fill = color.border; } - - // Set border width (use detected border width if opts.border is true) - self.border = border = opts.border !== TRUE ? opts.border : border; - } - - // Border colour was invalid, set border to zero - else { self.border = border = 0; } - - // Calculate coordinates - coords = calculateTip(mimic, width , height); - - // Determine tip size - self.size = newSize = calculateSize(corner); - tip.css(newSize); - - // Calculate tip translation - if(corner.precedance === 'y') { - translate = [ - round(mimic.x === 'left' ? border : mimic.x === 'right' ? newSize.width - width - border : (newSize.width - width) / 2), - round(mimic.y === 'top' ? newSize.height - height : 0) - ]; - } - else { - translate = [ - round(mimic.x === 'left' ? newSize.width - width : 0), - round(mimic.y === 'top' ? border : mimic.y === 'bottom' ? newSize.height - height - border : (newSize.height - height) / 2) - ]; - } - - // Canvas drawing implementation - if(hasCanvas) { - // Set the canvas size using calculated size - inner.attr(newSize); - - // Grab canvas context and clear/save it - context = inner[0].getContext('2d'); - context.restore(); context.save(); - context.clearRect(0,0,3000,3000); - - // Set properties - context.fillStyle = color.fill; - context.strokeStyle = color.border; - context.lineWidth = border * 2; - context.lineJoin = 'miter'; - context.miterLimit = 100; - - // Translate origin - context.translate(translate[0], translate[1]); - - // Draw the tip - context.beginPath(); - context.moveTo(coords[0][0], coords[0][1]); - context.lineTo(coords[1][0], coords[1][1]); - context.lineTo(coords[2][0], coords[2][1]); - context.closePath(); - - // Create borders - if(border) { - // Make sure transparent borders are supported by doing a stroke - // of the background colour before the stroke colour (border-box only) - if( elems.content.css('backgroundClip') === 'border-box' ) { - context.strokeStyle = color.fill; - context.stroke(); - } - - // Do our regular stroke - context.strokeStyle = color.border; - context.stroke(); - } - context.fill(); - } - - // VML (IE Proprietary implementation) - else { - // Setup coordinates string - coords = 'm' + coords[0][0] + ',' + coords[0][1] + ' l' + coords[1][0] + - ',' + coords[1][1] + ' ' + coords[2][0] + ',' + coords[2][1] + ' xe'; - - // Setup VML-specific offset for pixel-perfection - translate[2] = border && /^(r|b)/i.test(corner.string()) ? - parseFloat($.browser.version, 10) === 8 ? 2 : 1 : 0; - - // Set initial CSS - inner.css({ - antialias: ''+(mimic.string().indexOf('center') > -1), - left: translate[0] - (translate[2] * Number(precedance === 'x')), - top: translate[1] - (translate[2] * Number(precedance === 'y')), - width: width + border, - height: height + border - }) - .each(function(i) { - var $this = $(this); - - // Set shape specific attributes - $this[ $this.prop ? 'prop' : 'attr' ]({ - coordsize: (width+border) + ' ' + (height+border), - path: coords, - fillcolor: color.fill, - filled: !!i, - stroked: !!!i - }) - .css({ display: border || i ? 'block' : 'none' }); - - // Check if border is enabled and add stroke element - if(!i && $this.html() === '') { - $this.html( - '' - ); - } - }); - } - - // Position if needed - if(position !== FALSE) { self.position(corner); } - }, - - // Tip positioning method - position: function(corner) - { - var tip = elems.tip, - position = {}, - userOffset = Math.max(0, opts.offset), - precedance, dimensions, corners; - - // Return if tips are disabled or tip is not yet rendered - if(opts.corner === FALSE || !tip) { return FALSE; } - - // Inherit corner if not provided - corner = corner || self.corner; - precedance = corner.precedance; - - // Determine which tip dimension to use for adjustment - dimensions = calculateSize(corner); - - // Setup corners and offset array - corners = [ corner.x, corner.y ]; - if(precedance === 'x') { corners.reverse(); } - - // Calculate tip position - $.each(corners, function(i, side) { - var b, br; - - if(side === 'center') { - b = precedance === 'y' ? 'left' : 'top'; - position[ b ] = '50%'; - position['margin-' + b] = -Math.round(dimensions[ precedance === 'y' ? 'width' : 'height' ] / 2) + userOffset; - } - else { - b = borderWidth(corner, side, TRUE); - br = borderRadius(corner); - - position[ side ] = i ? - border ? borderWidth(corner, side) : 0 : - userOffset + (br > b ? br : 0); - } - }); - - // Adjust for tip dimensions - position[ corner[precedance] ] -= dimensions[ precedance === 'x' ? 'width' : 'height' ]; - - // Set and return new position - tip.css({ top: '', bottom: '', left: '', right: '', margin: '' }).css(position); - return position; - }, - - destroy: function() - { - // Remove the tip element - if(elems.tip) { elems.tip.remove(); } - elems.tip = false; - - // Unbind events - tooltip.unbind(namespace); - } - }); - - self.init(); -} - -PLUGINS.tip = function(api) -{ - var self = api.plugins.tip; - - return 'object' === typeof self ? self : (api.plugins.tip = new Tip(api)); -}; - -// Initialize tip on render -PLUGINS.tip.initialize = 'render'; - -// Setup plugin sanitization options -PLUGINS.tip.sanitize = function(options) -{ - var style = options.style, opts; - if(style && 'tip' in style) { - opts = options.style.tip; - if(typeof opts !== 'object'){ options.style.tip = { corner: opts }; } - if(!(/string|boolean/i).test(typeof opts.corner)) { opts.corner = TRUE; } - if(typeof opts.width !== 'number'){ delete opts.width; } - if(typeof opts.height !== 'number'){ delete opts.height; } - if(typeof opts.border !== 'number' && opts.border !== TRUE){ delete opts.border; } - if(typeof opts.offset !== 'number'){ delete opts.offset; } - } -}; - -// Extend original qTip defaults -$.extend(TRUE, QTIP.defaults, { - style: { - tip: { - corner: TRUE, - mimic: FALSE, - width: 6, - height: 6, - border: TRUE, - offset: 0 - } - } -}); +PLUGINS.ie6.initialize = 'render'; -})); \ No newline at end of file +})); +}( window, document )); \ No newline at end of file diff --git a/utils/hints.js b/utils/hints.js index 02f4d292f..777440417 100644 --- a/utils/hints.js +++ b/utils/hints.js @@ -47,7 +47,7 @@ $(Khan).bind("newProblem", function() { prerender: true }, style: { - classes: "ui-tooltip-light leaf-tooltip" + classes: "qtip-light leaf-tooltip" }, position: { my: "bottom center",