├── .gitignore ├── README.md ├── advancedsearch.css ├── advancedsearch.user.js ├── base.css ├── buttons.css ├── catsprites.png ├── clipboard.min.js ├── dklib.js ├── familyimages.js ├── fixedsticky.css ├── fixedsticky.js ├── highcharts.js ├── jquery-ui.css ├── jquery-ui.min.js ├── jquery.dragtable.js ├── jquery.hoverIntent.js ├── jquery.jqpagination.js ├── jquery.lazyloadxt.js ├── jquery.localScroll.js ├── jquery.min.js ├── jquery.spellchecker.js ├── pure.css ├── quantities.js ├── tooltipster-sideTip-shadow.min.css ├── tooltipster.bundle.css └── tooltipster.bundle.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 18 | .grunt 19 | 20 | # node-waf configuration 21 | .lock-wscript 22 | 23 | # Compiled binary addons (http://nodejs.org/api/addons.html) 24 | build/Release 25 | 26 | # Dependency directory 27 | # https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git 28 | node_modules 29 | 30 | # Optional npm cache directory 31 | .npm 32 | 33 | # Optional REPL history 34 | .node_repl_history -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | The advancedsearch userscript is intended to enhance user experience while browsing www.digikey.com and associated international websites. 2 | 3 | The official project page with installation instructions is located here: https://www.digikey.com/eewiki/display/Motley/advancedsearch+Greasemonkey+Userscript 4 | 5 | 6 | 7 | 8 | Highlights include: 9 | 10 | - Voltage Range Parsing 11 | - One-Click Part Number Copy 12 | - Column Math 13 | - Parametric Scatter Charts 14 | - Picture Oriented Browsing Additions 15 | - Break-Even Price Point Calculations for Price Breaks 16 | - Keyword Highlighting 17 | - Sticky Search Header 18 | - Search 3d Models 19 | - Much more... 20 | 21 | This script is a hobby and as such may have some bugs or flaws, but it is intended to be a test bed for trying things that could be helpful for people on a quest to find parts. Many functions are modular and can individually be disabled or enabled based on user preferences. Inspiration for this userscript came from the now retired Digi-Key Sort By Price that added the then lacking title function to DigiKey's website. 22 | 23 | ### Requirements 24 | This script is updated and tested on the most current official releases of Firefox/Chrome and Tampermonkey. 25 | 26 | This script is not designed with small screens in mind. A 900p or larger screen is recommended for the best experience. 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /base.css: -------------------------------------------------------------------------------- 1 | /*! 2 | Pure v0.5.0 3 | Copyright 2014 Yahoo! Inc. All rights reserved. 4 | Licensed under the BSD License. 5 | https://github.com/yui/pure/blob/master/LICENSE.md 6 | */ 7 | /*! 8 | normalize.css v1.1.3 | MIT License | git.io/normalize 9 | Copyright (c) Nicolas Gallagher and Jonathan Neal 10 | */ 11 | /*! normalize.css v1.1.3 | MIT License | git.io/normalize */ 12 | 13 | /* ========================================================================== 14 | HTML5 display definitions 15 | ========================================================================== */ 16 | 17 | /** 18 | * Correct `block` display not defined in IE 6/7/8/9 and Firefox 3. 19 | */ 20 | 21 | article, 22 | aside, 23 | details, 24 | figcaption, 25 | figure, 26 | footer, 27 | header, 28 | hgroup, 29 | main, 30 | nav, 31 | section, 32 | summary { 33 | display: block; 34 | } 35 | 36 | /** 37 | * Correct `inline-block` display not defined in IE 6/7/8/9 and Firefox 3. 38 | */ 39 | 40 | audio, 41 | canvas, 42 | video { 43 | display: inline-block; 44 | *display: inline; 45 | *zoom: 1; 46 | } 47 | 48 | /** 49 | * Prevent modern browsers from displaying `audio` without controls. 50 | * Remove excess height in iOS 5 devices. 51 | */ 52 | 53 | audio:not([controls]) { 54 | display: none; 55 | height: 0; 56 | } 57 | 58 | /** 59 | * Address styling not present in IE 7/8/9, Firefox 3, and Safari 4. 60 | * Known issue: no IE 6 support. 61 | */ 62 | 63 | [hidden] { 64 | display: none; 65 | } 66 | 67 | /* ========================================================================== 68 | Base 69 | ========================================================================== */ 70 | 71 | /** 72 | * 1. Correct text resizing oddly in IE 6/7 when body `font-size` is set using 73 | * `em` units. 74 | * 2. Prevent iOS text size adjust after orientation change, without disabling 75 | * user zoom. 76 | */ 77 | 78 | html { 79 | font-size: 100%; /* 1 */ 80 | -ms-text-size-adjust: 100%; /* 2 */ 81 | -webkit-text-size-adjust: 100%; /* 2 */ 82 | } 83 | 84 | /** 85 | * Address `font-family` inconsistency between `textarea` and other form 86 | * elements. 87 | */ 88 | 89 | html, 90 | button, 91 | input, 92 | select, 93 | textarea { 94 | font-family: sans-serif; 95 | } 96 | 97 | /** 98 | * Address margins handled incorrectly in IE 6/7. 99 | */ 100 | 101 | body { 102 | margin: 0; 103 | } 104 | 105 | /* ========================================================================== 106 | Links 107 | ========================================================================== */ 108 | 109 | /** 110 | * Address `outline` inconsistency between Chrome and other browsers. 111 | */ 112 | 113 | a:focus { 114 | outline: thin dotted; 115 | } 116 | 117 | /** 118 | * Improve readability when focused and also mouse hovered in all browsers. 119 | */ 120 | 121 | a:active, 122 | a:hover { 123 | outline: 0; 124 | } 125 | 126 | /* ========================================================================== 127 | Typography 128 | ========================================================================== */ 129 | 130 | /** 131 | * Address font sizes and margins set differently in IE 6/7. 132 | * Address font sizes within `section` and `article` in Firefox 4+, Safari 5, 133 | * and Chrome. 134 | */ 135 | 136 | h1 { 137 | font-size: 2em; 138 | margin: 0.67em 0; 139 | } 140 | 141 | h2 { 142 | font-size: 1.5em; 143 | margin: 0.83em 0; 144 | } 145 | 146 | h3 { 147 | font-size: 1.17em; 148 | margin: 1em 0; 149 | } 150 | 151 | h4 { 152 | font-size: 1em; 153 | margin: 1.33em 0; 154 | } 155 | 156 | h5 { 157 | font-size: 0.83em; 158 | margin: 1.67em 0; 159 | } 160 | 161 | h6 { 162 | font-size: 0.67em; 163 | margin: 2.33em 0; 164 | } 165 | 166 | /** 167 | * Address styling not present in IE 7/8/9, Safari 5, and Chrome. 168 | */ 169 | 170 | abbr[title] { 171 | border-bottom: 1px dotted; 172 | } 173 | 174 | /** 175 | * Address style set to `bolder` in Firefox 3+, Safari 4/5, and Chrome. 176 | */ 177 | 178 | b, 179 | strong { 180 | font-weight: bold; 181 | } 182 | 183 | blockquote { 184 | margin: 1em 40px; 185 | } 186 | 187 | /** 188 | * Address styling not present in Safari 5 and Chrome. 189 | */ 190 | 191 | dfn { 192 | font-style: italic; 193 | } 194 | 195 | /** 196 | * Address differences between Firefox and other browsers. 197 | * Known issue: no IE 6/7 normalization. 198 | */ 199 | 200 | hr { 201 | -moz-box-sizing: content-box; 202 | box-sizing: content-box; 203 | height: 0; 204 | } 205 | 206 | /** 207 | * Address styling not present in IE 6/7/8/9. 208 | */ 209 | 210 | mark { 211 | background: #ff0; 212 | color: #000; 213 | } 214 | 215 | /** 216 | * Address margins set differently in IE 6/7. 217 | */ 218 | 219 | p, 220 | pre { 221 | margin: 1em 0; 222 | } 223 | 224 | /** 225 | * Correct font family set oddly in IE 6, Safari 4/5, and Chrome. 226 | */ 227 | 228 | code, 229 | kbd, 230 | pre, 231 | samp { 232 | font-family: monospace, serif; 233 | _font-family: 'courier new', monospace; 234 | font-size: 1em; 235 | } 236 | 237 | /** 238 | * Improve readability of pre-formatted text in all browsers. 239 | */ 240 | 241 | pre { 242 | white-space: pre; 243 | white-space: pre-wrap; 244 | word-wrap: break-word; 245 | } 246 | 247 | /** 248 | * Address CSS quotes not supported in IE 6/7. 249 | */ 250 | 251 | q { 252 | quotes: none; 253 | } 254 | 255 | /** 256 | * Address `quotes` property not supported in Safari 4. 257 | */ 258 | 259 | q:before, 260 | q:after { 261 | content: ''; 262 | content: none; 263 | } 264 | 265 | /** 266 | * Address inconsistent and variable font size in all browsers. 267 | */ 268 | 269 | small { 270 | font-size: 80%; 271 | } 272 | 273 | /** 274 | * Prevent `sub` and `sup` affecting `line-height` in all browsers. 275 | */ 276 | 277 | sub, 278 | sup { 279 | font-size: 75%; 280 | line-height: 0; 281 | position: relative; 282 | vertical-align: baseline; 283 | } 284 | 285 | sup { 286 | top: -0.5em; 287 | } 288 | 289 | sub { 290 | bottom: -0.25em; 291 | } 292 | 293 | /* ========================================================================== 294 | Lists 295 | ========================================================================== */ 296 | 297 | /** 298 | * Address margins set differently in IE 6/7. 299 | */ 300 | 301 | dl, 302 | menu, 303 | ol, 304 | ul { 305 | margin: 1em 0; 306 | } 307 | 308 | dd { 309 | margin: 0 0 0 40px; 310 | } 311 | 312 | /** 313 | * Address paddings set differently in IE 6/7. 314 | */ 315 | 316 | menu, 317 | ol, 318 | ul { 319 | padding: 0 0 0 40px; 320 | } 321 | 322 | /** 323 | * Correct list images handled incorrectly in IE 7. 324 | */ 325 | 326 | nav ul, 327 | nav ol { 328 | list-style: none; 329 | list-style-image: none; 330 | } 331 | 332 | /* ========================================================================== 333 | Embedded content 334 | ========================================================================== */ 335 | 336 | /** 337 | * 1. Remove border when inside `a` element in IE 6/7/8/9 and Firefox 3. 338 | * 2. Improve image quality when scaled in IE 7. 339 | */ 340 | 341 | img { 342 | border: 0; /* 1 */ 343 | -ms-interpolation-mode: bicubic; /* 2 */ 344 | } 345 | 346 | /** 347 | * Correct overflow displayed oddly in IE 9. 348 | */ 349 | 350 | svg:not(:root) { 351 | overflow: hidden; 352 | } 353 | 354 | /* ========================================================================== 355 | Figures 356 | ========================================================================== */ 357 | 358 | /** 359 | * Address margin not present in IE 6/7/8/9, Safari 5, and Opera 11. 360 | */ 361 | 362 | figure { 363 | margin: 0; 364 | } 365 | 366 | /* ========================================================================== 367 | Forms 368 | ========================================================================== */ 369 | 370 | /** 371 | * Correct margin displayed oddly in IE 6/7. 372 | */ 373 | 374 | form { 375 | margin: 0; 376 | } 377 | 378 | /** 379 | * Define consistent border, margin, and padding. 380 | */ 381 | 382 | fieldset { 383 | border: 1px solid #c0c0c0; 384 | margin: 0 2px; 385 | padding: 0.35em 0.625em 0.75em; 386 | } 387 | 388 | /** 389 | * 1. Correct color not being inherited in IE 6/7/8/9. 390 | * 2. Correct text not wrapping in Firefox 3. 391 | * 3. Correct alignment displayed oddly in IE 6/7. 392 | */ 393 | 394 | legend { 395 | border: 0; /* 1 */ 396 | padding: 0; 397 | white-space: normal; /* 2 */ 398 | *margin-left: -7px; /* 3 */ 399 | } 400 | 401 | /** 402 | * 1. Correct font size not being inherited in all browsers. 403 | * 2. Address margins set differently in IE 6/7, Firefox 3+, Safari 5, 404 | * and Chrome. 405 | * 3. Improve appearance and consistency in all browsers. 406 | */ 407 | 408 | button, 409 | input, 410 | select, 411 | textarea { 412 | font-size: 100%; /* 1 */ 413 | margin: 0; /* 2 */ 414 | vertical-align: baseline; /* 3 */ 415 | *vertical-align: middle; /* 3 */ 416 | } 417 | 418 | /** 419 | * Address Firefox 3+ setting `line-height` on `input` using `!important` in 420 | * the UA stylesheet. 421 | */ 422 | 423 | button, 424 | input { 425 | line-height: normal; 426 | } 427 | 428 | /** 429 | * Address inconsistent `text-transform` inheritance for `button` and `select`. 430 | * All other form control elements do not inherit `text-transform` values. 431 | * Correct `button` style inheritance in Chrome, Safari 5+, and IE 6+. 432 | * Correct `select` style inheritance in Firefox 4+ and Opera. 433 | */ 434 | 435 | button, 436 | select { 437 | text-transform: none; 438 | } 439 | 440 | /** 441 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` 442 | * and `video` controls. 443 | * 2. Correct inability to style clickable `input` types in iOS. 444 | * 3. Improve usability and consistency of cursor style between image-type 445 | * `input` and others. 446 | * 4. Remove inner spacing in IE 7 without affecting normal text inputs. 447 | * Known issue: inner spacing remains in IE 6. 448 | */ 449 | 450 | button, 451 | html input[type="button"], /* 1 */ 452 | input[type="reset"], 453 | input[type="submit"] { 454 | -webkit-appearance: button; /* 2 */ 455 | cursor: pointer; /* 3 */ 456 | *overflow: visible; /* 4 */ 457 | } 458 | 459 | /** 460 | * Re-set default cursor for disabled elements. 461 | */ 462 | 463 | button[disabled], 464 | html input[disabled] { 465 | cursor: default; 466 | } 467 | 468 | /** 469 | * 1. Address box sizing set to content-box in IE 8/9. 470 | * 2. Remove excess padding in IE 8/9. 471 | * 3. Remove excess padding in IE 7. 472 | * Known issue: excess padding remains in IE 6. 473 | */ 474 | 475 | input[type="checkbox"], 476 | input[type="radio"] { 477 | box-sizing: border-box; /* 1 */ 478 | padding: 0; /* 2 */ 479 | *height: 13px; /* 3 */ 480 | *width: 13px; /* 3 */ 481 | } 482 | 483 | /** 484 | * 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome. 485 | * 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome 486 | * (include `-moz` to future-proof). 487 | */ 488 | 489 | input[type="search"] { 490 | -webkit-appearance: textfield; /* 1 */ 491 | -moz-box-sizing: content-box; 492 | -webkit-box-sizing: content-box; /* 2 */ 493 | box-sizing: content-box; 494 | } 495 | 496 | /** 497 | * Remove inner padding and search cancel button in Safari 5 and Chrome 498 | * on OS X. 499 | */ 500 | 501 | input[type="search"]::-webkit-search-cancel-button, 502 | input[type="search"]::-webkit-search-decoration { 503 | -webkit-appearance: none; 504 | } 505 | 506 | /** 507 | * Remove inner padding and border in Firefox 3+. 508 | */ 509 | 510 | button::-moz-focus-inner, 511 | input::-moz-focus-inner { 512 | border: 0; 513 | padding: 0; 514 | } 515 | 516 | /** 517 | * 1. Remove default vertical scrollbar in IE 6/7/8/9. 518 | * 2. Improve readability and alignment in all browsers. 519 | */ 520 | 521 | textarea { 522 | overflow: auto; /* 1 */ 523 | vertical-align: top; /* 2 */ 524 | } 525 | 526 | /* ========================================================================== 527 | Tables 528 | ========================================================================== */ 529 | 530 | /** 531 | * Remove most spacing between table cells. 532 | */ 533 | 534 | table { 535 | border-collapse: collapse; 536 | border-spacing: 0; 537 | } 538 | 539 | /*csslint important:false*/ 540 | 541 | /* ========================================================================== 542 | Pure Base Extras 543 | ========================================================================== */ 544 | 545 | /** 546 | * Extra rules that Pure adds on top of Normalize.css 547 | */ 548 | 549 | /** 550 | * Always hide an element when it has the `hidden` HTML attribute. 551 | */ 552 | 553 | [hidden] { 554 | display: none !important; 555 | } 556 | 557 | /** 558 | * Add this class to an image to make it fit within it's fluid parent wrapper while maintaining 559 | * aspect ratio. 560 | */ 561 | .pure-img { 562 | max-width: 100%; 563 | height: auto; 564 | display: block; 565 | } 566 | -------------------------------------------------------------------------------- /buttons.css: -------------------------------------------------------------------------------- 1 | /*Copyright (c) 2011 Chad Mazzola 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE.*/ 20 | button::-moz-focus-inner { 21 | border: 0; } 22 | 23 | /* minimal 24 | *******************************************************************************/ 25 | .minimal { 26 | background: #e3e3e3; 27 | border: 1px solid #bbb; 28 | border-radius: 3px; 29 | -webkit-box-shadow: inset 0 0 1px 1px #f6f6f6; 30 | box-shadow: inset 0 0 1px 1px #f6f6f6; 31 | color: #333; 32 | font: bold 12px/1 "helvetica neue", helvetica, arial, sans-serif; 33 | padding: 4px 0 4px; 34 | text-align: center; 35 | text-shadow: 0 1px 0 #fff; 36 | height: 20px; 37 | } 38 | .minimal:hover { 39 | background: #d9d9d9; 40 | -webkit-box-shadow: inset 0 0 1px 1px #eaeaea; 41 | box-shadow: inset 0 0 1px 1px #eaeaea; 42 | color: #222; 43 | cursor: pointer; } 44 | .minimal:active { 45 | background: #d0d0d0; 46 | -webkit-box-shadow: inset 0 0 1px 1px #e3e3e3; 47 | box-shadow: inset 0 0 1px 1px #e3e3e3; 48 | color: #000; } 49 | 50 | /* clean gray 51 | *******************************************************************************/ 52 | .clean-gray { 53 | background-color: #eeeeee; 54 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #eeeeee), color-stop(100%, #cccccc)); 55 | background-image: -webkit-linear-gradient(top, #eeeeee, #cccccc); 56 | background-image: -moz-linear-gradient(top, #eeeeee, #cccccc); 57 | background-image: -ms-linear-gradient(top, #eeeeee, #cccccc); 58 | background-image: -o-linear-gradient(top, #eeeeee, #cccccc); 59 | background-image: linear-gradient(top, #eeeeee, #cccccc); 60 | border: 1px solid #ccc; 61 | border-bottom: 1px solid #bbb; 62 | border-radius: 3px; 63 | color: #333; 64 | font: bold 11px/1 "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif; 65 | padding: 4px 0; 66 | text-align: center; 67 | text-shadow: 0 1px 0 #eee; 68 | 69 | } 70 | .clean-gray:hover { 71 | background-color: #dddddd; 72 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #dddddd), color-stop(100%, #bbbbbb)); 73 | background-image: -webkit-linear-gradient(top, #dddddd, #bbbbbb); 74 | background-image: -moz-linear-gradient(top, #dddddd, #bbbbbb); 75 | background-image: -ms-linear-gradient(top, #dddddd, #bbbbbb); 76 | background-image: -o-linear-gradient(top, #dddddd, #bbbbbb); 77 | background-image: linear-gradient(top, #dddddd, #bbbbbb); 78 | border: 1px solid #bbb; 79 | border-bottom: 1px solid #999; 80 | cursor: pointer; 81 | text-shadow: 0 1px 0 #ddd; } 82 | .clean-gray:active { 83 | border: 1px solid #aaa; 84 | border-bottom: 1px solid #888; 85 | -webkit-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eee} 86 | 87 | /* clean gray********************************************************************************/ 88 | .clean-gray2 { 89 | background-color: #eeeeee; 90 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #eeeeee), color-stop(100%, #cccccc)); 91 | background-image: -webkit-linear-gradient(top, #eeeeee, #cccccc); 92 | background-image: -moz-linear-gradient(top, #eeeeee, #cccccc); 93 | background-image: -ms-linear-gradient(top, #eeeeee, #cccccc); 94 | background-image: -o-linear-gradient(top, #eeeeee, #cccccc); 95 | background-image: linear-gradient(top, #eeeeee, #cccccc); 96 | border: 1px solid #ccc; 97 | border-bottom: 1px solid #bbb; 98 | border-radius: 1px; 99 | color: #333; 100 | font: bold 11px/1 "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif; 101 | padding: 4px 0; 102 | text-align: center; 103 | text-shadow: 0 1px 0 #eee; 104 | 105 | } 106 | .clean-gray2:hover { 107 | background-color: #dddddd; 108 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #dddddd), color-stop(100%, #bbbbbb)); 109 | background-image: -webkit-linear-gradient(top, #dddddd, #bbbbbb); 110 | background-image: -moz-linear-gradient(top, #dddddd, #bbbbbb); 111 | background-image: -ms-linear-gradient(top, #dddddd, #bbbbbb); 112 | background-image: -o-linear-gradient(top, #dddddd, #bbbbbb); 113 | background-image: linear-gradient(top, #dddddd, #bbbbbb); 114 | border: 1px solid #bbb; 115 | border-bottom: 1px solid #999; 116 | cursor: pointer; 117 | text-shadow: 0 1px 0 #ddd; } 118 | .clean-gray2:active { 119 | border: 1px solid #aaa; 120 | border-bottom: 1px solid #888; 121 | -webkit-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; 122 | box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; } 123 | 124 | /* cupid green (inspired by okcupid.com) 125 | *******************************************************************************/ 126 | .cupid-green { 127 | background-color: #7fbf4d; 128 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #7fbf4d), color-stop(100%, #63a62f)); 129 | background-image: -webkit-linear-gradient(top, #7fbf4d, #63a62f); 130 | background-image: -moz-linear-gradient(top, #7fbf4d, #63a62f); 131 | background-image: -ms-linear-gradient(top, #7fbf4d, #63a62f); 132 | background-image: -o-linear-gradient(top, #7fbf4d, #63a62f); 133 | background-image: linear-gradient(top, #7fbf4d, #63a62f); 134 | border: 1px solid #63a62f; 135 | border-bottom: 1px solid #5b992b; 136 | border-radius: 3px; 137 | -webkit-box-shadow: inset 0 1px 0 0 #96ca6d; 138 | box-shadow: inset 0 1px 0 0 #96ca6d; 139 | color: #fff; 140 | font: bold 11px/1 "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif; 141 | padding: 4px 0 5px 0; 142 | text-align: center; 143 | text-shadow: 0 -1px 0 #4c9021; 144 | width: 150px; } 145 | .cupid-green:hover { 146 | background-color: #76b347; 147 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #76b347), color-stop(100%, #5e9e2e)); 148 | background-image: -webkit-linear-gradient(top, #76b347, #5e9e2e); 149 | background-image: -moz-linear-gradient(top, #76b347, #5e9e2e); 150 | background-image: -ms-linear-gradient(top, #76b347, #5e9e2e); 151 | background-image: -o-linear-gradient(top, #76b347, #5e9e2e); 152 | background-image: linear-gradient(top, #76b347, #5e9e2e); 153 | -webkit-box-shadow: inset 0 1px 0 0 #8dbf67; 154 | box-shadow: inset 0 1px 0 0 #8dbf67; 155 | cursor: pointer; } 156 | .cupid-green:active { 157 | border: 1px solid #5b992b; 158 | border-bottom: 1px solid #538c27; 159 | -webkit-box-shadow: inset 0 0 8px 4px #548c29, 0 1px 0 0 #eeeeee; 160 | box-shadow: inset 0 0 8px 4px #548c29, 0 1px 0 0 #eeeeee; } 161 | 162 | /* cupid blue (inspired by okcupid.com) 163 | *******************************************************************************/ 164 | .cupid-blue { 165 | background-color: #d7e5f5; 166 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #d7e5f5), color-stop(100%, #cbe0f5)); 167 | background-image: -webkit-linear-gradient(top, #d7e5f5, #cbe0f5); 168 | background-image: -moz-linear-gradient(top, #d7e5f5, #cbe0f5); 169 | background-image: -ms-linear-gradient(top, #d7e5f5, #cbe0f5); 170 | background-image: -o-linear-gradient(top, #d7e5f5, #cbe0f5); 171 | background-image: linear-gradient(top, #d7e5f5, #cbe0f5); 172 | border-top: 1px solid #abbbcc; 173 | border-left: 1px solid #a7b6c7; 174 | border-bottom: 1px solid #a1afbf; 175 | border-right: 1px solid #a7b6c7; 176 | border-radius: 12px; 177 | -webkit-box-shadow: inset 0 1px 0 0 white; 178 | box-shadow: inset 0 1px 0 0 white; 179 | color: #1a3e66; 180 | font: normal 11px/1 "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif; 181 | padding: 6px 0 7px 0; 182 | text-align: center; 183 | text-shadow: 0 1px 1px #fff; 184 | width: 150px; } 185 | .cupid-blue:hover { 186 | background-color: #ccd9e8; 187 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ccd9e8), color-stop(100%, #c1d4e8)); 188 | background-image: -webkit-linear-gradient(top, #ccd9e8, #c1d4e8); 189 | background-image: -moz-linear-gradient(top, #ccd9e8, #c1d4e8); 190 | background-image: -ms-linear-gradient(top, #ccd9e8, #c1d4e8); 191 | background-image: -o-linear-gradient(top, #ccd9e8, #c1d4e8); 192 | background-image: linear-gradient(top, #ccd9e8, #c1d4e8); 193 | border-top: 1px solid #a1afbf; 194 | border-left: 1px solid #9caaba; 195 | border-bottom: 1px solid #96a3b3; 196 | border-right: 1px solid #9caaba; 197 | -webkit-box-shadow: inset 0 1px 0 0 #f2f2f2; 198 | box-shadow: inset 0 1px 0 0 #f2f2f2; 199 | color: #163659; 200 | cursor: pointer; } 201 | .cupid-blue:active { 202 | border: 1px solid #8c98a7; 203 | -webkit-box-shadow: inset 0 0 4px 2px #abbccf, 0 0 1px 0 #eeeeee; 204 | box-shadow: inset 0 0 4px 2px #abbccf, 0 0 1px 0 #eeeeee; } 205 | 206 | /* blue pill (inspired by iTunes) 207 | *******************************************************************************/ 208 | .blue-pill { 209 | background-color: #a5b8da; 210 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #a5b8da), color-stop(100%, #cf0404)); 211 | background-image: -webkit-linear-gradient(top, #a5b8da, #cf0404); 212 | background-image: -moz-linear-gradient(top, #a5b8da, #cf0404); 213 | background-image: -ms-linear-gradient(top, #a5b8da, #cf0404); 214 | background-image: -o-linear-gradient(top, #a5b8da, #cf0404); 215 | background-image: linear-gradient(top, #a5b8da, #cf0404); 216 | border-top: 1px solid #758fba; 217 | border-right: 1px solid #6c84ab; 218 | border-bottom: 1px solid #5c6f91; 219 | border-left: 1px solid #6c84ab; 220 | border-radius: 18px; 221 | -webkit-box-shadow: inset 0 1px 0 0 #aec3e5; 222 | box-shadow: inset 0 1px 0 0 #aec3e5; 223 | color: #fff; 224 | font: bold 11px/1 "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif; 225 | padding: 8px 0; 226 | text-align: center; 227 | text-shadow: 0 -1px 1px #64799e; 228 | text-transform: uppercase; 229 | /*width: 150px; */ 230 | } 231 | .blue-pill:hover { 232 | background-color: #9badcc; 233 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #9badcc), color-stop(100%, #687fa6)); 234 | background-image: -webkit-linear-gradient(top, #9badcc, #687fa6); 235 | background-image: -moz-linear-gradient(top, #9badcc, #687fa6); 236 | background-image: -ms-linear-gradient(top, #9badcc, #687fa6); 237 | background-image: -o-linear-gradient(top, #9badcc, #687fa6); 238 | background-image: linear-gradient(top, #9badcc, #687fa6); 239 | border-top: 1px solid #6d86ad; 240 | border-right: 1px solid #647a9e; 241 | border-bottom: 1px solid #546685; 242 | border-left: 1px solid #647a9e; 243 | -webkit-box-shadow: inset 0 1px 0 0 #a5b9d9; 244 | box-shadow: inset 0 1px 0 0 #a5b9d9; 245 | cursor: pointer; } 246 | .blue-pill:active { 247 | border: 1px solid #546685; 248 | -webkit-box-shadow: inset 0 0 8px 2px #7e8da6, 0 1px 0 0 #eeeeee; 249 | box-shadow: inset 0 0 8px 2px #7e8da6, 0 1px 0 0 #eeeeee; } 250 | 251 | /* red pill (inspired by iTunes) 252 | *******************************************************************************/ 253 | .red-pill { 254 | background-color: #ff3019; 255 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ff3019), color-stop(100%, #cf0404)); 256 | background-image: -webkit-linear-gradient(top, #ff3019, #cf0404); 257 | background-image: -moz-linear-gradient(top, #ff3019, #cf0404); 258 | background-image: -ms-linear-gradient(top, #ff3019, #cf0404); 259 | background-image: -o-linear-gradient(top, #ff3019, #cf0404); 260 | background-image: linear-gradient(top, #ff3019, #cf0404); 261 | border-top: 1px solid #758fba; 262 | border-right: 1px solid #6c84ab; 263 | border-bottom: 1px solid #5c6f91; 264 | border-left: 1px solid #6c84ab; 265 | border-radius: 18px; 266 | -webkit-box-shadow: inset 0 1px 0 0 #aec3e5; 267 | box-shadow: inset 0 1px 0 0 #aec3e5; 268 | color: #fff; 269 | font: bold 11px/1 "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif; 270 | /*padding: 2px;*/ 271 | text-align: center; 272 | text-shadow: 0 -1px 1px #64799e; 273 | text-transform: uppercase; 274 | /*width: 150px; */ 275 | } 276 | .red-pill:hover { 277 | background-color: #9badcc; 278 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #9badcc), color-stop(100%, #687fa6)); 279 | background-image: -webkit-linear-gradient(top, #9badcc, #687fa6); 280 | background-image: -moz-linear-gradient(top, #9badcc, #687fa6); 281 | background-image: -ms-linear-gradient(top, #9badcc, #687fa6); 282 | background-image: -o-linear-gradient(top, #9badcc, #687fa6); 283 | background-image: linear-gradient(top, #9badcc, #687fa6); 284 | border-top: 1px solid #6d86ad; 285 | border-right: 1px solid #647a9e; 286 | border-bottom: 1px solid #546685; 287 | border-left: 1px solid #647a9e; 288 | -webkit-box-shadow: inset 0 1px 0 0 #a5b9d9; 289 | box-shadow: inset 0 1px 0 0 #a5b9d9; 290 | cursor: pointer; } 291 | .blue-pill:active { 292 | border: 1px solid #546685; 293 | -webkit-box-shadow: inset 0 0 8px 2px #7e8da6, 0 1px 0 0 #eeeeee; 294 | box-shadow: inset 0 0 8px 2px #7e8da6, 0 1px 0 0 #eeeeee; } 295 | 296 | /* thoughtbot (inspired by thoughtbot.com) 297 | *******************************************************************************/ 298 | .thoughtbot { 299 | background-color: #ee432e; 300 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ee432e), color-stop(50%, #c63929), color-stop(50%, #b51700), color-stop(100%, #891100)); 301 | background-image: -webkit-linear-gradient(top, #ee432e 0%, #c63929 50%, #b51700 50%, #891100 100%); 302 | background-image: -moz-linear-gradient(top, #ee432e 0%, #c63929 50%, #b51700 50%, #891100 100%); 303 | background-image: -ms-linear-gradient(top, #ee432e 0%, #c63929 50%, #b51700 50%, #891100 100%); 304 | background-image: -o-linear-gradient(top, #ee432e 0%, #c63929 50%, #b51700 50%, #891100 100%); 305 | background-image: linear-gradient(top, #ee432e 0%, #c63929 50%, #b51700 50%, #891100 100%); 306 | border: 1px solid #951100; 307 | border-radius: 5px; 308 | -webkit-box-shadow: inset 0px 0px 0px 1px rgba(255, 115, 100, 0.4), 0 1px 3px #333333; 309 | box-shadow: inset 0px 0px 0px 1px rgba(255, 115, 100, 0.4), 0 1px 3px #333333; 310 | color: #fff; 311 | font: bold 13px/1 "helvetica neue", helvetica, arial, sans-serif; 312 | padding: 3px 15px 4px 15px; 313 | text-align: center; 314 | text-shadow: 0px -1px 1px rgba(0, 0, 0, 0.8); 315 | /*width: 100px;*/ } 316 | .thoughtbot:hover { 317 | background-color: #f37873; 318 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f37873), color-stop(50%, #db504d), color-stop(50%, #cb0500), color-stop(100%, #a20601)); 319 | background-image: -webkit-linear-gradient(top, #f37873 0%, #db504d 50%, #cb0500 50%, #a20601 100%); 320 | background-image: -moz-linear-gradient(top, #f37873 0%, #db504d 50%, #cb0500 50%, #a20601 100%); 321 | background-image: -ms-linear-gradient(top, #f37873 0%, #db504d 50%, #cb0500 50%, #a20601 100%); 322 | background-image: -o-linear-gradient(top, #f37873 0%, #db504d 50%, #cb0500 50%, #a20601 100%); 323 | background-image: linear-gradient(top, #f37873 0%, #db504d 50%, #cb0500 50%, #a20601 100%); 324 | cursor: pointer; } 325 | .thoughtbot:active { 326 | background-color: #d43c28; 327 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #d43c28), color-stop(50%, #ad3224), color-stop(50%, #9c1500), color-stop(100%, #700d00)); 328 | background-image: -webkit-linear-gradient(top, #d43c28 0%, #ad3224 50%, #9c1500 50%, #700d00 100%); 329 | background-image: -moz-linear-gradient(top, #d43c28 0%, #ad3224 50%, #9c1500 50%, #700d00 100%); 330 | background-image: -ms-linear-gradient(top, #d43c28 0%, #ad3224 50%, #9c1500 50%, #700d00 100%); 331 | background-image: -o-linear-gradient(top, #d43c28 0%, #ad3224 50%, #9c1500 50%, #700d00 100%); 332 | background-image: linear-gradient(top, #d43c28 0%, #ad3224 50%, #9c1500 50%, #700d00 100%); 333 | -webkit-box-shadow: inset 0px 0px 0px 1px rgba(255, 115, 100, 0.4); 334 | box-shadow: inset 0px 0px 0px 1px rgba(255, 115, 100, 0.4); } 335 | 336 | .thoughtbot2 { 337 | background-color: #ee432e; 338 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ee432e), color-stop(50%, #c63929), color-stop(50%, #b51700), color-stop(100%, #891100)); 339 | background-image: -webkit-linear-gradient(top, #ee432e 0%, #c63929 50%, #b51700 50%, #891100 100%); 340 | background-image: -moz-linear-gradient(top, #ee432e 0%, #c63929 50%, #b51700 50%, #891100 100%); 341 | background-image: -ms-linear-gradient(top, #ee432e 0%, #c63929 50%, #b51700 50%, #891100 100%); 342 | background-image: -o-linear-gradient(top, #ee432e 0%, #c63929 50%, #b51700 50%, #891100 100%); 343 | background-image: linear-gradient(top, #ee432e 0%, #c63929 50%, #b51700 50%, #891100 100%); 344 | border: 1px solid #951100; 345 | border-radius: 1px; 346 | -webkit-box-shadow: inset 0px 0px 0px 1px rgba(255, 115, 100, 0.4), 0 1px 3px #333333; 347 | box-shadow: inset 0px 0px 0px 1px rgba(255, 115, 100, 0.4), 0 1px 3px #333333; 348 | color: #fff; 349 | font: bold 13px/1 "helvetica neue", helvetica, arial, sans-serif; 350 | padding: 5px 5px 5px 4px; 351 | text-align: center; 352 | text-shadow: 0px -1px 1px rgba(0, 0, 0, 0.8); 353 | /*width: 100px;*/ } 354 | .thoughtbot2:hover { 355 | background-color: #f37873; 356 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f37873), color-stop(50%, #db504d), color-stop(50%, #cb0500), color-stop(100%, #a20601)); 357 | background-image: -webkit-linear-gradient(top, #f37873 0%, #db504d 50%, #cb0500 50%, #a20601 100%); 358 | background-image: -moz-linear-gradient(top, #f37873 0%, #db504d 50%, #cb0500 50%, #a20601 100%); 359 | background-image: -ms-linear-gradient(top, #f37873 0%, #db504d 50%, #cb0500 50%, #a20601 100%); 360 | background-image: -o-linear-gradient(top, #f37873 0%, #db504d 50%, #cb0500 50%, #a20601 100%); 361 | background-image: linear-gradient(top, #f37873 0%, #db504d 50%, #cb0500 50%, #a20601 100%); 362 | cursor: pointer; } 363 | .thoughtbot2:active { 364 | background-color: #d43c28; 365 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #d43c28), color-stop(50%, #ad3224), color-stop(50%, #9c1500), color-stop(100%, #700d00)); 366 | background-image: -webkit-linear-gradient(top, #d43c28 0%, #ad3224 50%, #9c1500 50%, #700d00 100%); 367 | background-image: -moz-linear-gradient(top, #d43c28 0%, #ad3224 50%, #9c1500 50%, #700d00 100%); 368 | background-image: -ms-linear-gradient(top, #d43c28 0%, #ad3224 50%, #9c1500 50%, #700d00 100%); 369 | background-image: -o-linear-gradient(top, #d43c28 0%, #ad3224 50%, #9c1500 50%, #700d00 100%); 370 | background-image: linear-gradient(top, #d43c28 0%, #ad3224 50%, #9c1500 50%, #700d00 100%); 371 | -webkit-box-shadow: inset 0px 0px 0px 1px rgba(255, 115, 100, 0.4); 372 | box-shadow: inset 0px 0px 0px 1px rgba(255, 115, 100, 0.4); } 373 | 374 | /* punch 375 | *******************************************************************************/ 376 | .punch { 377 | background: #4162a8; 378 | border-top: 1px solid #38538c; 379 | border-right: 1px solid #1f2d4d; 380 | border-bottom: 1px solid #151e33; 381 | border-left: 1px solid #1f2d4d; 382 | border-radius: 4px; 383 | -webkit-box-shadow: inset 0 1px 10px 1px #5c8bee, 0px 1px 0 #1d2c4d, 0 6px 0px #1f3053, 0 8px 4px 1px #111111; 384 | box-shadow: inset 0 1px 10px 1px #5c8bee, 0px 1px 0 #1d2c4d, 0 6px 0px #1f3053, 0 8px 4px 1px #111111; 385 | color: #fff; 386 | font: bold 20px/1 "helvetica neue", helvetica, arial, sans-serif; 387 | margin-bottom: 10px; 388 | padding: 10px 0 12px 0; 389 | text-align: center; 390 | text-shadow: 0px -1px 1px #1e2d4d; 391 | /*width: 150px;*/ 392 | -webkit-background-clip: padding-box; } 393 | .punch:hover { 394 | -webkit-box-shadow: inset 0 0px 20px 1px #87adff, 0px 1px 0 #1d2c4d, 0 6px 0px #1f3053, 0 8px 4px 1px #111111; 395 | box-shadow: inset 0 0px 20px 1px #87adff, 0px 1px 0 #1d2c4d, 0 6px 0px #1f3053, 0 8px 4px 1px #111111; 396 | cursor: pointer; } 397 | .punch:active { 398 | -webkit-box-shadow: inset 0 1px 10px 1px #5c8bee, 0 1px 0 #1d2c4d, 0 2px 0 #1f3053, 0 4px 3px 0 #111111; 399 | box-shadow: inset 0 1px 10px 1px #5c8bee, 0 1px 0 #1d2c4d, 0 2px 0 #1f3053, 0 4px 3px 0 #111111; 400 | margin-top: 58px; } 401 | 402 | /* purple candy 403 | *******************************************************************************/ 404 | .purple-candy { 405 | background-color: #9e76e8; 406 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #9e76e8), color-stop(50%, #7038e0), color-stop(50%, #6021de), color-stop(100%, #6224de)); 407 | background-image: -webkit-linear-gradient(top, #9e76e8 0%, #7038e0 50%, #6021de 50%, #6224de 100%); 408 | background-image: -moz-linear-gradient(top, #9e76e8 0%, #7038e0 50%, #6021de 50%, #6224de 100%); 409 | background-image: -ms-linear-gradient(top, #9e76e8 0%, #7038e0 50%, #6021de 50%, #6224de 100%); 410 | background-image: -o-linear-gradient(top, #9e76e8 0%, #7038e0 50%, #6021de 50%, #6224de 100%); 411 | background-image: linear-gradient(top, #9e76e8 0%, #7038e0 50%, #6021de 50%, #6224de 100%); 412 | border-radius: 3px; 413 | color: #fff; 414 | font: bold 12px/1 "helvetica neue", helvetica, arial, sans-serif; 415 | padding: 10px 0 12px 0; 416 | text-align: center; 417 | text-shadow: 0px -1px 1px #473569; 418 | /*width: 150px;*/ 419 | -webkit-background-clip: padding-box; } 420 | .purple-candy:hover { 421 | background-color: #8d69cf; 422 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #8d69cf), color-stop(50%, #6332c7), color-stop(50%, #551dc4), color-stop(100%, #561fc4)); 423 | background-image: -webkit-linear-gradient(top, #8d69cf 0%, #6332c7 50%, #551dc4 50%, #561fc4 100%); 424 | background-image: -moz-linear-gradient(top, #8d69cf 0%, #6332c7 50%, #551dc4 50%, #561fc4 100%); 425 | background-image: -ms-linear-gradient(top, #8d69cf 0%, #6332c7 50%, #551dc4 50%, #561fc4 100%); 426 | background-image: -o-linear-gradient(top, #8d69cf 0%, #6332c7 50%, #551dc4 50%, #561fc4 100%); 427 | background-image: linear-gradient(top, #8d69cf 0%, #6332c7 50%, #551dc4 50%, #561fc4 100%); 428 | -webkit-background-clip: padding-box; 429 | cursor: pointer; } 430 | .purple-candy:active { 431 | background: #4a1aab; 432 | background: -moz-radial-gradient(50% 31% 0deg, circle cover, rgba(38, 76, 153, 0.4), rgba(11, 23, 46, 0.4)), -moz-linear-gradient(top, #7b5cb5 0%, #572bad 50%, #4a1aab 50%, #4b1bab 100%); 433 | background: -webkit-gradient(radial, 50% 20%, 75, 50% 50%, 0, from(rgba(38, 76, 153, 0.4)), to(rgba(11, 23, 46, 0.4))), -webkit-gradient(linear, 0 0, 0 100%, color-stop(0, #7b5cb5), color-stop(0.5, #572bad), color-stop(0.5, #4a1aab), color-stop(1, #4b1bab)); 434 | color: #ddd; 435 | -webkit-background-clip: padding-box; } 436 | 437 | /* shiny blue (inspired by rdio iphone interface) 438 | *******************************************************************************/ 439 | .shiny-blue { 440 | background-color: #759ae9; 441 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #759ae9), color-stop(50%, #376fe0), color-stop(50%, #1a5ad9), color-stop(100%, #2463de)); 442 | background-image: -webkit-linear-gradient(top, #759ae9 0%, #376fe0 50%, #1a5ad9 50%, #2463de 100%); 443 | background-image: -moz-linear-gradient(top, #759ae9 0%, #376fe0 50%, #1a5ad9 50%, #2463de 100%); 444 | background-image: -ms-linear-gradient(top, #759ae9 0%, #376fe0 50%, #1a5ad9 50%, #2463de 100%); 445 | background-image: -o-linear-gradient(top, #759ae9 0%, #376fe0 50%, #1a5ad9 50%, #2463de 100%); 446 | background-image: linear-gradient(top, #759ae9 0%, #376fe0 50%, #1a5ad9 50%, #2463de 100%); 447 | border-top: 1px solid #1f58cc; 448 | border-right: 1px solid #1b4db3; 449 | border-bottom: 1px solid #174299; 450 | border-left: 1px solid #1b4db3; 451 | border-radius: 4px; 452 | -webkit-box-shadow: inset 0 0 2px 0 rgba(57, 140, 255, 0.8); 453 | box-shadow: inset 0 0 2px 0 rgba(57, 140, 255, 0.8); 454 | color: #fff; 455 | font: bold 12px/1 "helvetica neue", helvetica, arial, sans-serif; 456 | padding: 7px 0; 457 | text-shadow: 0 -1px 1px #1a5ad9; 458 | /*width: 150px; */ 459 | } 460 | .shiny-blue:hover { 461 | background-color: #5d89e8; 462 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #5d89e8), color-stop(50%, #2261e0), color-stop(50%, #044bd9), color-stop(100%, #0d53de)); 463 | background-image: -webkit-linear-gradient(top, #5d89e8 0%, #2261e0 50%, #044bd9 50%, #0d53de 100%); 464 | background-image: -moz-linear-gradient(top, #5d89e8 0%, #2261e0 50%, #044bd9 50%, #0d53de 100%); 465 | background-image: -ms-linear-gradient(top, #5d89e8 0%, #2261e0 50%, #044bd9 50%, #0d53de 100%); 466 | background-image: -o-linear-gradient(top, #5d89e8 0%, #2261e0 50%, #044bd9 50%, #0d53de 100%); 467 | background-image: linear-gradient(top, #5d89e8 0%, #2261e0 50%, #044bd9 50%, #0d53de 100%); 468 | cursor: pointer; } 469 | .shiny-blue:active { 470 | border-top: 1px solid #1b4db3; 471 | border-right: 1px solid #174299; 472 | border-bottom: 1px solid #133780; 473 | border-left: 1px solid #174299; 474 | -webkit-box-shadow: inset 0 0 5px 2px #1a47a0, 0 1px 0 #eeeeee; 475 | box-shadow: inset 0 0 5px 2px #1a47a0, 0 1px 0 #eeeeee; } 476 | 477 | /* download itunes 478 | I wrote a blog post about creating this button: 479 | http://robots.thoughtbot.com/post/2718077289/make-css3-buttons-like-a-boss 480 | *******************************************************************************/ 481 | ;.download-itunes { 482 | background-color: #52a8e8; 483 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #52a8e8), color-stop(100%, #377ad0)); 484 | background-image: -webkit-linear-gradient(top, #52a8e8, #377ad0); 485 | background-image: -moz-linear-gradient(top, #52a8e8, #377ad0); 486 | background-image: -ms-linear-gradient(top, #52a8e8, #377ad0); 487 | background-image: -o-linear-gradient(top, #52a8e8, #377ad0); 488 | background-image: linear-gradient(top, #52a8e8, #377ad0); 489 | border-top: 1px solid #4081af; 490 | border-right: 1px solid #2e69a3; 491 | border-bottom: 1px solid #20559a; 492 | border-left: 1px solid #2e69a3; 493 | border-radius: 16px; 494 | -webkit-box-shadow: inset 0 1px 0 0 #72b9eb, 0 1px 2px 0 #b3b3b3; 495 | box-shadow: inset 0 1px 0 0 #72b9eb, 0 1px 2px 0 #b3b3b3; 496 | color: #fff; 497 | font: normal 11px/1 "lucida grande", sans-serif; 498 | padding: 3px 5px; 499 | text-align: center; 500 | text-shadow: 0 -1px 1px #3275bc; 501 | width: 112px; 502 | -webkit-background-clip: padding-box; } 503 | ;.download-itunes:hover { 504 | background-color: #3e9ee5; 505 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #3e9ee5), color-stop(100%, #206bcb)); 506 | background-image: -webkit-linear-gradient(top, #3e9ee5 0%, #206bcb 100%); 507 | background-image: -moz-linear-gradient(top, #3e9ee5 0%, #206bcb 100%); 508 | background-image: -ms-linear-gradient(top, #3e9ee5 0%, #206bcb 100%); 509 | background-image: -o-linear-gradient(top, #3e9ee5 0%, #206bcb 100%); 510 | background-image: linear-gradient(top, #3e9ee5 0%, #206bcb 100%); 511 | border-top: 1px solid #2a73a6; 512 | border-right: 1px solid #165899; 513 | border-bottom: 1px solid #07428f; 514 | border-left: 1px solid #165899; 515 | -webkit-box-shadow: inset 0 1px 0 0 #62b1e9; 516 | box-shadow: inset 0 1px 0 0 #62b1e9; 517 | cursor: pointer; 518 | text-shadow: 0 -1px 1px #1d62ab; 519 | -webkit-background-clip: padding-box; } 520 | ;.download-itunes:active { 521 | background: #3282d3; 522 | border: 1px solid #154c8c; 523 | border-bottom: 1px solid #0e408e; 524 | -webkit-box-shadow: inset 0 0 6px 3px #1657b5, 0 1px 0 0 white; 525 | box-shadow: inset 0 0 6px 3px #1657b5, 0 1px 0 0 white; 526 | text-shadow: 0 -1px 1px #2361a4; 527 | -webkit-background-clip: padding-box; } 528 | 529 | button[disabled].download-itunes, 530 | button[disabled].download-itunes:hover, 531 | button[disabled].download-itunes:active { 532 | background-color: #dadada; 533 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #dadada), color-stop(100%, #f3f3f3)); 534 | background-image: -webkit-linear-gradient(top, #dadada, #f3f3f3); 535 | background-image: -moz-linear-gradient(top, #dadada, #f3f3f3); 536 | background-image: -ms-linear-gradient(top, #dadada, #f3f3f3); 537 | background-image: -o-linear-gradient(top, #dadada, #f3f3f3); 538 | background-image: linear-gradient(top, #dadada, #f3f3f3); 539 | border-top: 1px solid #c5c5c5; 540 | border-right: 1px solid #cecece; 541 | border-bottom: 1px solid #d9d9d9; 542 | border-left: 1px solid #cecece; 543 | -webkit-box-shadow: none; 544 | box-shadow: none; 545 | color: #8f8f8f; 546 | cursor: not-allowed; 547 | text-shadow: 0 -1px 1px #ebebeb; } 548 | 549 | ;.download-itunes::-moz-focus-inner { 550 | border: 0; 551 | padding: 0; } 552 | 553 | /* skip (inspired by okcupid iphone interface) 554 | *******************************************************************************/ 555 | ;.skip { 556 | background-color: #8c9cbf; 557 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #8c9cbf), color-stop(50%, #546a9e), color-stop(50%, #36518f), color-stop(100%, #3d5691)); 558 | background-image: -webkit-linear-gradient(top, #8c9cbf 0%, #546a9e 50%, #36518f 50%, #3d5691 100%); 559 | background-image: -moz-linear-gradient(top, #8c9cbf 0%, #546a9e 50%, #36518f 50%, #3d5691 100%); 560 | background-image: -ms-linear-gradient(top, #8c9cbf 0%, #546a9e 50%, #36518f 50%, #3d5691 100%); 561 | background-image: -o-linear-gradient(top, #8c9cbf 0%, #546a9e 50%, #36518f 50%, #3d5691 100%); 562 | background-image: linear-gradient(top, #8c9cbf 0%, #546a9e 50%, #36518f 50%, #3d5691 100%); 563 | border: 1px solid #172d6e; 564 | border-bottom: 1px solid #0e1d45; 565 | border-radius: 5px; 566 | -webkit-box-shadow: inset 0 1px 0 0 #b1b9cb; 567 | box-shadow: inset 0 1px 0 0 #b1b9cb; 568 | color: #fff; 569 | font: bold 16px/1 "helvetica neue", helvetica, arial, sans-serif; 570 | padding: 7px 0 8px 0; 571 | text-decoration: none; 572 | text-align: center; 573 | text-shadow: 0 -1px 1px #000f4d; 574 | width: 150px; } 575 | ;.skip:hover { 576 | background-color: #7f8dad; 577 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #7f8dad), color-stop(50%, #4a5e8c), color-stop(50%, #2f477d), color-stop(100%, #364c80)); 578 | background-image: -webkit-linear-gradient(top, #7f8dad 0%, #4a5e8c 50%, #2f477d 50%, #364c80 100%); 579 | background-image: -moz-linear-gradient(top, #7f8dad 0%, #4a5e8c 50%, #2f477d 50%, #364c80 100%); 580 | background-image: -ms-linear-gradient(top, #7f8dad 0%, #4a5e8c 50%, #2f477d 50%, #364c80 100%); 581 | background-image: -o-linear-gradient(top, #7f8dad 0%, #4a5e8c 50%, #2f477d 50%, #364c80 100%); 582 | background-image: linear-gradient(top, #7f8dad 0%, #4a5e8c 50%, #2f477d 50%, #364c80 100%); 583 | cursor: pointer; } 584 | ;.skip:active { 585 | -webkit-box-shadow: inset 0 0 20px 0 #1d2845, 0 1px 0 white; 586 | box-shadow: inset 0 0 20px 0 #1d2845, 0 1px 0 white; } 587 | 588 | /* minimal indent (inspired by okcupid iphone interface) 589 | *******************************************************************************/ 590 | div.indent { 591 | background-color: #e2e2e2; 592 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #e2e2e2), color-stop(100%, #fafafa)); 593 | background-image: -webkit-linear-gradient(top, #e2e2e2, #fafafa); 594 | background-image: -moz-linear-gradient(top, #e2e2e2, #fafafa); 595 | background-image: -ms-linear-gradient(top, #e2e2e2, #fafafa); 596 | background-image: -o-linear-gradient(top, #e2e2e2, #fafafa); 597 | background-image: linear-gradient(top, #e2e2e2, #fafafa); 598 | border-bottom: 1px solid #e7e7e7; 599 | border-left: 1px solid #eaeaea; 600 | border-right: 1px solid #eaeaea; 601 | border-top: 1px solid #dfdfdf; 602 | border-radius: 8px; 603 | margin: 50px auto 0; 604 | padding: 10px 0; 605 | width: 170px; } 606 | 607 | ;.minimal-indent { 608 | background-color: #f3f3f3; 609 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f3f3f3), color-stop(50%, #dddddd), color-stop(50%, #d2d2d2), color-stop(100%, #dfdfdf)); 610 | background-image: -webkit-linear-gradient(top, #f3f3f3 0%, #dddddd 50%, #d2d2d2 50%, #dfdfdf 100%); 611 | background-image: -moz-linear-gradient(top, #f3f3f3 0%, #dddddd 50%, #d2d2d2 50%, #dfdfdf 100%); 612 | background-image: -ms-linear-gradient(top, #f3f3f3 0%, #dddddd 50%, #d2d2d2 50%, #dfdfdf 100%); 613 | background-image: -o-linear-gradient(top, #f3f3f3 0%, #dddddd 50%, #d2d2d2 50%, #dfdfdf 100%); 614 | background-image: linear-gradient(top, #f3f3f3 0%, #dddddd 50%, #d2d2d2 50%, #dfdfdf 100%); 615 | border-right: 1px solid #dfdfdf; 616 | border-bottom: 1px solid #b4b4b4; 617 | border-right: 1px solid #dfdfdf; 618 | border-radius: 5px; 619 | -webkit-box-shadow: inset 0 1px 0 0 white, 0 1px 0 0 #d5d5d5, 0 -1px 2px 1px #efefef; 620 | box-shadow: inset 0 1px 0 0 white, 0 1px 0 0 #d5d5d5, 0 -1px 2px 1px #efefef; 621 | color: #666; 622 | font: bold 16px/1 "helvetica neue", helvetica, arial, sans-serif; 623 | margin: 0; 624 | padding: 7px 0; 625 | text-shadow: 0 1px 1px #fff; 626 | width: 150px; } 627 | ;.minimal-indent:hover { 628 | background-color: #e5e5e5; 629 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #e5e5e5), color-stop(50%, #d1d1d1), color-stop(50%, #c4c4c4), color-stop(100%, #b8b8b8)); 630 | background-image: -webkit-linear-gradient(top, #e5e5e5 0%, #d1d1d1 50%, #c4c4c4 50%, #b8b8b8 100%); 631 | background-image: -moz-linear-gradient(top, #e5e5e5 0%, #d1d1d1 50%, #c4c4c4 50%, #b8b8b8 100%); 632 | background-image: -ms-linear-gradient(top, #e5e5e5 0%, #d1d1d1 50%, #c4c4c4 50%, #b8b8b8 100%); 633 | background-image: -o-linear-gradient(top, #e5e5e5 0%, #d1d1d1 50%, #c4c4c4 50%, #b8b8b8 100%); 634 | background-image: linear-gradient(top, #e5e5e5 0%, #d1d1d1 50%, #c4c4c4 50%, #b8b8b8 100%); 635 | -webkit-box-shadow: inset 0 1px 0 0 #f2f2f2, 0 1px 0 0 #c9c9c9, 0 -1px 2px 1px #e3e3e3; 636 | box-shadow: inset 0 1px 0 0 #f2f2f2, 0 1px 0 0 #c9c9c9, 0 -1px 2px 1px #e3e3e3; 637 | cursor: pointer; } 638 | ;.minimal-indent:active { 639 | -webkit-box-shadow: inset 0 0 30px 0 #999999, 0 1px 0 0 white; 640 | box-shadow: inset 0 0 30px 0 #999999, 0 1px 0 0 white; } 641 | 642 | 643 | 644 | /* disabled button styles 645 | works with this markup: 646 | *******************************************************************************/ 647 | button[disabled], 648 | button[disabled]:hover, 649 | button[disabled]:active { 650 | background: #999; 651 | border: 0; 652 | -webkit-box-shadow: none; 653 | box-shadow: none; 654 | color: #aaa; 655 | cursor: not-allowed; 656 | text-shadow: none; } 657 | 658 | -------------------------------------------------------------------------------- /catsprites.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bombledmonk/advancedsearch/25280e2e537b2bfaf073d216b4217a5c95a3f09c/catsprites.png -------------------------------------------------------------------------------- /clipboard.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * clipboard.js v1.5.8 3 | * https://zenorocha.github.io/clipboard.js 4 | * 5 | * Licensed MIT © Zeno Rocha 6 | */ 7 | !function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.Clipboard=t()}}(function(){var t,e,n;return function t(e,n,r){function o(a,s){if(!n[a]){if(!e[a]){var c="function"==typeof require&&require;if(!s&&c)return c(a,!0);if(i)return i(a,!0);var u=new Error("Cannot find module '"+a+"'");throw u.code="MODULE_NOT_FOUND",u}var l=n[a]={exports:{}};e[a][0].call(l.exports,function(t){var n=e[a][1][t];return o(n?n:t)},l,l.exports,t,e,n,r)}return n[a].exports}for(var i="function"==typeof require&&require,a=0;ar;r++)n[r].fn.apply(n[r].ctx,e);return this},off:function(t,e){var n=this.e||(this.e={}),r=n[t],o=[];if(r&&e)for(var i=0,a=r.length;a>i;i++)r[i].fn!==e&&r[i].fn._!==e&&o.push(r[i]);return o.length?n[t]=o:delete n[t],this}},e.exports=r},{}],8:[function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}n.__esModule=!0;var i=function(){function t(t,e){for(var n=0;n' ).addClass( S.classes.clone ).height( height ) ); 79 | } 80 | 81 | if( !position ) { 82 | // Some browsers require fixed/absolute to report accurate top/left values. 83 | skipSettingToFixed = $el.css( 'top' ) !== 'auto' || $el.css( 'bottom' ) !== 'auto'; 84 | 85 | if( !skipSettingToFixed ) { 86 | $el.css( 'position', 'fixed' ); 87 | } 88 | 89 | position = { 90 | top: $el.css( 'top' ) !== 'auto', 91 | bottom: $el.css( 'bottom' ) !== 'auto' 92 | }; 93 | 94 | if( !skipSettingToFixed ) { 95 | $el.css( 'position', '' ); 96 | } 97 | 98 | $el.data( S.keys.position, position ); 99 | } 100 | 101 | function isFixedToTop() { 102 | var offsetTop = scroll + elTop; 103 | 104 | // Initial Offset Top 105 | return initialOffset < offsetTop && 106 | // Container Bottom 107 | offsetTop + height <= parentOffset + parentHeight; 108 | } 109 | 110 | function isFixedToBottom() { 111 | // Initial Offset Top + Height 112 | return initialOffset + ( height || 0 ) > scroll + viewportHeight - elBottom && 113 | // Container Top 114 | scroll + viewportHeight - elBottom >= parentOffset + ( height || 0 ); 115 | } 116 | 117 | elTop = getPx( $el.css( 'top' ) ); 118 | elBottom = getPx( $el.css( 'bottom' ) ); 119 | 120 | if( position.top && isFixedToTop() || position.bottom && isFixedToBottom() ) { 121 | if( !isAlreadyOn ) { 122 | toggle( true ); 123 | } 124 | } else { 125 | if( isAlreadyOn ) { 126 | toggle( false ); 127 | } 128 | } 129 | }, 130 | destroy: function( el ) { 131 | var $el = $( el ); 132 | if (S.bypass()) { 133 | return $el; 134 | } 135 | 136 | return $el.each(function() { 137 | var $this = $( this ); 138 | var id = $this.data( S.keys.id ); 139 | $( win ).unbind( '.fixedsticky' + id ); 140 | 141 | $this 142 | .removeData( [ S.keys.offset, S.keys.position, S.keys.id ] ) 143 | .removeClass( S.classes.active ) 144 | .removeClass( S.classes.inactive ) 145 | .next( '.' + S.classes.clone ).remove(); 146 | }); 147 | }, 148 | init: function( el ) { 149 | var $el = $( el ); 150 | 151 | if( S.bypass() ) { 152 | return $el; 153 | } 154 | 155 | return $el.each(function() { 156 | var _this = this; 157 | var id = uniqueIdCounter++; 158 | $( this ).data( S.keys.id, id ); 159 | 160 | $( win ).bind( 'scroll.fixedsticky' + id, function() { 161 | S.update( _this ); 162 | }).trigger( 'scroll.fixedsticky' + id ); 163 | 164 | $( win ).bind( 'resize.fixedsticky' + id , function() { 165 | if( $el.is( '.' + S.classes.active ) ) { 166 | S.update( _this ); 167 | } 168 | }); 169 | }); 170 | } 171 | }; 172 | 173 | win.FixedSticky = S; 174 | 175 | // Plugin 176 | $.fn.fixedsticky = function( method ) { 177 | if ( typeof S[ method ] === 'function') { 178 | return S[ method ].call( S, this); 179 | } else if ( typeof method === 'object' || ! method ) { 180 | return S.init.call( S, this ); 181 | } else { 182 | throw new Error( 'Method `' + method + '` does not exist on jQuery.fixedsticky' ); 183 | } 184 | }; 185 | 186 | // Add fallback when fixed-fixed is not available. 187 | if( !win.FixedFixed ) { 188 | $( win.document.documentElement ).addClass( S.classes.withoutFixedFixed ); 189 | } 190 | 191 | })( window, jQuery ); 192 | -------------------------------------------------------------------------------- /jquery-ui.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery UI CSS Framework 1.8.24 3 | * 4 | * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) 5 | * Dual licensed under the MIT or GPL Version 2 licenses. 6 | * http://jquery.org/license 7 | * 8 | * http://docs.jquery.com/UI/Theming/API 9 | */ 10 | 11 | /* Layout helpers 12 | ----------------------------------*/ 13 | .ui-helper-hidden { display: none; } 14 | .ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); } 15 | .ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } 16 | .ui-helper-clearfix:before, .ui-helper-clearfix:after { content: ""; display: table; } 17 | .ui-helper-clearfix:after { clear: both; } 18 | .ui-helper-clearfix { zoom: 1; } 19 | .ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } 20 | 21 | 22 | /* Interaction Cues 23 | ----------------------------------*/ 24 | .ui-state-disabled { cursor: default !important; } 25 | 26 | 27 | /* Icons 28 | ----------------------------------*/ 29 | 30 | /* states and images */ 31 | .ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } 32 | 33 | 34 | /* Misc visuals 35 | ----------------------------------*/ 36 | 37 | /* Overlays */ 38 | .ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } 39 | 40 | 41 | /*! 42 | * jQuery UI CSS Framework 1.8.24 43 | * 44 | * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) 45 | * Dual licensed under the MIT or GPL Version 2 licenses. 46 | * http://jquery.org/license 47 | * 48 | * http://docs.jquery.com/UI/Theming/API 49 | * 50 | * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px 51 | */ 52 | 53 | 54 | /* Component containers 55 | ----------------------------------*/ 56 | .ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; } 57 | .ui-widget .ui-widget { font-size: 1em; } 58 | .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; } 59 | .ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; } 60 | .ui-widget-content a { color: #222222; } 61 | .ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; } 62 | .ui-widget-header a { color: #222222; } 63 | 64 | /* Interaction states 65 | ----------------------------------*/ 66 | .ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; } 67 | .ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; } 68 | .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(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } 69 | .ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; } 70 | .ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } 71 | .ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; } 72 | .ui-widget :active { outline: none; } 73 | 74 | /* Interaction Cues 75 | ----------------------------------*/ 76 | .ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; } 77 | .ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; } 78 | .ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; } 79 | .ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; } 80 | .ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; } 81 | .ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } 82 | .ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } 83 | .ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } 84 | 85 | /* Icons 86 | ----------------------------------*/ 87 | 88 | /* states and images */ 89 | .ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); } 90 | .ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } 91 | .ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } 92 | .ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); } 93 | .ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); } 94 | .ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); } 95 | .ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); } 96 | .ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); } 97 | 98 | /* positioning */ 99 | .ui-icon-carat-1-n { background-position: 0 0; } 100 | .ui-icon-carat-1-ne { background-position: -16px 0; } 101 | .ui-icon-carat-1-e { background-position: -32px 0; } 102 | .ui-icon-carat-1-se { background-position: -48px 0; } 103 | .ui-icon-carat-1-s { background-position: -64px 0; } 104 | .ui-icon-carat-1-sw { background-position: -80px 0; } 105 | .ui-icon-carat-1-w { background-position: -96px 0; } 106 | .ui-icon-carat-1-nw { background-position: -112px 0; } 107 | .ui-icon-carat-2-n-s { background-position: -128px 0; } 108 | .ui-icon-carat-2-e-w { background-position: -144px 0; } 109 | .ui-icon-triangle-1-n { background-position: 0 -16px; } 110 | .ui-icon-triangle-1-ne { background-position: -16px -16px; } 111 | .ui-icon-triangle-1-e { background-position: -32px -16px; } 112 | .ui-icon-triangle-1-se { background-position: -48px -16px; } 113 | .ui-icon-triangle-1-s { background-position: -64px -16px; } 114 | .ui-icon-triangle-1-sw { background-position: -80px -16px; } 115 | .ui-icon-triangle-1-w { background-position: -96px -16px; } 116 | .ui-icon-triangle-1-nw { background-position: -112px -16px; } 117 | .ui-icon-triangle-2-n-s { background-position: -128px -16px; } 118 | .ui-icon-triangle-2-e-w { background-position: -144px -16px; } 119 | .ui-icon-arrow-1-n { background-position: 0 -32px; } 120 | .ui-icon-arrow-1-ne { background-position: -16px -32px; } 121 | .ui-icon-arrow-1-e { background-position: -32px -32px; } 122 | .ui-icon-arrow-1-se { background-position: -48px -32px; } 123 | .ui-icon-arrow-1-s { background-position: -64px -32px; } 124 | .ui-icon-arrow-1-sw { background-position: -80px -32px; } 125 | .ui-icon-arrow-1-w { background-position: -96px -32px; } 126 | .ui-icon-arrow-1-nw { background-position: -112px -32px; } 127 | .ui-icon-arrow-2-n-s { background-position: -128px -32px; } 128 | .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } 129 | .ui-icon-arrow-2-e-w { background-position: -160px -32px; } 130 | .ui-icon-arrow-2-se-nw { background-position: -176px -32px; } 131 | .ui-icon-arrowstop-1-n { background-position: -192px -32px; } 132 | .ui-icon-arrowstop-1-e { background-position: -208px -32px; } 133 | .ui-icon-arrowstop-1-s { background-position: -224px -32px; } 134 | .ui-icon-arrowstop-1-w { background-position: -240px -32px; } 135 | .ui-icon-arrowthick-1-n { background-position: 0 -48px; } 136 | .ui-icon-arrowthick-1-ne { background-position: -16px -48px; } 137 | .ui-icon-arrowthick-1-e { background-position: -32px -48px; } 138 | .ui-icon-arrowthick-1-se { background-position: -48px -48px; } 139 | .ui-icon-arrowthick-1-s { background-position: -64px -48px; } 140 | .ui-icon-arrowthick-1-sw { background-position: -80px -48px; } 141 | .ui-icon-arrowthick-1-w { background-position: -96px -48px; } 142 | .ui-icon-arrowthick-1-nw { background-position: -112px -48px; } 143 | .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } 144 | .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } 145 | .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } 146 | .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } 147 | .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } 148 | .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } 149 | .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } 150 | .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } 151 | .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } 152 | .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } 153 | .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } 154 | .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } 155 | .ui-icon-arrowreturn-1-w { background-position: -64px -64px; } 156 | .ui-icon-arrowreturn-1-n { background-position: -80px -64px; } 157 | .ui-icon-arrowreturn-1-e { background-position: -96px -64px; } 158 | .ui-icon-arrowreturn-1-s { background-position: -112px -64px; } 159 | .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } 160 | .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } 161 | .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } 162 | .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } 163 | .ui-icon-arrow-4 { background-position: 0 -80px; } 164 | .ui-icon-arrow-4-diag { background-position: -16px -80px; } 165 | .ui-icon-extlink { background-position: -32px -80px; } 166 | .ui-icon-newwin { background-position: -48px -80px; } 167 | .ui-icon-refresh { background-position: -64px -80px; } 168 | .ui-icon-shuffle { background-position: -80px -80px; } 169 | .ui-icon-transfer-e-w { background-position: -96px -80px; } 170 | .ui-icon-transferthick-e-w { background-position: -112px -80px; } 171 | .ui-icon-folder-collapsed { background-position: 0 -96px; } 172 | .ui-icon-folder-open { background-position: -16px -96px; } 173 | .ui-icon-document { background-position: -32px -96px; } 174 | .ui-icon-document-b { background-position: -48px -96px; } 175 | .ui-icon-note { background-position: -64px -96px; } 176 | .ui-icon-mail-closed { background-position: -80px -96px; } 177 | .ui-icon-mail-open { background-position: -96px -96px; } 178 | .ui-icon-suitcase { background-position: -112px -96px; } 179 | .ui-icon-comment { background-position: -128px -96px; } 180 | .ui-icon-person { background-position: -144px -96px; } 181 | .ui-icon-print { background-position: -160px -96px; } 182 | .ui-icon-trash { background-position: -176px -96px; } 183 | .ui-icon-locked { background-position: -192px -96px; } 184 | .ui-icon-unlocked { background-position: -208px -96px; } 185 | .ui-icon-bookmark { background-position: -224px -96px; } 186 | .ui-icon-tag { background-position: -240px -96px; } 187 | .ui-icon-home { background-position: 0 -112px; } 188 | .ui-icon-flag { background-position: -16px -112px; } 189 | .ui-icon-calendar { background-position: -32px -112px; } 190 | .ui-icon-cart { background-position: -48px -112px; } 191 | .ui-icon-pencil { background-position: -64px -112px; } 192 | .ui-icon-clock { background-position: -80px -112px; } 193 | .ui-icon-disk { background-position: -96px -112px; } 194 | .ui-icon-calculator { background-position: -112px -112px; } 195 | .ui-icon-zoomin { background-position: -128px -112px; } 196 | .ui-icon-zoomout { background-position: -144px -112px; } 197 | .ui-icon-search { background-position: -160px -112px; } 198 | .ui-icon-wrench { background-position: -176px -112px; } 199 | .ui-icon-gear { background-position: -192px -112px; } 200 | .ui-icon-heart { background-position: -208px -112px; } 201 | .ui-icon-star { background-position: -224px -112px; } 202 | .ui-icon-link { background-position: -240px -112px; } 203 | .ui-icon-cancel { background-position: 0 -128px; } 204 | .ui-icon-plus { background-position: -16px -128px; } 205 | .ui-icon-plusthick { background-position: -32px -128px; } 206 | .ui-icon-minus { background-position: -48px -128px; } 207 | .ui-icon-minusthick { background-position: -64px -128px; } 208 | .ui-icon-close { background-position: -80px -128px; } 209 | .ui-icon-closethick { background-position: -96px -128px; } 210 | .ui-icon-key { background-position: -112px -128px; } 211 | .ui-icon-lightbulb { background-position: -128px -128px; } 212 | .ui-icon-scissors { background-position: -144px -128px; } 213 | .ui-icon-clipboard { background-position: -160px -128px; } 214 | .ui-icon-copy { background-position: -176px -128px; } 215 | .ui-icon-contact { background-position: -192px -128px; } 216 | .ui-icon-image { background-position: -208px -128px; } 217 | .ui-icon-video { background-position: -224px -128px; } 218 | .ui-icon-script { background-position: -240px -128px; } 219 | .ui-icon-alert { background-position: 0 -144px; } 220 | .ui-icon-info { background-position: -16px -144px; } 221 | .ui-icon-notice { background-position: -32px -144px; } 222 | .ui-icon-help { background-position: -48px -144px; } 223 | .ui-icon-check { background-position: -64px -144px; } 224 | .ui-icon-bullet { background-position: -80px -144px; } 225 | .ui-icon-radio-off { background-position: -96px -144px; } 226 | .ui-icon-radio-on { background-position: -112px -144px; } 227 | .ui-icon-pin-w { background-position: -128px -144px; } 228 | .ui-icon-pin-s { background-position: -144px -144px; } 229 | .ui-icon-play { background-position: 0 -160px; } 230 | .ui-icon-pause { background-position: -16px -160px; } 231 | .ui-icon-seek-next { background-position: -32px -160px; } 232 | .ui-icon-seek-prev { background-position: -48px -160px; } 233 | .ui-icon-seek-end { background-position: -64px -160px; } 234 | .ui-icon-seek-start { background-position: -80px -160px; } 235 | /* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ 236 | .ui-icon-seek-first { background-position: -80px -160px; } 237 | .ui-icon-stop { background-position: -96px -160px; } 238 | .ui-icon-eject { background-position: -112px -160px; } 239 | .ui-icon-volume-off { background-position: -128px -160px; } 240 | .ui-icon-volume-on { background-position: -144px -160px; } 241 | .ui-icon-power { background-position: 0 -176px; } 242 | .ui-icon-signal-diag { background-position: -16px -176px; } 243 | .ui-icon-signal { background-position: -32px -176px; } 244 | .ui-icon-battery-0 { background-position: -48px -176px; } 245 | .ui-icon-battery-1 { background-position: -64px -176px; } 246 | .ui-icon-battery-2 { background-position: -80px -176px; } 247 | .ui-icon-battery-3 { background-position: -96px -176px; } 248 | .ui-icon-circle-plus { background-position: 0 -192px; } 249 | .ui-icon-circle-minus { background-position: -16px -192px; } 250 | .ui-icon-circle-close { background-position: -32px -192px; } 251 | .ui-icon-circle-triangle-e { background-position: -48px -192px; } 252 | .ui-icon-circle-triangle-s { background-position: -64px -192px; } 253 | .ui-icon-circle-triangle-w { background-position: -80px -192px; } 254 | .ui-icon-circle-triangle-n { background-position: -96px -192px; } 255 | .ui-icon-circle-arrow-e { background-position: -112px -192px; } 256 | .ui-icon-circle-arrow-s { background-position: -128px -192px; } 257 | .ui-icon-circle-arrow-w { background-position: -144px -192px; } 258 | .ui-icon-circle-arrow-n { background-position: -160px -192px; } 259 | .ui-icon-circle-zoomin { background-position: -176px -192px; } 260 | .ui-icon-circle-zoomout { background-position: -192px -192px; } 261 | .ui-icon-circle-check { background-position: -208px -192px; } 262 | .ui-icon-circlesmall-plus { background-position: 0 -208px; } 263 | .ui-icon-circlesmall-minus { background-position: -16px -208px; } 264 | .ui-icon-circlesmall-close { background-position: -32px -208px; } 265 | .ui-icon-squaresmall-plus { background-position: -48px -208px; } 266 | .ui-icon-squaresmall-minus { background-position: -64px -208px; } 267 | .ui-icon-squaresmall-close { background-position: -80px -208px; } 268 | .ui-icon-grip-dotted-vertical { background-position: 0 -224px; } 269 | .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } 270 | .ui-icon-grip-solid-vertical { background-position: -32px -224px; } 271 | .ui-icon-grip-solid-horizontal { background-position: -48px -224px; } 272 | .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } 273 | .ui-icon-grip-diagonal-se { background-position: -80px -224px; } 274 | 275 | 276 | /* Misc visuals 277 | ----------------------------------*/ 278 | 279 | /* Corner radius */ 280 | .ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -khtml-border-top-left-radius: 4px; border-top-left-radius: 4px; } 281 | .ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -khtml-border-top-right-radius: 4px; border-top-right-radius: 4px; } 282 | .ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -khtml-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; } 283 | .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; } 284 | 285 | /* Overlays */ 286 | .ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); } 287 | .ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(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; }/*! 288 | * jQuery UI Resizable 1.8.24 289 | * 290 | * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) 291 | * Dual licensed under the MIT or GPL Version 2 licenses. 292 | * http://jquery.org/license 293 | * 294 | * http://docs.jquery.com/UI/Resizable#theming 295 | */ 296 | .ui-resizable { position: relative;} 297 | .ui-resizable-handle { position: absolute;font-size: 0.1px; display: block; } 298 | .ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } 299 | .ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; } 300 | .ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; } 301 | .ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; } 302 | .ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; } 303 | .ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; } 304 | .ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; } 305 | .ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; } 306 | .ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/*! 307 | * jQuery UI Selectable 1.8.24 308 | * 309 | * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) 310 | * Dual licensed under the MIT or GPL Version 2 licenses. 311 | * http://jquery.org/license 312 | * 313 | * http://docs.jquery.com/UI/Selectable#theming 314 | */ 315 | .ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; } 316 | /*! 317 | * jQuery UI Accordion 1.8.24 318 | * 319 | * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) 320 | * Dual licensed under the MIT or GPL Version 2 licenses. 321 | * http://jquery.org/license 322 | * 323 | * http://docs.jquery.com/UI/Accordion#theming 324 | */ 325 | /* IE/Win - Fix animation bug - #4615 */ 326 | .ui-accordion { width: 100%; } 327 | .ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; } 328 | .ui-accordion .ui-accordion-li-fix { display: inline; } 329 | .ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; } 330 | .ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; } 331 | .ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; } 332 | .ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; } 333 | .ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; } 334 | .ui-accordion .ui-accordion-content-active { display: block; } 335 | /*! 336 | * jQuery UI Autocomplete 1.8.24 337 | * 338 | * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) 339 | * Dual licensed under the MIT or GPL Version 2 licenses. 340 | * http://jquery.org/license 341 | * 342 | * http://docs.jquery.com/UI/Autocomplete#theming 343 | */ 344 | .ui-autocomplete { position: absolute; cursor: default; } 345 | 346 | /* workarounds */ 347 | * html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */ 348 | 349 | /* 350 | * jQuery UI Menu 1.8.24 351 | * 352 | * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) 353 | * Dual licensed under the MIT or GPL Version 2 licenses. 354 | * http://jquery.org/license 355 | * 356 | * http://docs.jquery.com/UI/Menu#theming 357 | */ 358 | .ui-menu { 359 | list-style:none; 360 | padding: 2px; 361 | margin: 0; 362 | display:block; 363 | float: left; 364 | } 365 | .ui-menu .ui-menu { 366 | margin-top: -3px; 367 | } 368 | .ui-menu .ui-menu-item { 369 | margin:0; 370 | padding: 0; 371 | zoom: 1; 372 | float: left; 373 | clear: left; 374 | width: 100%; 375 | } 376 | .ui-menu .ui-menu-item a { 377 | text-decoration:none; 378 | display:block; 379 | padding:.2em .4em; 380 | line-height:1.5; 381 | zoom:1; 382 | } 383 | .ui-menu .ui-menu-item a.ui-state-hover, 384 | .ui-menu .ui-menu-item a.ui-state-active { 385 | font-weight: normal; 386 | margin: -1px; 387 | } 388 | /*! 389 | * jQuery UI Button 1.8.24 390 | * 391 | * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) 392 | * Dual licensed under the MIT or GPL Version 2 licenses. 393 | * http://jquery.org/license 394 | * 395 | * http://docs.jquery.com/UI/Button#theming 396 | */ 397 | .ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */ 398 | .ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */ 399 | button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */ 400 | .ui-button-icons-only { width: 3.4em; } 401 | button.ui-button-icons-only { width: 3.7em; } 402 | 403 | /*button text element */ 404 | .ui-button .ui-button-text { display: block; line-height: 1.4; } 405 | .ui-button-text-only .ui-button-text { padding: .4em 1em; } 406 | .ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; } 407 | .ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; } 408 | .ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; } 409 | .ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; } 410 | /* no icon support for input elements, provide padding by default */ 411 | input.ui-button { padding: .4em 1em; } 412 | 413 | /*button icon element(s) */ 414 | .ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; } 415 | .ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; } 416 | .ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; } 417 | .ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } 418 | .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } 419 | 420 | /*button sets*/ 421 | .ui-buttonset { margin-right: 7px; } 422 | .ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; } 423 | 424 | /* workarounds */ 425 | button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */ 426 | /*! 427 | * jQuery UI Dialog 1.8.24 428 | * 429 | * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) 430 | * Dual licensed under the MIT or GPL Version 2 licenses. 431 | * http://jquery.org/license 432 | * 433 | * http://docs.jquery.com/UI/Dialog#theming 434 | */ 435 | .ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; } 436 | .ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; } 437 | .ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; } 438 | .ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; } 439 | .ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; } 440 | .ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; } 441 | .ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; } 442 | .ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; } 443 | .ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; } 444 | .ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; } 445 | .ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } 446 | .ui-draggable .ui-dialog-titlebar { cursor: move; } 447 | /*! 448 | * jQuery UI Slider 1.8.24 449 | * 450 | * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) 451 | * Dual licensed under the MIT or GPL Version 2 licenses. 452 | * http://jquery.org/license 453 | * 454 | * http://docs.jquery.com/UI/Slider#theming 455 | */ 456 | .ui-slider { position: relative; text-align: left; } 457 | .ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; } 458 | .ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; } 459 | 460 | .ui-slider-horizontal { height: .8em; } 461 | .ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; } 462 | .ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } 463 | .ui-slider-horizontal .ui-slider-range-min { left: 0; } 464 | .ui-slider-horizontal .ui-slider-range-max { right: 0; } 465 | 466 | .ui-slider-vertical { width: .8em; height: 100px; } 467 | .ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; } 468 | .ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } 469 | .ui-slider-vertical .ui-slider-range-min { bottom: 0; } 470 | .ui-slider-vertical .ui-slider-range-max { top: 0; }/*! 471 | * jQuery UI Tabs 1.8.24 472 | * 473 | * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) 474 | * Dual licensed under the MIT or GPL Version 2 licenses. 475 | * http://jquery.org/license 476 | * 477 | * http://docs.jquery.com/UI/Tabs#theming 478 | */ 479 | .ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ 480 | .ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; } 481 | .ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; } 482 | .ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; } 483 | .ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; } 484 | .ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; } 485 | .ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ 486 | .ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; } 487 | .ui-tabs .ui-tabs-hide { display: none !important; } 488 | /*! 489 | * jQuery UI Datepicker 1.8.24 490 | * 491 | * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) 492 | * Dual licensed under the MIT or GPL Version 2 licenses. 493 | * http://jquery.org/license 494 | * 495 | * http://docs.jquery.com/UI/Datepicker#theming 496 | */ 497 | .ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; } 498 | .ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; } 499 | .ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; } 500 | .ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; } 501 | .ui-datepicker .ui-datepicker-prev { left:2px; } 502 | .ui-datepicker .ui-datepicker-next { right:2px; } 503 | .ui-datepicker .ui-datepicker-prev-hover { left:1px; } 504 | .ui-datepicker .ui-datepicker-next-hover { right:1px; } 505 | .ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; } 506 | .ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; } 507 | .ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; } 508 | .ui-datepicker select.ui-datepicker-month-year {width: 100%;} 509 | .ui-datepicker select.ui-datepicker-month, 510 | .ui-datepicker select.ui-datepicker-year { width: 49%;} 511 | .ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; } 512 | .ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; } 513 | .ui-datepicker td { border: 0; padding: 1px; } 514 | .ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; } 515 | .ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; } 516 | .ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; } 517 | .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; } 518 | 519 | /* with multiple calendars */ 520 | .ui-datepicker.ui-datepicker-multi { width:auto; } 521 | .ui-datepicker-multi .ui-datepicker-group { float:left; } 522 | .ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; } 523 | .ui-datepicker-multi-2 .ui-datepicker-group { width:50%; } 524 | .ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; } 525 | .ui-datepicker-multi-4 .ui-datepicker-group { width:25%; } 526 | .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; } 527 | .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; } 528 | .ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; } 529 | .ui-datepicker-row-break { clear:both; width:100%; font-size:0em; } 530 | 531 | /* RTL support */ 532 | .ui-datepicker-rtl { direction: rtl; } 533 | .ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; } 534 | .ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; } 535 | .ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; } 536 | .ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; } 537 | .ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; } 538 | .ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; } 539 | .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; } 540 | .ui-datepicker-rtl .ui-datepicker-group { float:right; } 541 | .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; } 542 | .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; } 543 | 544 | /* IE6 IFRAME FIX (taken from datepicker 1.5.3 */ 545 | .ui-datepicker-cover { 546 | position: absolute; /*must have*/ 547 | z-index: -1; /*must have*/ 548 | filter: mask(); /*must have*/ 549 | top: -4px; /*must have*/ 550 | left: -4px; /*must have*/ 551 | width: 200px; /*must have*/ 552 | height: 200px; /*must have*/ 553 | }/*! 554 | * jQuery UI Progressbar 1.8.24 555 | * 556 | * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) 557 | * Dual licensed under the MIT or GPL Version 2 licenses. 558 | * http://jquery.org/license 559 | * 560 | * http://docs.jquery.com/UI/Progressbar#theming 561 | */ 562 | .ui-progressbar { height:2em; text-align: left; overflow: hidden; } 563 | .ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; } -------------------------------------------------------------------------------- /jquery.dragtable.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * dragtable - jquery ui widget to re-order table columns 3 | * version 3.0 4 | * 5 | * Copyright (c) 2010, Jesse Baird 6 | * 12/2/2010 7 | * https://github.com/jebaird/dragtable 8 | * 9 | * Dual licensed under the MIT (MIT-LICENSE.txt) 10 | * and GPL (GPL-LICENSE.txt) licenses. 11 | * 12 | * 13 | * 14 | * Forked from https://github.com/akottr/dragtable - Andres Koetter akottr@gmail.com 15 | * 16 | * 17 | * 18 | * 19 | * quick down and and dirty on how this works 20 | * ########################################### 21 | * so when a column is selected we grab all of the cells in that row and clone append them to a semi copy of the parent table and the 22 | * "real" cells get a place holder class witch is removed when the dragstop event is triggered 23 | * 24 | * 25 | * make it easy to have a button swap columns 26 | * 27 | * 28 | * Events - in order of trigger 29 | * start - when the user mouses down on handle or th, use in favor of display helper 30 | * beforeChange - called when a col will be moved 31 | * change - called after the col has been moved 32 | * stop - the user mouses up and stops dragging and the drag display is removed from the dom 33 | * 34 | * 35 | * 36 | * 37 | * IE notes 38 | * ie8 in quirks mode will only drag once after that the events are lost 39 | * 40 | */ 41 | 42 | (function($) { 43 | $.widget("jb.dragtable", { 44 | //TODO: implement this 45 | eventWidgetPrefix: 'dragtable', 46 | options: { 47 | //used to the col headers, data contained in here is used to set / get the name of the col 48 | dataHeader:'data-header', 49 | //class name that handles have 50 | handle:'dragtable-drag-handle', 51 | //draggable items in cols, .dragtable-drag-handle has to match the handle options 52 | items: 'th:not( :has( .dragtable-drag-handle ) ), .dragtable-drag-handle', 53 | //if a col header as this class, cols cant be dragged past it 54 | boundary: 'dragtable-drag-boundary', 55 | //classnames that get applied to the real td, th 56 | placeholder: 'dragtable-col-placeholder', 57 | 58 | /* 59 | the drag display will be appended to this element, 60 | if this is set to document.body and has been zeroed off the display will seem to jump 61 | 62 | Its either : parent or a dom node 63 | */ 64 | appendTarget: ':parent', 65 | //if true,this will scroll the appendTarget offsetParent when the dragDisplay is dragged past its boundaries 66 | scroll: false 67 | 68 | }, 69 | // when a col is dragged use this to find the semantic elements, for speed 70 | tableElemIndex:{ 71 | head: '0', 72 | body: '1', 73 | foot: '2' 74 | }, 75 | tbodyRegex: /(tbody|TBODY)/, 76 | theadRegex: /(thead|THEAD)/, 77 | tfootRegex: /(tfoot|TFOOT)/, 78 | 79 | _create: function() { 80 | 81 | //console.log(this); 82 | //used start/end of drag 83 | this.startIndex = null; 84 | this.endIndex = null; 85 | //the references to the table cells that are getting dragged 86 | this.currentColumnCollection = []; 87 | //the references the position of the first element in the currentColunmCollection position 88 | this.currentColumnCollectionOffset = {}; 89 | //the div wrapping the drag display table 90 | this.dragDisplay = $([]) 91 | 92 | 93 | var self = this, 94 | o = self.options, 95 | el = self.element; 96 | 97 | o.appendTarget = ( o.appendTarget === ':parent' ) ? this.element.parent() : $( o.appendTarget ); 98 | 99 | 100 | //grab the ths and the handles and bind them 101 | el.delegate(o.items, 'mousedown.' + self.widgetEventPrefix, function(e){ 102 | 103 | var $handle = $(this), 104 | elementOffsetTop = self.element.position().top; 105 | 106 | //make sure we are working with a th instead of a handle 107 | if( $handle.hasClass( o.handle ) ){ 108 | 109 | $handle = $handle.closest('th'); 110 | //change the target to the th, so the handler can pick up the offsetleft 111 | e.currentTarget = $handle.closest('th')[0] 112 | } 113 | 114 | 115 | self.getCol( $handle.index() ) 116 | .attr( 'tabindex', -1 ) 117 | .focus() 118 | .disableSelection() 119 | .css({ 120 | top: elementOffsetTop, 121 | //need to account for the scroll left of the append target, other wise the display will be off by that many pix 122 | left: ( self.currentColumnCollectionOffset.left + o.appendTarget[0].scrollLeft ) 123 | }) 124 | .appendTo( o.appendTarget ) 125 | 126 | 127 | 128 | self._mousemoveHandler( e ); 129 | //############ 130 | }); 131 | 132 | }, 133 | 134 | /* 135 | * e.currentTarget is used for figuring out offsetLeft 136 | * getCol must be called before this is 137 | * 138 | */ 139 | _mousemoveHandler: function( e ){ 140 | //call this first, catch any drag display issues 141 | this._start( e ) 142 | 143 | var self = this, 144 | o = self.options, 145 | prevMouseX = e.pageX, 146 | dragDisplayWidth = self.dragDisplay.outerWidth(), 147 | halfDragDisplayWidth = dragDisplayWidth / 2, 148 | appendTargetOP = o.appendTarget.offsetParent()[0], 149 | scroll = o.scroll, 150 | //get the col count, used to contain col swap 151 | colCount = self.element[ 0 ] 152 | .getElementsByTagName( 'thead' )[ 0 ] 153 | .getElementsByTagName( 'tr' )[ 0 ] 154 | .getElementsByTagName( 'th' ) 155 | .length - 1; 156 | 157 | $( document ).bind('mousemove.' + self.widgetEventPrefix, function( e ){ 158 | var columnPos = self._setCurrentColumnCollectionOffset(), 159 | mouseXDiff = e.pageX - prevMouseX, 160 | appendTarget = o.appendTarget[0], 161 | left = ( parseInt( self.dragDisplay[0].style.left ) + mouseXDiff ); 162 | self.dragDisplay.css( 'left', left ) 163 | 164 | /* 165 | * when moving left and e.pageX and prevMouseX are the same it will trigger right when moving left 166 | * 167 | * it should only swap cols when the col dragging is half over the prev/next col 168 | */ 169 | if( e.pageX < prevMouseX ){ 170 | //move left 171 | var threshold = columnPos.left - halfDragDisplayWidth; 172 | 173 | 174 | //scroll left 175 | if( left < ( appendTarget.clientWidth - dragDisplayWidth ) && scroll == true ) { 176 | var scrollLeft = appendTarget.scrollLeft + mouseXDiff 177 | /* 178 | * firefox does scroll the body with target being body but chome does 179 | */ 180 | if( appendTarget.tagName == 'BODY' ) { 181 | window.scroll( window.scrollX + scrollLeft, window.scrollY ); 182 | } else { 183 | appendTarget.scrollLeft = scrollLeft; 184 | } 185 | 186 | } 187 | 188 | 189 | if( left < threshold ){ 190 | self._swapCol(self.startIndex-1); 191 | } 192 | 193 | }else{ 194 | //move right 195 | var threshold = columnPos.left + halfDragDisplayWidth ; 196 | 197 | //scroll right 198 | if( left > (appendTarget.clientWidth - dragDisplayWidth ) && scroll == true ) { 199 | //console.log( o.appendTarget[0].clientWidth + (e.pageX - prevMouseX)) 200 | 201 | var scrollLeft = appendTarget.scrollLeft + mouseXDiff 202 | /* 203 | * firefox does scroll the body with target being body but chome does 204 | */ 205 | if( appendTarget.tagName == 'BODY' ) { 206 | window.scroll( window.scrollX + scrollLeft, window.scrollY ); 207 | } else { 208 | appendTarget.scrollLeft = scrollLeft; 209 | } 210 | 211 | } 212 | 213 | //move to the right only if x is greater than threshold and the current col isn' the last one 214 | if( left > threshold && colCount != self.startIndex ){ 215 | self._swapCol( self.startIndex + 1 ); 216 | } 217 | } 218 | //update mouse position 219 | prevMouseX = e.pageX; 220 | 221 | }) 222 | .one( 'mouseup.' + self.widgetEventPrefix ,function(e ){ 223 | self._stop( e ); 224 | }); 225 | 226 | }, 227 | 228 | _start: function( e ){ 229 | 230 | $( document ) 231 | //move disableselection and cursor to default handlers of the start event 232 | .disableSelection() 233 | .css( 'cursor', 'move'); 234 | 235 | // guess the width of the column that is getting dragged and apply it to the drag display. fixes issues with 236 | // cols / tables having fixed widths 237 | this.dragDisplay.width( this.currentColumnCollection[0].clientWidth ) 238 | 239 | return this._eventHelper('start',e); 240 | 241 | }, 242 | _stop: function( e ){ 243 | 244 | // issue #25 reorder the stop event order always remove the stop event 245 | $( document ) 246 | .unbind( 'mousemove.' + this.widgetEventPrefix ) 247 | .enableSelection() 248 | .css( 'cursor', ''); 249 | 250 | // clean up 251 | this 252 | .dropCol() 253 | .dragDisplay.remove(); 254 | // let the world know we have stopped 255 | this._eventHelper('stop',e,{}); 256 | 257 | 258 | }, 259 | 260 | _setOption: function(option, value) { 261 | $.Widget.prototype._setOption.apply( this, arguments ); 262 | 263 | }, 264 | 265 | /* 266 | * get the selected index cell out of table row 267 | * needs to work as fast as possible. and performance gains in this method are worth the time 268 | * because its used to build the drag display and get the cells on col swap 269 | * http://jsperf.com/binary-regex-vs-string-equality/4 270 | */ 271 | _getCells: function( elem, index ){ 272 | //console.time('getcells'); 273 | var td, 274 | parentNodeName, 275 | ei = this.tableElemIndex, 276 | //TODO: clean up this format 277 | tds = { 278 | //store where the cells came from 279 | 'semantic':{ 280 | '0': [],//head throws error if ei.head or ei['head'] 281 | '1': [],//body 282 | '2': []//footer 283 | }, 284 | //keep a ref in a flat array for easy access 285 | 'array':[] 286 | }, 287 | //cache regex, reduces looking up the chain 288 | theadRegex = this.theadRegex, 289 | tbodyRegex = this.tbodyRegex, 290 | tfootRegex = this.tfootRegex, 291 | 292 | 293 | tdsSemanticHead = tds.semantic[ei.head], 294 | tdsSemanticBody = tds.semantic[ei.body], 295 | tdsSemanticFoot = tds.semantic[ei.foot]; 296 | 297 | //console.log(index); 298 | //check does this col exsist 299 | if(index <= -1 || typeof elem.rows[0].cells[index] == undefined){ 300 | return tds; 301 | } 302 | 303 | for(var i = 0, length = elem.rows.length; i < length; i++){ 304 | 305 | td = elem.rows[i].cells[index]; 306 | 307 | //if the row has no cells dont error out; 308 | if( td == undefined ){ 309 | continue; 310 | } 311 | 312 | parentNodeName = td.parentNode.parentNode.nodeName; 313 | tds.array.push(td); 314 | //faster to leave out ^ and $ in the regular expression 315 | if( tbodyRegex.test( parentNodeName ) ){ 316 | 317 | tdsSemanticBody.push( td ); 318 | 319 | }else if( theadRegex.test( parentNodeName ) ){ 320 | 321 | tdsSemanticHead.push( td ); 322 | 323 | }else if( this.tfootRegex.test( parentNodeName ) ){ 324 | 325 | tdsSemanticFoot.push( td ); 326 | } 327 | 328 | 329 | } 330 | 331 | return tds; 332 | }, 333 | /* 334 | * returns all element attrs in a string key="value" key2="value" 335 | */ 336 | _getElementAttributes: function(element){ 337 | 338 | var attrsString = [], 339 | attrs = element.attributes, 340 | i = 0, 341 | length = attrs.length; 342 | 343 | for( ; i < length; i++) { 344 | attrsString.push( attrs[i].nodeName + '="' + attrs[i].value+'"' ); 345 | } 346 | return attrsString.join(' '); 347 | }, 348 | 349 | /* 350 | * faster than swap nodes 351 | * only works if a b parent are the same, works great for columns 352 | */ 353 | _swapCells: function(a, b) { 354 | a.parentNode.insertBefore(b, a); 355 | }, 356 | 357 | /* 358 | * used to trigger optional events 359 | */ 360 | _eventHelper: function(eventName ,eventObj, additionalData){ 361 | return this._trigger( 362 | eventName, 363 | eventObj, 364 | $.extend({ 365 | column: this.currentColumnCollection, 366 | order: this.order(), 367 | startIndex: this.startIndex, 368 | endIndex: this.endIndex, 369 | dragDisplay: this.dragDisplay, 370 | columnOffset: this.currentColumnCollectionOffset 371 | },additionalData) 372 | ); 373 | }, 374 | /* 375 | * build copy of table and attach the selected col to it, also removes the select col out of the table 376 | * @returns copy of table with the selected col 377 | * 378 | * populates self.dragDisplay 379 | * TODO: name this something better, like select col or get dragDisplay 380 | * 381 | */ 382 | getCol: function(index){ 383 | //console.log('index of col '+index); 384 | //drag display is just simple html 385 | 386 | var target, 387 | cells, 388 | clone, 389 | tr, 390 | i, 391 | length, 392 | $table = this.element, 393 | self = this, 394 | eIndex = self.tableElemIndex, 395 | placholderClassnames = ' ' + this.options.placeholder;; 396 | 397 | //BUG: IE thinks that this table is disabled, dont know how that happend 398 | self.dragDisplay = $('
') 399 | .addClass('dragtable-drag-col'); 400 | 401 | //start and end are the same to start out with 402 | self.startIndex = self.endIndex = index; 403 | 404 | 405 | cells = self._getCells($table[0], index); 406 | self.currentColumnCollection = cells.array; 407 | 408 | //################################ 409 | 410 | //TODO: convert to for in // its faster than each 411 | $.each(cells.semantic,function(k,collection){ 412 | //dont bother processing if there is nothing here 413 | 414 | if(collection.length == 0){ 415 | return; 416 | } 417 | 418 | if ( k == '0' ){ 419 | target = document.createElement('thead'); 420 | self.dragDisplay[0].appendChild(target); 421 | 422 | }else if ( k == 1 ) { 423 | target = document.createElement('tbody'); 424 | self.dragDisplay[0].appendChild(target); 425 | 426 | }else { 427 | target = document.createElement('tfoot'); 428 | self.dragDisplay[0].appendChild(target); 429 | } 430 | 431 | for(i = 0,length = collection.length; i < length; i++){ 432 | 433 | clone = collection[i].cloneNode(true); 434 | collection[i].className+=placholderClassnames; 435 | tr = document.createElement('tr'); 436 | tr.appendChild(clone); 437 | 438 | target.appendChild(tr); 439 | 440 | } 441 | }); 442 | 443 | 444 | this._setCurrentColumnCollectionOffset(); 445 | 446 | 447 | self.dragDisplay = $('
').append(self.dragDisplay) 448 | return self.dragDisplay; 449 | }, 450 | 451 | 452 | _setCurrentColumnCollectionOffset: function(){ 453 | return this.currentColumnCollectionOffset = $( this.currentColumnCollection[0] ).position(); 454 | }, 455 | 456 | /* 457 | * move column left or right 458 | */ 459 | _swapCol: function( to ){ 460 | 461 | //cant swap if same position 462 | if(to == this.startIndex){ 463 | return false; 464 | } 465 | 466 | var from = this.startIndex; 467 | this.endIndex = to; 468 | //this col cant be moved past me 469 | var th = this.element.find('th').eq( to ); 470 | //check on th 471 | if( th.hasClass( this.options.boundary ) == true ){ 472 | return false; 473 | } 474 | //check handle element 475 | if( th.find( '.' + this.options.handle ).hasClass( this.options.boundary ) == true ){ 476 | return false; 477 | } 478 | 479 | if( this._eventHelper('beforeChange',{}) === false ){ 480 | return false; 481 | }; 482 | 483 | 484 | if(from < to) { 485 | //console.log('move right'); 486 | for(var i = from; i < to; i++) { 487 | var row2 = this._getCells(this.element[0],i+1); 488 | // console.log(row2) 489 | for(var j = 0, length = row2.array.length; j < length; j++){ 490 | this._swapCells(this.currentColumnCollection[j],row2.array[j]); 491 | } 492 | } 493 | } else { 494 | //console.log('move left'); 495 | for(var i = from; i > to; i--) { 496 | var row2 = this._getCells(this.element[0],i-1); 497 | for(var j = 0, length = row2.array.length; j < length; j++){ 498 | this._swapCells(row2.array[j],this.currentColumnCollection[j]); 499 | } 500 | } 501 | } 502 | this._eventHelper('change',{}); 503 | 504 | this.startIndex = this.endIndex; 505 | }, 506 | /* 507 | * called when drag start is finished 508 | */ 509 | dropCol: function(){ 510 | //TODO: cache this when the option is set 511 | var regex = new RegExp("(?:^|\\s)" + this.options.placeholder + "(?!\\S)",'g'); 512 | //remove placeholder class 513 | //dont use jquery.fn.removeClass for performance reasons 514 | for(var i = 0, length = this.currentColumnCollection.length; i < length; i++){ 515 | var td = this.currentColumnCollection[i]; 516 | 517 | td.className = td.className.replace(regex,'') 518 | } 519 | 520 | return this; 521 | 522 | }, 523 | /* 524 | * get / set the current order of the cols 525 | */ 526 | order: function(order){ 527 | var self = this, 528 | elem = self.element, 529 | options = self.options, 530 | headers = elem.find('thead tr:first').children('th'); 531 | 532 | 533 | if(order == undefined){ 534 | //get 535 | var ret = []; 536 | headers.each(function(){ 537 | var header = this.getAttribute(options.dataHeader); 538 | if(header == null){ 539 | //the attr is missing so grab the text and use that 540 | header = $(this).text(); 541 | } 542 | 543 | ret.push(header); 544 | 545 | }); 546 | 547 | return ret; 548 | 549 | }else{ 550 | //set 551 | //headers and order have to match up 552 | if(order.length != headers.length){ 553 | 554 | return self; 555 | } 556 | for(var i = 0, length = order.length; i < length; i++){ 557 | 558 | var start = headers.filter('['+ options.dataHeader +'='+ order[i] +']').index(); 559 | if(start != -1){ 560 | 561 | self.startIndex = start; 562 | 563 | self.currentColumnCollection = self._getCells(self.element[0], start).array; 564 | 565 | self._swapCol(i); 566 | } 567 | 568 | 569 | } 570 | return self; 571 | } 572 | }, 573 | 574 | destroy: function() { 575 | var self = this, 576 | o = self.options; 577 | 578 | this.element.undelegate( o.items, 'mousedown.' + self.widgetEventPrefix ); 579 | 580 | $( document ).unbind('.' + self.widgetEventPrefix ) 581 | 582 | } 583 | 584 | 585 | }); 586 | 587 | })(jQuery); 588 | -------------------------------------------------------------------------------- /jquery.hoverIntent.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * hoverIntent r7 // 2013.03.11 // jQuery 1.9.1+ 3 | * http://cherne.net/brian/resources/jquery.hoverIntent.html 4 | * 5 | * You may use hoverIntent under the terms of the MIT license. Basically that 6 | * means you are free to use hoverIntent as long as this header is left intact. 7 | * Copyright 2007, 2013 Brian Cherne 8 | */ 9 | 10 | /* hoverIntent is similar to jQuery's built-in "hover" method except that 11 | * instead of firing the handlerIn function immediately, hoverIntent checks 12 | * to see if the user's mouse has slowed down (beneath the sensitivity 13 | * threshold) before firing the event. The handlerOut function is only 14 | * called after a matching handlerIn. 15 | * 16 | * // basic usage ... just like .hover() 17 | * .hoverIntent( handlerIn, handlerOut ) 18 | * .hoverIntent( handlerInOut ) 19 | * 20 | * // basic usage ... with event delegation! 21 | * .hoverIntent( handlerIn, handlerOut, selector ) 22 | * .hoverIntent( handlerInOut, selector ) 23 | * 24 | * // using a basic configuration object 25 | * .hoverIntent( config ) 26 | * 27 | * @param handlerIn function OR configuration object 28 | * @param handlerOut function OR selector for delegation OR undefined 29 | * @param selector selector OR undefined 30 | * @author Brian Cherne 31 | */ 32 | (function($) { 33 | $.fn.hoverIntent = function(handlerIn,handlerOut,selector) { 34 | 35 | // default configuration values 36 | var cfg = { 37 | interval: 100, 38 | sensitivity: 7, 39 | timeout: 0 40 | }; 41 | 42 | if ( typeof handlerIn === "object" ) { 43 | cfg = $.extend(cfg, handlerIn ); 44 | } else if ($.isFunction(handlerOut)) { 45 | cfg = $.extend(cfg, { over: handlerIn, out: handlerOut, selector: selector } ); 46 | } else { 47 | cfg = $.extend(cfg, { over: handlerIn, out: handlerIn, selector: handlerOut } ); 48 | } 49 | 50 | // instantiate variables 51 | // cX, cY = current X and Y position of mouse, updated by mousemove event 52 | // pX, pY = previous X and Y position of mouse, set by mouseover and polling interval 53 | var cX, cY, pX, pY; 54 | 55 | // A private function for getting mouse position 56 | var track = function(ev) { 57 | cX = ev.pageX; 58 | cY = ev.pageY; 59 | }; 60 | 61 | // A private function for comparing current and previous mouse position 62 | var compare = function(ev,ob) { 63 | ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); 64 | // compare mouse positions to see if they've crossed the threshold 65 | if ( ( Math.abs(pX-cX) + Math.abs(pY-cY) ) < cfg.sensitivity ) { 66 | $(ob).off("mousemove.hoverIntent",track); 67 | // set hoverIntent state to true (so mouseOut can be called) 68 | ob.hoverIntent_s = 1; 69 | return cfg.over.apply(ob,[ev]); 70 | } else { 71 | // set previous coordinates for next time 72 | pX = cX; pY = cY; 73 | // use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs) 74 | ob.hoverIntent_t = setTimeout( function(){compare(ev, ob);} , cfg.interval ); 75 | } 76 | }; 77 | 78 | // A private function for delaying the mouseOut function 79 | var delay = function(ev,ob) { 80 | ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); 81 | ob.hoverIntent_s = 0; 82 | return cfg.out.apply(ob,[ev]); 83 | }; 84 | 85 | // A private function for handling mouse 'hovering' 86 | var handleHover = function(e) { 87 | // copy objects to be passed into t (required for event object to be passed in IE) 88 | var ev = jQuery.extend({},e); 89 | var ob = this; 90 | 91 | // cancel hoverIntent timer if it exists 92 | if (ob.hoverIntent_t) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); } 93 | 94 | // if e.type == "mouseenter" 95 | if (e.type == "mouseenter") { 96 | // set "previous" X and Y position based on initial entry point 97 | pX = ev.pageX; pY = ev.pageY; 98 | // update "current" X and Y position based on mousemove 99 | $(ob).on("mousemove.hoverIntent",track); 100 | // start polling interval (self-calling timeout) to compare mouse coordinates over time 101 | if (ob.hoverIntent_s != 1) { ob.hoverIntent_t = setTimeout( function(){compare(ev,ob);} , cfg.interval );} 102 | 103 | // else e.type == "mouseleave" 104 | } else { 105 | // unbind expensive mousemove event 106 | $(ob).off("mousemove.hoverIntent",track); 107 | // if hoverIntent state is true, then call the mouseOut function after the specified delay 108 | if (ob.hoverIntent_s == 1) { ob.hoverIntent_t = setTimeout( function(){delay(ev,ob);} , cfg.timeout );} 109 | } 110 | }; 111 | 112 | // listen for mouseenter and mouseleave 113 | return this.on({'mouseenter.hoverIntent':handleHover,'mouseleave.hoverIntent':handleHover}, cfg.selector); 114 | }; 115 | })(jQuery); 116 | -------------------------------------------------------------------------------- /jquery.jqpagination.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jqPagination, a jQuery pagination plugin (obviously) 3 | * Version: 1.4 (26th July 2013) 4 | * 5 | * Copyright (C) 2013 Ben Everard 6 | * 7 | * http://beneverard.github.com/jqPagination 8 | * 9 | * This program is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU General Public License as published by 11 | * the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | 24 | (function ($) { 25 | "use strict"; 26 | 27 | $.jqPagination = function (el, options) { 28 | 29 | // To avoid scope issues, use 'base' instead of 'this' 30 | // to reference this class from internal events and functions. 31 | 32 | var base = this; 33 | 34 | // Access to jQuery and DOM versions of element 35 | base.$el = $(el); 36 | base.el = el; 37 | 38 | // get input jQuery object 39 | base.$input = base.$el.find('input'); 40 | 41 | // Add a reverse reference to the DOM object 42 | base.$el.data("jqPagination", base); 43 | 44 | base.init = function () { 45 | 46 | base.options = $.extend({}, $.jqPagination.defaultOptions, options); 47 | 48 | // if the user hasn't provided a max page number in the options try and find 49 | // the data attribute for it, if that cannot be found, use one as a max page number 50 | 51 | if (base.options.max_page === null) { 52 | 53 | if (base.$input.data('max-page') !== undefined) { 54 | base.options.max_page = base.$input.data('max-page'); 55 | } else { 56 | base.options.max_page = 1; 57 | } 58 | 59 | } 60 | 61 | // if the current-page data attribute is specified this takes priority 62 | // over the options passed in, so long as it's a number 63 | 64 | if (base.$input.data('current-page') !== undefined && base.isNumber(base.$input.data('current-page'))) { 65 | base.options.current_page = base.$input.data('current-page'); 66 | } 67 | 68 | // remove the readonly attribute as JavaScript must be working by now ;-) 69 | base.$input.removeAttr('readonly'); 70 | 71 | // set the initial input value 72 | // pass true to prevent paged callback form being fired 73 | 74 | base.updateInput(true); 75 | 76 | 77 | //*************** 78 | // BIND EVENTS 79 | 80 | base.$input.on('focus.jqPagination mouseup.jqPagination', function (event) { 81 | 82 | // if event === focus, select all text... 83 | if (event.type === 'focus') { 84 | 85 | var current_page = parseInt(base.options.current_page, 10); 86 | 87 | $(this).val(current_page).select(); 88 | 89 | } 90 | 91 | // if event === mouse up, return false. Fixes Chrome bug 92 | if (event.type === 'mouseup') { 93 | return false; 94 | } 95 | 96 | }); 97 | 98 | base.$input.on('blur.jqPagination keydown.jqPagination', function (event) { 99 | 100 | var $self = $(this), 101 | current_page = parseInt(base.options.current_page, 10); 102 | 103 | // if the user hits escape revert the input back to the original value 104 | if (event.keyCode === 27) { 105 | $self.val(current_page); 106 | $self.blur(); 107 | } 108 | 109 | // if the user hits enter, trigger blur event but DO NOT set the page value 110 | if (event.keyCode === 13) { 111 | $self.blur(); 112 | } 113 | 114 | // only set the page is the event is focusout.. aka blur 115 | if (event.type === 'blur') { 116 | base.setPage($self.val()); 117 | } 118 | 119 | }); 120 | 121 | base.$el.on('click.jqPagination', 'a', function (event) { 122 | 123 | var $self = $(this); 124 | 125 | // we don't want to do anything if we've clicked a disabled link 126 | // return false so we stop normal link action btu also drop out of this event 127 | 128 | if ($self.hasClass('disabled')) { 129 | return false; 130 | } 131 | 132 | // for mac + windows (read: other), maintain the cmd + ctrl click for new tab 133 | if (!event.metaKey && !event.ctrlKey) { 134 | event.preventDefault(); 135 | base.setPage($self.data('action')); 136 | } 137 | 138 | }); 139 | 140 | }; 141 | 142 | base.setPage = function (page, prevent_paged) { 143 | 144 | // return current_page value if getting instead of setting 145 | if (page === undefined) { 146 | return base.options.current_page; 147 | } 148 | 149 | var current_page = parseInt(base.options.current_page, 10), 150 | max_page = parseInt(base.options.max_page, 10); 151 | 152 | if (isNaN(parseInt(page, 10))) { 153 | 154 | switch (page) { 155 | 156 | case 'first': 157 | page = 1; 158 | break; 159 | 160 | case 'prev': 161 | case 'previous': 162 | page = current_page - 1; 163 | break; 164 | 165 | case 'next': 166 | page = current_page + 1; 167 | break; 168 | 169 | case 'last': 170 | page = max_page; 171 | break; 172 | 173 | } 174 | 175 | } 176 | 177 | page = parseInt(page, 10); 178 | 179 | // reject any invalid page requests 180 | if (isNaN(page) || page < 1 || page > max_page) { 181 | 182 | // update the input element 183 | base.setInputValue(current_page); 184 | 185 | return false; 186 | 187 | } 188 | 189 | // update current page options 190 | base.options.current_page = page; 191 | base.$input.data('current-page', page); 192 | 193 | // update the input element 194 | base.updateInput( prevent_paged ); 195 | 196 | }; 197 | 198 | base.setMaxPage = function (max_page, prevent_paged) { 199 | 200 | // return the max_page value if getting instead of setting 201 | if (max_page === undefined) { 202 | return base.options.max_page; 203 | } 204 | 205 | // ignore if max_page is not a number 206 | if (!base.isNumber(max_page)) { 207 | console.error('jqPagination: max_page is not a number'); 208 | return false; 209 | } 210 | 211 | // ignore if max_page is less than the current_page 212 | if (max_page < base.options.current_page) { 213 | console.error('jqPagination: max_page lower than current_page'); 214 | return false; 215 | } 216 | 217 | // set max_page options 218 | base.options.max_page = max_page; 219 | base.$input.data('max-page', max_page); 220 | 221 | // update the input element 222 | base.updateInput( prevent_paged ); 223 | 224 | }; 225 | 226 | // ATTN this isn't really the correct name is it? 227 | base.updateInput = function (prevent_paged) { 228 | 229 | var current_page = parseInt(base.options.current_page, 10); 230 | 231 | // set the input value 232 | base.setInputValue(current_page); 233 | 234 | // set the link href attributes 235 | base.setLinks(current_page); 236 | 237 | // we may want to prevent the paged callback from being fired 238 | if (prevent_paged !== true) { 239 | 240 | // fire the callback function with the current page 241 | base.options.paged(current_page); 242 | 243 | } 244 | 245 | }; 246 | 247 | base.setInputValue = function (page) { 248 | 249 | var page_string = base.options.page_string, 250 | max_page = base.options.max_page; 251 | 252 | // this looks horrible :-( 253 | page_string = page_string 254 | .replace("{current_page}", page) 255 | .replace("{max_page}", max_page); 256 | 257 | base.$input.val(page_string); 258 | 259 | }; 260 | 261 | base.isNumber = function(n) { 262 | return !isNaN(parseFloat(n)) && isFinite(n); 263 | }; 264 | 265 | base.setLinks = function (page) { 266 | 267 | var link_string = base.options.link_string, 268 | current_page = parseInt(base.options.current_page, 10), 269 | max_page = parseInt(base.options.max_page, 10); 270 | 271 | if (link_string !== '') { 272 | 273 | // set initial page numbers + make sure the page numbers aren't out of range 274 | 275 | var previous = current_page - 1; 276 | if (previous < 1) { 277 | previous = 1; 278 | } 279 | 280 | var next = current_page + 1; 281 | if (next > max_page) { 282 | next = max_page; 283 | } 284 | 285 | // apply each page number to the link string, set it back to the element href attribute 286 | base.$el.find('a.first').attr('href', link_string.replace('{page_number}', '1')); 287 | base.$el.find('a.prev, a.previous').attr('href', link_string.replace('{page_number}', previous)); 288 | base.$el.find('a.next').attr('href', link_string.replace('{page_number}', next)); 289 | base.$el.find('a.last').attr('href', link_string.replace('{page_number}', max_page)); 290 | 291 | } 292 | 293 | // set disable class on appropriate links 294 | base.$el.find('a').removeClass('disabled'); 295 | 296 | if (current_page === max_page) { 297 | base.$el.find('.next, .last').addClass('disabled'); 298 | } 299 | 300 | if (current_page === 1) { 301 | base.$el.find('.previous, .first').addClass('disabled'); 302 | } 303 | 304 | }; 305 | 306 | base.callMethod = function (method, key, value) { 307 | 308 | switch (method.toLowerCase()) { 309 | 310 | case 'option': 311 | 312 | // if we're getting, immediately return the value 313 | if ( value === undefined && typeof key !== "object" ) { 314 | return base.options[key]; 315 | } 316 | 317 | // set default object to trigger the paged event (legacy opperation) 318 | var options = {'trigger': true}, 319 | result = false; 320 | 321 | // if the key passed in is an object 322 | if($.isPlainObject(key) && !value){ 323 | $.extend(options, key) 324 | } 325 | else{ // make the key value pair part of the default object 326 | options[key] = value; 327 | } 328 | 329 | var prevent_paged = (options.trigger === false); 330 | 331 | // if current_page property is set call setPage 332 | if(options.current_page !== undefined){ 333 | result = base.setPage(options.current_page, prevent_paged); 334 | } 335 | 336 | // if max_page property is set call setMaxPage 337 | if(options.max_page !== undefined){ 338 | result = base.setMaxPage(options.max_page, prevent_paged); 339 | } 340 | 341 | // if we've not got a result fire an error and return false 342 | if( result === false ) console.error('jqPagination: cannot get / set option ' + key); 343 | return result; 344 | 345 | break; 346 | 347 | case 'destroy': 348 | 349 | base.$el 350 | .off('.jqPagination') 351 | .find('*') 352 | .off('.jqPagination'); 353 | 354 | break; 355 | 356 | default: 357 | 358 | // the function name must not exist 359 | console.error('jqPagination: method "' + method + '" does not exist'); 360 | return false; 361 | 362 | } 363 | 364 | }; 365 | 366 | // Run initializer 367 | base.init(); 368 | 369 | }; 370 | 371 | $.jqPagination.defaultOptions = { 372 | current_page : 1, 373 | link_string : '', 374 | max_page : null, 375 | page_string : 'Page {current_page} of {max_page}', 376 | paged : function () {} 377 | }; 378 | 379 | $.fn.jqPagination = function () { 380 | 381 | // get any function parameters 382 | var self = this, 383 | $self = $(self), 384 | args = Array.prototype.slice.call(arguments), 385 | result = false; 386 | 387 | // if the first argument is a string call the desired function 388 | // note: we can only do this to a single element, and not a collection of elements 389 | 390 | if (typeof args[0] === 'string') { 391 | 392 | // if we're getting, we can only get value for the first pagination element 393 | if (args[2] === undefined) { 394 | 395 | result = $self.first().data('jqPagination').callMethod(args[0], args[1]); 396 | 397 | } else { 398 | 399 | // if we're setting, set values for all pagination elements 400 | $self.each(function(){ 401 | result = $(this).data('jqPagination').callMethod(args[0], args[1], args[2]); 402 | }); 403 | 404 | } 405 | 406 | return result; 407 | } 408 | 409 | // if we're not dealing with a method, initialise plugin 410 | self.each(function () { 411 | (new $.jqPagination(this, args[0])); 412 | }); 413 | 414 | }; 415 | 416 | })(jQuery); 417 | 418 | -------------------------------------------------------------------------------- /jquery.lazyloadxt.js: -------------------------------------------------------------------------------- 1 | /*jslint browser:true, plusplus:true, vars:true */ 2 | /*jshint browser:true, jquery:true */ 3 | /*jshint -W040:false */ /* to don't alert on "this" in triggerLoadOrError */ 4 | 5 | (function ($, window, document, undefined) { 6 | 'use strict'; 7 | 8 | // options 9 | var lazyLoadXT = 'lazyLoadXT', 10 | dataLazied = 'lazied', 11 | load_error = 'load error', 12 | classLazyHidden = 'lazy-hidden', 13 | docElement = document.documentElement || document.body, 14 | // force load all images in Opera Mini and some mobile browsers without scroll event or getBoundingClientRect() 15 | forceLoad = (window.onscroll === undefined || !!window.operamini || !docElement.getBoundingClientRect), 16 | options = { 17 | autoInit: true, // auto initialize in $.ready 18 | selector: 'img[data-src]', // selector for lazyloading elements 19 | blankImage: 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7', 20 | throttle: 99, // interval (ms) for changes check 21 | forceLoad: forceLoad, // force auto load all images 22 | 23 | loadEvent: 'pageshow', // check AJAX-loaded content in jQueryMobile 24 | updateEvent: 'load orientationchange resize scroll touchmove focus', // page-modified events 25 | forceEvent: '', // force loading of all elements 26 | 27 | //onstart: null, 28 | oninit: {removeClass: 'lazy'}, // init handler 29 | onshow: {addClass: classLazyHidden}, // start loading handler 30 | onload: {removeClass: classLazyHidden, addClass: 'lazy-loaded'}, // load success handler 31 | onerror: {removeClass: classLazyHidden}, // error handler 32 | //oncomplete: null, // complete handler 33 | 34 | //scrollContainer: undefined, 35 | checkDuplicates: true 36 | }, 37 | elementOptions = { 38 | srcAttr: 'data-src', 39 | edgeX: 0, 40 | edgeY: 0, 41 | visibleOnly: true 42 | }, 43 | $window = $(window), 44 | $isFunction = $.isFunction, 45 | $extend = $.extend, 46 | $data = $.data || function (el, name) { 47 | return $(el).data(name); 48 | }, 49 | elements = [], 50 | topLazy = 0, 51 | /* 52 | waitingMode=0 : no setTimeout 53 | waitingMode=1 : setTimeout, no deferred events 54 | waitingMode=2 : setTimeout, deferred events 55 | */ 56 | waitingMode = 0; 57 | 58 | $[lazyLoadXT] = $extend(options, elementOptions, $[lazyLoadXT]); 59 | 60 | /** 61 | * Return options.prop if obj.prop is undefined, otherwise return obj.prop 62 | * @param {*} obj 63 | * @param {*} prop 64 | * @returns * 65 | */ 66 | function getOrDef(obj, prop) { 67 | return obj[prop] === undefined ? options[prop] : obj[prop]; 68 | } 69 | 70 | /** 71 | * @returns {number} 72 | */ 73 | function scrollTop() { 74 | var scroll = window.pageYOffset; 75 | return (scroll === undefined) ? docElement.scrollTop : scroll; 76 | } 77 | 78 | /** 79 | * Add new elements to lazy-load list: 80 | * $(elements).lazyLoadXT() or $(window).lazyLoadXT() 81 | * 82 | * @param {object} [overrides] override global options 83 | */ 84 | $.fn[lazyLoadXT] = function (overrides) { 85 | overrides = overrides || {}; 86 | 87 | var blankImage = getOrDef(overrides, 'blankImage'), 88 | checkDuplicates = getOrDef(overrides, 'checkDuplicates'), 89 | scrollContainer = getOrDef(overrides, 'scrollContainer'), 90 | forceShow = getOrDef(overrides, 'show'), 91 | elementOptionsOverrides = {}, 92 | prop; 93 | 94 | // empty overrides.scrollContainer is supported by both jQuery and Zepto 95 | $(scrollContainer).on('scroll', queueCheckLazyElements); 96 | 97 | for (prop in elementOptions) { 98 | elementOptionsOverrides[prop] = getOrDef(overrides, prop); 99 | } 100 | 101 | return this.each(function (index, el) { 102 | if (el === window) { 103 | $(options.selector).lazyLoadXT(overrides); 104 | } else { 105 | var duplicate = checkDuplicates && $data(el, dataLazied), 106 | $el = $(el).data(dataLazied, forceShow ? -1 : 1); 107 | 108 | // prevent duplicates 109 | if (duplicate) { 110 | queueCheckLazyElements(); 111 | return; 112 | } 113 | 114 | if (blankImage && el.tagName === 'IMG' && !el.src) { 115 | el.src = blankImage; 116 | } 117 | 118 | // clone elementOptionsOverrides object 119 | $el[lazyLoadXT] = $extend({}, elementOptionsOverrides); 120 | 121 | triggerEvent('init', $el); 122 | 123 | elements.push($el); 124 | queueCheckLazyElements(); 125 | } 126 | }); 127 | }; 128 | 129 | 130 | /** 131 | * Process function/object event handler 132 | * @param {string} event suffix 133 | * @param {jQuery} $el 134 | */ 135 | function triggerEvent(event, $el) { 136 | var handler = options['on' + event]; 137 | if (handler) { 138 | if ($isFunction(handler)) { 139 | handler.call($el[0]); 140 | } else { 141 | if (handler.addClass) { 142 | $el.addClass(handler.addClass); 143 | } 144 | if (handler.removeClass) { 145 | $el.removeClass(handler.removeClass); 146 | } 147 | } 148 | } 149 | 150 | $el.trigger('lazy' + event, [$el]); 151 | 152 | // queue next check as images may be resized after loading of actual file 153 | queueCheckLazyElements(); 154 | } 155 | 156 | 157 | /** 158 | * Trigger onload/onerror handler 159 | * @param {Event} e 160 | */ 161 | function triggerLoadOrError(e) { 162 | triggerEvent(e.type, $(this).off(load_error, triggerLoadOrError)); 163 | } 164 | 165 | 166 | /** 167 | * Load visible elements 168 | * @param {bool} [force] loading of all elements 169 | */ 170 | function checkLazyElements(force) { 171 | if (!elements.length) { 172 | return; 173 | } 174 | 175 | force = force || options.forceLoad; 176 | 177 | topLazy = Infinity; 178 | 179 | var viewportTop = scrollTop(), 180 | viewportHeight = window.innerHeight || docElement.clientHeight, 181 | viewportWidth = window.innerWidth || docElement.clientWidth, 182 | i, 183 | length; 184 | 185 | for (i = 0, length = elements.length; i < length; i++) { 186 | var $el = elements[i], 187 | el = $el[0], 188 | objData = $el[lazyLoadXT], 189 | removeNode = false, 190 | visible = force || $data(el, dataLazied) < 0, 191 | topEdge; 192 | 193 | // remove items that are not in DOM 194 | if (!$.contains(docElement, el)) { 195 | removeNode = true; 196 | } else if (force || !objData.visibleOnly || el.offsetWidth || el.offsetHeight) { 197 | 198 | if (!visible) { 199 | var elPos = el.getBoundingClientRect(), 200 | edgeX = objData.edgeX, 201 | edgeY = objData.edgeY; 202 | 203 | topEdge = (elPos.top + viewportTop - edgeY) - viewportHeight; 204 | 205 | visible = (topEdge <= viewportTop && elPos.bottom > -edgeY && 206 | elPos.left <= viewportWidth + edgeX && elPos.right > -edgeX); 207 | } 208 | 209 | if (visible) { 210 | $el.on(load_error, triggerLoadOrError); 211 | 212 | triggerEvent('show', $el); 213 | 214 | var srcAttr = objData.srcAttr, 215 | src = $isFunction(srcAttr) ? srcAttr($el) : el.getAttribute(srcAttr); 216 | 217 | if (src) { 218 | el.src = src; 219 | } 220 | 221 | removeNode = true; 222 | } else { 223 | if (topEdge < topLazy) { 224 | topLazy = topEdge; 225 | } 226 | } 227 | } 228 | 229 | if (removeNode) { 230 | elements.splice(i--, 1); 231 | length--; 232 | } 233 | } 234 | 235 | if (!length) { 236 | triggerEvent('complete', $(docElement)); 237 | } 238 | } 239 | 240 | 241 | /** 242 | * Run check of lazy elements after timeout 243 | */ 244 | function timeoutLazyElements() { 245 | if (waitingMode > 1) { 246 | waitingMode = 1; 247 | checkLazyElements(); 248 | setTimeout(timeoutLazyElements, options.throttle); 249 | } else { 250 | waitingMode = 0; 251 | } 252 | } 253 | 254 | 255 | /** 256 | * Queue check of lazy elements because of event e 257 | * @param {Event} [e] 258 | */ 259 | function queueCheckLazyElements(e) { 260 | if (!elements.length) { 261 | return; 262 | } 263 | 264 | // fast check for scroll event without new visible elements 265 | if (e && e.type === 'scroll' && e.currentTarget === window) { 266 | if (topLazy >= scrollTop()) { 267 | return; 268 | } 269 | } 270 | 271 | if (!waitingMode) { 272 | setTimeout(timeoutLazyElements, 0); 273 | } 274 | waitingMode = 2; 275 | } 276 | 277 | 278 | /** 279 | * Initialize list of hidden elements 280 | */ 281 | function initLazyElements() { 282 | $window.lazyLoadXT(); 283 | } 284 | 285 | 286 | /** 287 | * Loading of all elements 288 | */ 289 | function forceLoadAll() { 290 | checkLazyElements(true); 291 | } 292 | 293 | 294 | /** 295 | * Initialization 296 | */ 297 | $(document).ready(function () { 298 | triggerEvent('start', $window); 299 | 300 | $window 301 | .on(options.loadEvent, initLazyElements) 302 | .on(options.updateEvent, queueCheckLazyElements) 303 | .on(options.forceEvent, forceLoadAll); 304 | 305 | $(document).on(options.updateEvent, queueCheckLazyElements); 306 | 307 | if (options.autoInit) { 308 | initLazyElements(); // standard initialization 309 | } 310 | }); 311 | 312 | })(window.jQuery || window.Zepto || window.$, window, document); -------------------------------------------------------------------------------- /jquery.localScroll.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery.LocalScroll 3 | * Copyright (c) 2007-2010 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com 4 | * Dual licensed under MIT and GPL. 5 | * Date: 05/31/2010 6 | * 7 | * @projectDescription Animated scrolling navigation, using anchors. 8 | * http://flesler.blogspot.com/2007/10/jquerylocalscroll-10.html 9 | * @author Ariel Flesler 10 | * @version 1.2.8b 11 | * 12 | * @id jQuery.fn.localScroll 13 | * @param {Object} settings Hash of settings, it is passed in to jQuery.ScrollTo, none is required. 14 | * @return {jQuery} Returns the same jQuery object, for chaining. 15 | * 16 | * @example $('ul.links').localScroll(); 17 | * 18 | * @example $('ul.links').localScroll({ filter:'.animated', duration:400, axis:'x' }); 19 | * 20 | * @example $.localScroll({ target:'#pane', axis:'xy', queue:true, event:'mouseover' }); 21 | * 22 | * Notes: 23 | * - The plugin requires jQuery.ScrollTo. 24 | * - The hash of settings, is passed to jQuery.ScrollTo, so the settings are valid for that plugin as well. 25 | * - jQuery.localScroll can be used if the desired links, are all over the document, it accepts the same settings. 26 | * - If the setting 'lazy' is set to true, then the binding will still work for later added anchors. 27 | * - If onBefore returns false, the event is ignored. 28 | */ 29 | ;(function( $ ){ 30 | var URI = location.href.replace(/#.*/,''); // local url without hash 31 | 32 | var $localScroll = $.localScroll = function( settings ){ 33 | $('body').localScroll( settings ); 34 | }; 35 | 36 | // Many of these defaults, belong to jQuery.ScrollTo, check it's demo for an example of each option. 37 | // @see http://flesler.demos.com/jquery/scrollTo/ 38 | // The defaults are public and can be overriden. 39 | $localScroll.defaults = { 40 | duration:1000, // How long to animate. 41 | axis:'y', // Which of top and left should be modified. 42 | event:'click', // On which event to react. 43 | stop:true, // Avoid queuing animations 44 | target: window, // What to scroll (selector or element). The whole window by default. 45 | reset: true // Used by $.localScroll.hash. If true, elements' scroll is resetted before actual scrolling 46 | /* 47 | lock:false, // ignore events if already animating 48 | lazy:false, // if true, links can be added later, and will still work. 49 | filter:null, // filter some anchors out of the matched elements. 50 | hash: false // if true, the hash of the selected link, will appear on the address bar. 51 | */ 52 | }; 53 | 54 | // If the URL contains a hash, it will scroll to the pointed element 55 | $localScroll.hash = function( settings ){ 56 | if( location.hash ){ 57 | settings = $.extend( {}, $localScroll.defaults, settings ); 58 | settings.hash = false; // can't be true 59 | 60 | if( settings.reset ){ 61 | var d = settings.duration; 62 | delete settings.duration; 63 | $(settings.target).scrollTo( 0, settings ); 64 | settings.duration = d; 65 | } 66 | scroll( 0, location, settings ); 67 | } 68 | }; 69 | 70 | $.fn.localScroll = function( settings ){ 71 | settings = $.extend( {}, $localScroll.defaults, settings ); 72 | 73 | return settings.lazy ? 74 | // use event delegation, more links can be added later. 75 | this.bind( settings.event, function( e ){ 76 | // Could use closest(), but that would leave out jQuery -1.3.x 77 | var a = $([e.target, e.target.parentNode]).filter(filter)[0]; 78 | // if a valid link was clicked 79 | if( a ) 80 | scroll( e, a, settings ); // do scroll. 81 | }) : 82 | // bind concretely, to each matching link 83 | this.find('a,area') 84 | .filter( filter ).bind( settings.event, function(e){ 85 | scroll( e, this, settings ); 86 | }).end() 87 | .end(); 88 | 89 | function filter(){// is this a link that points to an anchor and passes a possible filter ? href is checked to avoid a bug in FF. 90 | return !!this.href && !!this.hash && this.href.replace(this.hash,'') == URI && (!settings.filter || $(this).is( settings.filter )); 91 | }; 92 | }; 93 | 94 | function scroll( e, link, settings ){ 95 | var id = link.hash.slice(1), 96 | elem = document.getElementById(id) || document.getElementsByName(id)[0]; 97 | 98 | if ( !elem ) 99 | return; 100 | 101 | if( e ) 102 | e.preventDefault(); 103 | 104 | var $target = $( settings.target ); 105 | 106 | if( settings.lock && $target.is(':animated') || 107 | settings.onBefore && settings.onBefore(e, elem, $target) === false ) 108 | return; 109 | 110 | if( settings.stop ) 111 | $target._scrollable().stop(true); // remove all its animations 112 | 113 | if( settings.hash ){ 114 | var attr = elem.id == id ? 'id' : 'name', 115 | $a = $(' ').attr(attr, id).css({ 116 | position:'absolute', 117 | top: $(window).scrollTop(), 118 | left: $(window).scrollLeft() 119 | }); 120 | 121 | elem[attr] = ''; 122 | $('body').prepend($a); 123 | location = link.hash; 124 | $a.remove(); 125 | elem[attr] = id; 126 | } 127 | 128 | $target 129 | .scrollTo( elem, settings ) // do scroll 130 | .trigger('notify.serialScroll',[elem]); // notify serialScroll about this change 131 | }; 132 | 133 | })( jQuery ); -------------------------------------------------------------------------------- /jquery.spellchecker.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery Spellchecker - v0.2.4 - 2012-12-19 3 | * https://github.com/badsyntax/jquery-spellchecker 4 | * Copyright (c) 2012 Richard Willis; Licensed MIT 5 | */ 6 | 7 | (function(window, $) { 8 | 9 | /* Config 10 | *************************/ 11 | 12 | var defaultConfig = { 13 | lang: 'en', 14 | webservice: { 15 | path: 'spellchecker.php', 16 | driver: 'PSpell' 17 | }, 18 | local: { 19 | requestError: 'There was an error processing the request.', 20 | ignoreWord: 'Ignore word', 21 | ignoreAll: 'Ignore all', 22 | ignoreForever: 'Add to dictionary', 23 | loading: 'Loading...', 24 | noSuggestions: '(No suggestions)' 25 | }, 26 | suggestBox: { 27 | numWords: 5, 28 | position: 'above', 29 | offset: 2, 30 | appendTo: null 31 | }, 32 | incorrectWords: { 33 | container: 'body', //selector 34 | position: null //function 35 | } 36 | }; 37 | 38 | var pluginName = 'spellchecker'; 39 | 40 | /* Util 41 | *************************/ 42 | 43 | if (!Function.prototype.bind) { 44 | Function.prototype.bind = function(scope) { 45 | return $.proxy(this, scope); 46 | }; 47 | } 48 | 49 | var inherits = function(_sub, _super) { 50 | function F() {} 51 | F.prototype = _super.prototype; 52 | _sub.prototype = new F(); 53 | _sub.prototype.constructor = _sub; 54 | }; 55 | 56 | var decode = function(text) { 57 | return $('
').html(text).html(); 58 | }; 59 | 60 | RegExp.escape = function(text) { 61 | return text.replace(/[\-\[\]{}()*+?.,\^$|#\s]/g, "\\$&"); 62 | }; 63 | 64 | /* Character sets 65 | *************************/ 66 | 67 | var punctuationChars = '\\u0021-\\u0023\\u0025-\\u002A\\u002C-\\u002F\\u003A\\u003B\\u003F\\u0040\\u005B-\\u005D\\u005F\\u007B\\u007D\\u00A1\\u00A7\\u00AB\\u00B6\\u00B7\\u00BB\\u00BF\\u037E\\u0387\\u055A-\\u055F\\u0589\\u058A\\u05BE\\u05C0\\u05C3\\u05C6\\u05F3\\u05F4\\u0609\\u060A\\u060C\\u060D\\u061B\\u061E\\u061F\\u066A-\\u066D\\u06D4\\u0700-\\u070D\\u07F7-\\u07F9\\u0830-\\u083E\\u085E\\u0964\\u0965\\u0970\\u0AF0\\u0DF4\\u0E4F\\u0E5A\\u0E5B\\u0F04-\\u0F12\\u0F14\\u0F3A-\\u0F3D\\u0F85\\u0FD0-\\u0FD4\\u0FD9\\u0FDA\\u104A-\\u104F\\u10FB\\u1360-\\u1368\\u1400\\u166D\\u166E\\u169B\\u169C\\u16EB-\\u16ED\\u1735\\u1736\\u17D4-\\u17D6\\u17D8-\\u17DA\\u1800-\\u180A\\u1944\\u1945\\u1A1E\\u1A1F\\u1AA0-\\u1AA6\\u1AA8-\\u1AAD\\u1B5A-\\u1B60\\u1BFC-\\u1BFF\\u1C3B-\\u1C3F\\u1C7E\\u1C7F\\u1CC0-\\u1CC7\\u1CD3\\u2010-\\u2027\\u2030-\\u2043\\u2045-\\u2051\\u2053-\\u205E\\u207D\\u207E\\u208D\\u208E\\u2329\\u232A\\u2768-\\u2775\\u27C5\\u27C6\\u27E6-\\u27EF\\u2983-\\u2998\\u29D8-\\u29DB\\u29FC\\u29FD\\u2CF9-\\u2CFC\\u2CFE\\u2CFF\\u2D70\\u2E00-\\u2E2E\\u2E30-\\u2E3B\\u3001-\\u3003\\u3008-\\u3011\\u3014-\\u301F\\u3030\\u303D\\u30A0\\u30FB\\uA4FE\\uA4FF\\uA60D-\\uA60F\\uA673\\uA67E\\uA6F2-\\uA6F7\\uA874-\\uA877\\uA8CE\\uA8CF\\uA8F8-\\uA8FA\\uA92E\\uA92F\\uA95F\\uA9C1-\\uA9CD\\uA9DE\\uA9DF\\uAA5C-\\uAA5F\\uAADE\\uAADF\\uAAF0\\uAAF1\\uABEB\\uFD3E\\uFD3F\\uFE10-\\uFE19\\uFE30-\\uFE52\\uFE54-\\uFE61\\uFE63\\uFE68\\uFE6A\\uFE6B\\uFF01-\\uFF03\\uFF05-\\uFF0A\\uFF0C-\\uFF0F\\uFF1A\\uFF1B\\uFF1F\\uFF20\\uFF3B-\\uFF3D\\uFF3F\\uFF5B\\uFF5D\\uFF5F-\\uFF65'; 68 | var letterChars = '\\u0041-\\u005A\\u0061-\\u007A\\u00AA\\u00B5\\u00BA\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u0527\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0620-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0800-\\u0815\\u081A\\u0824\\u0828\\u0840-\\u0858\\u08A0\\u08A2-\\u08AC\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971-\\u0977\\u0979-\\u097F\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C33\\u0C35-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0CF1\\u0CF2\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D\\u0D4E\\u0D60\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC-\\u0EDF\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8C\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u18B0-\\u18F5\\u1900-\\u191C\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1A20-\\u1A54\\u1AA7\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1BBA-\\u1BE5\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1CE9-\\u1CEC\\u1CEE-\\u1CF1\\u1CF5\\u1CF6\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u209C\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2183\\u2184\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CEE\\u2CF2\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005\\u3006\\u3031-\\u3035\\u303B\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FCC\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA66E\\uA67F-\\uA697\\uA6A0-\\uA6E5\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA78E\\uA790-\\uA793\\uA7A0-\\uA7AA\\uA7F8-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA8F2-\\uA8F7\\uA8FB\\uA90A-\\uA925\\uA930-\\uA946\\uA960-\\uA97C\\uA984-\\uA9B2\\uA9CF\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAA60-\\uAA76\\uAA7A\\uAA80-\\uAAAF\\uAAB1\\uAAB5\\uAAB6\\uAAB9-\\uAABD\\uAAC0\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEA\\uAAF2-\\uAAF4\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uABC0-\\uABE2\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC'; 69 | 70 | /* Events 71 | *************************/ 72 | 73 | var Events = function(){ 74 | this._handlers = {}; 75 | }; 76 | 77 | Events.prototype = { 78 | on: function(name, handler) { 79 | if (!this._handlers[name]) { 80 | this._handlers[name] = $.Callbacks(); 81 | } 82 | this._handlers[name].add(handler); 83 | }, 84 | trigger: function(name) { 85 | var args = Array.prototype.slice.call(arguments, 1); 86 | if ($.isFunction(name)) { 87 | return name.apply(this, args); 88 | } 89 | if (this._handlers[name]) { 90 | this._handlers[name].fireWith(this, args); 91 | } 92 | }, 93 | handler: function(name) { 94 | return function(e) { 95 | this.trigger(name, e); 96 | }.bind(this); 97 | } 98 | }; 99 | 100 | /* Handlers 101 | *************************/ 102 | 103 | var selectWordHandler = function(handlerName) { 104 | 105 | return function(e) { 106 | 107 | e.preventDefault(); 108 | e.stopPropagation(); 109 | 110 | var element = $(e.currentTarget); 111 | var word = $.trim(element.data('word') || element.text()); 112 | 113 | this.trigger(handlerName, e, word, element, this); 114 | 115 | }.bind(this); 116 | }; 117 | 118 | /* Collections 119 | *************************/ 120 | 121 | var Collection = function(elements, instanceFactory) { 122 | this.instances = []; 123 | for(var i = 0; i < elements.length; i++) { 124 | this.instances.push( instanceFactory(elements[i]) ); 125 | } 126 | this.methods([ 'on', 'destroy', 'trigger' ]); 127 | }; 128 | 129 | Collection.prototype.methods = function(methods) { 130 | $.each(methods, function(i, method) { 131 | this[method] = function() { 132 | this.execute(method, arguments); 133 | }.bind(this); 134 | }.bind(this)); 135 | }; 136 | 137 | Collection.prototype.execute = function(method, args) { 138 | $.each(this.instances, function(i, instance) { 139 | instance[method].apply(instance, args); 140 | }); 141 | }; 142 | 143 | Collection.prototype.get = function(i) { 144 | return this.instances[i]; 145 | }; 146 | 147 | /* Base box 148 | *************************/ 149 | 150 | var Box = function(config, parser, element) { 151 | Events.call(this); 152 | this.config = config; 153 | this.parser = parser; 154 | this.spellCheckerElement = $(element); 155 | this.createBox(); 156 | this.bindEvents(); 157 | }; 158 | inherits(Box, Events); 159 | 160 | /* Incorrect words box 161 | *************************/ 162 | 163 | var IncorrectWordsBox = function(config, parser, element) { 164 | Box.apply(this, arguments); 165 | }; 166 | inherits(IncorrectWordsBox, Box); 167 | 168 | IncorrectWordsBox.prototype.bindEvents = function() { 169 | this.container.on('click', 'a', selectWordHandler.call(this, 'select.word')); 170 | this.on('addWords', this.addWords.bind(this)); 171 | }; 172 | 173 | IncorrectWordsBox.prototype.createBox = function() { 174 | 175 | this.container = $([ 176 | '
', 177 | '
' 178 | ].join('')) 179 | .hide(); 180 | 181 | if ($.isFunction(this.config.incorrectWords.position)) { 182 | this.config.incorrectWords.position.call(this.spellCheckerElement, this.container); 183 | } else { 184 | this.container.appendTo(this.config.incorrectWords.container); 185 | } 186 | }; 187 | 188 | IncorrectWordsBox.prototype.addWords = function(words) { 189 | 190 | // Make array values unique 191 | words = $.grep(words, function(el, index){ 192 | return index === $.inArray(el, words); 193 | }); 194 | 195 | var html = $.map(words, function(word) { 196 | return '' + word + ''; 197 | }).join(''); 198 | 199 | this.container.html(html).show(); 200 | }; 201 | 202 | IncorrectWordsBox.prototype.removeWord = function(elem) { 203 | if (elem) { 204 | elem.remove(); 205 | } 206 | if (this.container.children().length === 0) { 207 | this.container.hide(); 208 | } 209 | }; 210 | 211 | IncorrectWordsBox.prototype.destroy = function() { 212 | this.container.empty().remove(); 213 | }; 214 | 215 | /* Incorrect words inline 216 | *************************/ 217 | 218 | var IncorrectWordsInline = function(config, parser, element) { 219 | Events.call(this); 220 | this.config = config; 221 | this.parser = parser; 222 | this.spellCheckerElement = this.element = $(element); 223 | this.bindEvents(); 224 | }; 225 | inherits(IncorrectWordsInline, Events); 226 | 227 | IncorrectWordsInline.prototype.bindEvents = function() { 228 | this.element.on('click.' + pluginName, '.' + pluginName + '-word-highlight', selectWordHandler.call(this, 'select.word')); 229 | }; 230 | 231 | IncorrectWordsInline.prototype.addWords = function(words) { 232 | var highlighted = this.parser.highlightWords(words, this.element); 233 | this.element.html(highlighted); 234 | }; 235 | 236 | IncorrectWordsInline.prototype.removeWord = function(elem) {}; 237 | 238 | IncorrectWordsInline.prototype.destroy = function() { 239 | this.element.off('.' + pluginName); 240 | try { 241 | window.findAndReplaceDOMText.revert(); 242 | } catch(e) {} 243 | }; 244 | 245 | /* Suggest box 246 | *************************/ 247 | 248 | var SuggestBox = function(config, element) { 249 | this.element = element; 250 | if (config.suggestBox.appendTo) { 251 | this.body = $(config.suggestBox.appendTo); 252 | } else { 253 | this.body = (this.element.length && this.element[0].nodeName === 'BODY') ? this.element : 'body'; 254 | } 255 | this.position = $.isFunction(config.suggestBox.position) ? config.suggestBox.position : this.position; 256 | Box.apply(this, arguments); 257 | }; 258 | inherits(SuggestBox, Box); 259 | 260 | SuggestBox.prototype.bindEvents = function() { 261 | var click = 'click.' + pluginName; 262 | this.container.on(click, this.onContainerClick.bind(this)); 263 | this.container.on(click, '.ignore-word', selectWordHandler.call(this, 'ignore.word')); 264 | this.container.on(click, '.ignore-all', this.handler('ignore.all')); 265 | this.container.on(click, '.ignore-forever', this.handler('ignore.forever')); 266 | this.container.on(click, '.words a', selectWordHandler.call(this, 'select.word')); 267 | $('html').on(click, this.onWindowClick.bind(this)); 268 | if (this.element[0].nodeName === 'BODY') { 269 | this.element.parent().on(click, this.onWindowClick.bind(this)); 270 | } 271 | }; 272 | 273 | SuggestBox.prototype.createBox = function() { 274 | 275 | var local = this.config.local; 276 | 277 | this.container = $([ 278 | '
', 279 | ' ', 284 | '
' 285 | ].join('')).appendTo(this.body); 286 | 287 | this.words = $([ 288 | '
', 289 | '
' 290 | ].join('')).prependTo(this.container); 291 | 292 | this.loadingMsg = $([ 293 | '
', 294 | this.config.local.loading, 295 | '
' 296 | ].join('')); 297 | 298 | this.footer = this.container.find('.footer').hide(); 299 | }; 300 | 301 | SuggestBox.prototype.addWords = function(words) { 302 | 303 | var html; 304 | 305 | if (!words.length) { 306 | html = '' + this.config.local.noSuggestions + ''; 307 | } else { 308 | html = $.map(words, function(word) { 309 | return '' + word + ''; 310 | }).slice(0, this.config.suggestBox.numWords).join(''); 311 | } 312 | 313 | this.words.html(html); 314 | }; 315 | 316 | SuggestBox.prototype.showSuggestedWords = function(getWords, word, wordElement) { 317 | this.wordElement = $(wordElement); 318 | getWords(word, this.onGetWords.bind(this)); 319 | }; 320 | 321 | SuggestBox.prototype.loading = function(show) { 322 | this.footer.hide(); 323 | this.words.html(show ? this.loadingMsg.clone() : ''); 324 | this.position(); 325 | this.open(); 326 | }; 327 | 328 | SuggestBox.prototype.position = function() { 329 | 330 | var win = $(window); 331 | var element = this.wordElement.data('firstElement') || this.wordElement; 332 | var offset = element.offset(); 333 | var boxOffset = this.config.suggestBox.offset; 334 | var containerHeight = this.container.outerHeight(); 335 | 336 | var positionAbove = (offset.top - containerHeight - boxOffset); 337 | var positionBelow = (offset.top + element.outerHeight() + boxOffset); 338 | 339 | var left = offset.left; 340 | var top; 341 | 342 | if (this.config.suggestBox.position === 'below') { 343 | top = positionBelow; 344 | if (win.height() + win.scrollTop() < positionBelow + containerHeight) { 345 | top = positionAbove; 346 | } 347 | } else { 348 | top = positionAbove; 349 | } 350 | 351 | this.container.css({ top: top, left: left }); 352 | }; 353 | 354 | SuggestBox.prototype.open = function() { 355 | this.position(); 356 | this.container.fadeIn(180); 357 | }; 358 | 359 | SuggestBox.prototype.close = function() { 360 | this.container.fadeOut(100, function(){ 361 | this.footer.hide(); 362 | }.bind(this)); 363 | }; 364 | 365 | SuggestBox.prototype.detach = function() { 366 | this.container = this.container.detach(); 367 | }; 368 | 369 | SuggestBox.prototype.reattach = function() { 370 | this.container.appendTo(this.body); 371 | }; 372 | 373 | SuggestBox.prototype.onContainerClick = function(e) { 374 | e.stopPropagation(); 375 | }; 376 | 377 | SuggestBox.prototype.onWindowClick = function(e) { 378 | this.close(); 379 | }; 380 | 381 | SuggestBox.prototype.onGetWords = function(words) { 382 | this.addWords(words); 383 | this.footer.show(); 384 | this.position(); 385 | this.open(); 386 | }; 387 | 388 | SuggestBox.prototype.destroy = function() { 389 | this.container.empty().remove(); 390 | }; 391 | 392 | /* Spellchecker web service 393 | *************************/ 394 | 395 | var WebService = function(config) { 396 | 397 | this.config = config; 398 | 399 | this.defaultConfig = { 400 | url: config.webservice.path, 401 | type: 'POST', 402 | dataType: 'json', 403 | cache: false, 404 | data: { 405 | lang: config.lang, 406 | driver: config.webservice.driver 407 | }, 408 | error: function() { 409 | alert(config.local.requestError); 410 | }.bind(this) 411 | }; 412 | }; 413 | 414 | WebService.prototype.makeRequest = function(config) { 415 | 416 | var defaultConfig = $.extend(true, {}, this.defaultConfig); 417 | 418 | return $.ajax($.extend(true, defaultConfig, config)); 419 | }; 420 | 421 | WebService.prototype.checkWords = function(text, callback) { 422 | return this.makeRequest({ 423 | data: { 424 | action: 'get_incorrect_words', 425 | text: text 426 | }, 427 | success: callback 428 | }); 429 | }; 430 | 431 | WebService.prototype.getSuggestions = function(word, callback) { 432 | return this.makeRequest({ 433 | data: { 434 | action: 'get_suggestions', 435 | word: word 436 | }, 437 | success: callback 438 | }); 439 | }; 440 | 441 | /* Spellchecker base parser 442 | *************************/ 443 | 444 | var Parser = function(elements) { 445 | this.elements = elements; 446 | }; 447 | 448 | Parser.prototype.clean = function(text) { 449 | 450 | text = '' + text; // Typecast to string 451 | text = decode(text); // Decode HTML characters 452 | text = text.replace(/\xA0|\s+|( )/mg, ' '); // Convert whitespace 453 | text = text.replace(new RegExp('<[^>]+>', 'g'), ''); // Strip HTML tags 454 | 455 | var puncExpr = [ 456 | '(^|\\s+)[' + punctuationChars + ']+', // punctuation(s) with leading whitespace(s) 457 | '[' + punctuationChars + ']+\\s+[' + punctuationChars + ']+', // punctuation(s) with leading and trailing whitespace(s) 458 | '[' + punctuationChars + ']+(\\s+|$)' // puncutation(s) with trailing whitespace(s) 459 | ].join('|'); 460 | 461 | text = text.replace(new RegExp(puncExpr, 'g'), ' '); // strip any punctuation 462 | text = $.trim(text.replace(/\s{2,}/g, ' ')); // remove extra whitespace 463 | 464 | // Remove numbers 465 | text = $.map(text.split(' '), function(word) { 466 | return (/^\d+$/.test(word)) ? null : word; 467 | }).join(' '); 468 | 469 | return text; 470 | }; 471 | 472 | /* Spellchecker text parser 473 | *************************/ 474 | 475 | var TextParser = function() { 476 | Parser.apply(this, arguments); 477 | }; 478 | inherits(TextParser, Parser); 479 | 480 | TextParser.prototype.getText = function(text, textGetter) { 481 | return $.map(this.elements, function(element) { 482 | return this.clean(textGetter ? textGetter(element) : $(element).val()); 483 | }.bind(this)); 484 | }; 485 | 486 | TextParser.prototype.replaceWordInText = function(oldWord, newWord, text) { 487 | var regex = new RegExp('(^|[^' + letterChars + '])(' + RegExp.escape(oldWord) + ')(?=[^' + letterChars + ']|$)', 'g'); 488 | return (text + '').replace(regex, '$1' + newWord); 489 | }; 490 | 491 | TextParser.prototype.replaceWord = function(oldWord, replacement, element) { 492 | element = $(element); 493 | var newText = this.replaceWordInText(oldWord, replacement, element.val()); 494 | element.val(newText); 495 | }; 496 | 497 | /* Spellchecker html parser 498 | *************************/ 499 | 500 | var HtmlParser = function() { 501 | Parser.apply(this, arguments); 502 | }; 503 | inherits(HtmlParser, Parser); 504 | 505 | HtmlParser.prototype.getText = function(text, textGetter) { 506 | if (text && (text = $(text)).length) { 507 | return this.clean(text.text()); 508 | } 509 | return $.map(this.elements, function(element) { 510 | 511 | if (textGetter) { 512 | text = textGetter(element); 513 | } else { 514 | text = $(element) 515 | .clone() 516 | .find('[class^="spellchecker-"]') 517 | .remove() 518 | .end() 519 | .text(); 520 | } 521 | 522 | return this.clean(text); 523 | 524 | }.bind(this)); 525 | }; 526 | 527 | HtmlParser.prototype.replaceText = function(regExp, element, replaceText, captureGroup) { 528 | window.findAndReplaceDOMText(regExp, element, replaceText, captureGroup); 529 | }; 530 | 531 | HtmlParser.prototype.replaceWord = function(oldWord, replacement, element) { 532 | 533 | try { 534 | window.findAndReplaceDOMText.revert(); 535 | } catch(e) {} 536 | 537 | var regExp = new RegExp('(^|[^' + letterChars + '])(' + RegExp.escape(oldWord) + ')(?=[^' + letterChars + ']|$)', 'g'); 538 | 539 | this.replaceText(regExp, element[0], this.replaceTextHandler(oldWord, replacement), 2); 540 | 541 | // Remove this word from the list of incorrect words 542 | this.incorrectWords = $.map(this.incorrectWords || [], function(word) { 543 | return word === oldWord ? null : word; 544 | }); 545 | 546 | this.highlightWords(this.incorrectWords, element); 547 | }; 548 | 549 | HtmlParser.prototype.replaceTextHandler = function(oldWord, replacement){ 550 | 551 | var r = replacement; 552 | var replaced; 553 | var replaceFill; 554 | var c; 555 | 556 | return function(fill, i) { 557 | 558 | // Reset the replacement for each match 559 | if (i !== c) { 560 | c = i; 561 | replacement = r; 562 | replaced = ''; 563 | } 564 | 565 | replaceFill = replacement.substring(0, fill.length); 566 | replacement = replacement.substr(fill.length); 567 | replaced += fill; 568 | 569 | // Add remaining text to last node 570 | if (replaced === oldWord) { 571 | replaceFill += replacement; 572 | } 573 | 574 | return document.createTextNode(replaceFill); 575 | }; 576 | }; 577 | 578 | HtmlParser.prototype.highlightWords = function(incorrectWords, element) { 579 | if (!incorrectWords.length) { 580 | return; 581 | } 582 | 583 | this.incorrectWords = incorrectWords; 584 | incorrectWords = $.map(incorrectWords, function(word) { 585 | return RegExp.escape(word); 586 | }); 587 | 588 | var regExp = ''; 589 | regExp += '([^' + letterChars + '])'; 590 | regExp += '(' + incorrectWords.join('|') + ')'; 591 | regExp += '(?=[^' + letterChars + '])'; 592 | 593 | this.replaceText(new RegExp(regExp, 'g'), element[0], this.highlightWordsHandler(incorrectWords), 2); 594 | }; 595 | 596 | HtmlParser.prototype.highlightWordsHandler = function(incorrectWords) { 597 | 598 | var c; 599 | var replaceElement; 600 | 601 | return function(fill, i, word) { 602 | 603 | // Replacement node 604 | var span = $('', { 605 | 'class': pluginName + '-word-highlight' 606 | }); 607 | 608 | // If we have a new match 609 | if (i !== c) { 610 | c = i; 611 | replaceElement = span; 612 | } 613 | 614 | span 615 | .text(fill) 616 | .data({ 617 | 'firstElement': replaceElement, 618 | 'word': word 619 | }); 620 | 621 | return span[0]; 622 | }; 623 | }; 624 | 625 | HtmlParser.prototype.ignoreWord = function(oldWord, replacement) { 626 | this.replaceWord(oldWord, replacement); 627 | }; 628 | 629 | /* Spellchecker 630 | *************************/ 631 | 632 | var SpellChecker = function(elements, config) { 633 | 634 | Events.call(this); 635 | 636 | this.elements = $(elements).attr('spellcheck', 'false'); 637 | this.config = $.extend(true, defaultConfig, config); 638 | 639 | this.setupWebService(); 640 | this.setupParser(); 641 | 642 | if (this.elements.length) { 643 | this.setupSuggestBox(); 644 | this.setupIncorrectWords(); 645 | this.bindEvents(); 646 | } 647 | }; 648 | inherits(SpellChecker, Events); 649 | 650 | SpellChecker.prototype.setupWebService = function() { 651 | this.webservice = new WebService(this.config); 652 | }; 653 | 654 | SpellChecker.prototype.setupSuggestBox = function() { 655 | 656 | this.suggestBox = new SuggestBox(this.config, this.elements); 657 | 658 | this.on('replace.word.before', function() { 659 | this.suggestBox.close(); 660 | this.suggestBox.detach(); 661 | }.bind(this)); 662 | 663 | this.on('replace.word', function() { 664 | this.suggestBox.reattach(); 665 | }.bind(this)); 666 | 667 | this.on('destroy', function() { 668 | this.suggestBox.destroy(); 669 | }.bind(this)); 670 | }; 671 | 672 | SpellChecker.prototype.setupIncorrectWords = function() { 673 | 674 | this.incorrectWords = new Collection(this.elements, function(element) { 675 | return this.config.parser === 'html' ? 676 | new IncorrectWordsInline(this.config, this.parser, element) : 677 | new IncorrectWordsBox(this.config, this.parser, element); 678 | }.bind(this)); 679 | 680 | this.on('replace.word', function(index) { 681 | this.incorrectWords.get(index).removeWord(this.incorrectWordElement); 682 | }.bind(this)); 683 | 684 | this.on('destroy', function() { 685 | this.incorrectWords.destroy(); 686 | }, this); 687 | }; 688 | 689 | SpellChecker.prototype.setupParser = function() { 690 | this.parser = this.config.parser === 'html' ? 691 | new HtmlParser(this.elements) : 692 | new TextParser(this.elements); 693 | }; 694 | 695 | SpellChecker.prototype.bindEvents = function() { 696 | this.on('check.fail', this.onCheckFail.bind(this)); 697 | this.suggestBox.on('ignore.word', this.onIgnoreWord.bind(this)); 698 | this.suggestBox.on('select.word', this.onSelectWord.bind(this)); 699 | this.incorrectWords.on('select.word', this.onIncorrectWordSelect.bind(this)); 700 | }; 701 | 702 | /* Pubic API methods */ 703 | 704 | SpellChecker.prototype.check = function(text, callback) { 705 | this.trigger('check.start'); 706 | text = typeof text === 'string' ? this.parser.clean(text) : this.parser.getText(text || '', this.config.getText); 707 | this.webservice.checkWords(text, this.onCheckWords(callback)); 708 | }; 709 | 710 | SpellChecker.prototype.getSuggestions = function(word, callback) { 711 | if (this.suggestBox) { 712 | this.suggestBox.loading(true); 713 | } 714 | this.webservice.getSuggestions(word, callback); 715 | }; 716 | 717 | SpellChecker.prototype.replaceWord = function(oldWord, replacement, elementOrText) { 718 | 719 | if (typeof elementOrText === 'string') { 720 | return this.parser.replaceWordInText(oldWord, replacement, elementOrText); 721 | } 722 | 723 | var element = elementOrText || this.spellCheckerElement; 724 | var index = this.elements.index(element); 725 | 726 | this.trigger('replace.word.before'); 727 | this.parser.replaceWord(oldWord, replacement, element); 728 | this.trigger('replace.word', index); 729 | }; 730 | 731 | SpellChecker.prototype.destroy = function() { 732 | this.trigger('destroy'); 733 | }; 734 | 735 | /* Event handlers */ 736 | 737 | SpellChecker.prototype.onCheckWords = function(callback) { 738 | 739 | return function(data) { 740 | 741 | var incorrectWords = data.data; 742 | var outcome = 'success'; 743 | 744 | $.each(incorrectWords, function(i, words) { 745 | if (words.length) { 746 | outcome = 'fail'; 747 | return false; 748 | } 749 | }); 750 | 751 | this.trigger('check.complete'); 752 | this.trigger('check.' + outcome, incorrectWords); 753 | this.trigger(callback, incorrectWords); 754 | 755 | }.bind(this); 756 | }; 757 | 758 | SpellChecker.prototype.onCheckFail = function(badWords) { 759 | this.suggestBox.detach(); 760 | $.each(badWords, function(i, words) { 761 | if (words.length) { 762 | // Make array unique 763 | words = $.grep(words, function(el, index){ 764 | return index === $.inArray(el, words); 765 | }); 766 | this.incorrectWords.get(i).addWords(words); 767 | } 768 | }.bind(this)); 769 | this.suggestBox.reattach(); 770 | }; 771 | 772 | SpellChecker.prototype.onSelectWord = function(e, word, element) { 773 | e.preventDefault(); 774 | this.replaceWord(this.incorrectWord, word); 775 | }; 776 | 777 | SpellChecker.prototype.onIgnoreWord = function(e, word, element) { 778 | e.preventDefault(); 779 | this.replaceWord(this.incorrectWord, this.incorrectWord); 780 | }; 781 | 782 | SpellChecker.prototype.onIncorrectWordSelect = function(e, word, element, incorrectWords) { 783 | e.preventDefault(); 784 | this.incorrectWord = word; 785 | this.incorrectWordElement = element; 786 | this.spellCheckerElement = incorrectWords.spellCheckerElement; 787 | this.spellCheckerIndex = this.elements.index(this.spellCheckerElement); 788 | this.suggestBox.showSuggestedWords(this.getSuggestions.bind(this), word, element); 789 | this.trigger('select.word', e); 790 | }; 791 | 792 | $.SpellChecker = SpellChecker; 793 | 794 | }(this, jQuery)); 795 | 796 | /** 797 | * Some small changes were made by Richard Willis to allow this 798 | * code to pass the project-configured jshint 799 | * 800 | * findAndReplaceDOMText v 0.2 801 | * @author James Padolsey http://james.padolsey.com 802 | * @license http://unlicense.org/UNLICENSE 803 | * 804 | * Matches the text of a DOM node against a regular expression 805 | * and replaces each match (or node-separated portions of the match) 806 | * in the specified element. 807 | * 808 | * Example: Wrap 'test' in : 809 | *

This is a test

810 | * 817 | */ 818 | window.findAndReplaceDOMText = (function() { 819 | 820 | /** 821 | * findAndReplaceDOMText 822 | * 823 | * Locates matches and replaces with replacementNode 824 | * 825 | * @param {RegExp} regex The regular expression to match 826 | * @param {Node} node Element or Text node to search within 827 | * @param {String|Element|Function} replacementNode A NodeName, 828 | * Node to clone, or a function which returns a node to use 829 | * as the replacement node. 830 | * @param {Number} captureGroup A number specifiying which capture 831 | * group to use in the match. (optional) 832 | */ 833 | function findAndReplaceDOMText(regex, node, replacementNode, captureGroup) { 834 | 835 | var m, matches = [], text = _getText(node); 836 | var replaceFn = _genReplacer(replacementNode); 837 | 838 | if (!text) { return; } 839 | 840 | if (regex.global) { 841 | while (!!(m = regex.exec(text))) { 842 | matches.push(_getMatchIndexes(m, captureGroup)); 843 | } 844 | } else { 845 | m = text.match(regex); 846 | matches.push(_getMatchIndexes(m, captureGroup)); 847 | } 848 | 849 | if (matches.length) { 850 | _stepThroughMatches(node, matches, replaceFn); 851 | } 852 | } 853 | 854 | /** 855 | * Gets the start and end indexes of a match 856 | */ 857 | function _getMatchIndexes(m, captureGroup) { 858 | 859 | captureGroup = captureGroup || 0; 860 | 861 | if (!m[0]) throw 'findAndReplaceDOMText cannot handle zero-length matches'; 862 | 863 | var index = m.index; 864 | 865 | if (captureGroup > 0) { 866 | var cg = m[captureGroup]; 867 | if (!cg) throw 'Invalid capture group'; 868 | index += m[0].indexOf(cg); 869 | m[0] = cg; 870 | } 871 | 872 | return [ index, index + m[0].length, [ m[0] ] ]; 873 | } 874 | 875 | /** 876 | * Gets aggregate text of a node without resorting 877 | * to broken innerText/textContent 878 | */ 879 | function _getText(node) { 880 | 881 | if (node.nodeType === 3) { 882 | return node.data; 883 | } 884 | 885 | var txt = ''; 886 | 887 | if (!!(node = node.firstChild)) do { 888 | txt += _getText(node); 889 | } while (!!(node = node.nextSibling)); 890 | 891 | return txt; 892 | 893 | } 894 | 895 | /** 896 | * Steps through the target node, looking for matches, and 897 | * calling replaceFn when a match is found. 898 | */ 899 | function _stepThroughMatches(node, matches, replaceFn) { 900 | 901 | var after, before, 902 | startNode, 903 | endNode, 904 | startNodeIndex, 905 | endNodeIndex, 906 | innerNodes = [], 907 | atIndex = 0, 908 | curNode = node, 909 | matchLocation = matches.shift(), 910 | matchIndex = 0; 911 | 912 | out: while (true) { 913 | 914 | if (curNode.nodeType === 3) { 915 | if (!endNode && curNode.length + atIndex >= matchLocation[1]) { 916 | // We've found the ending 917 | endNode = curNode; 918 | endNodeIndex = matchLocation[1] - atIndex; 919 | } else if (startNode) { 920 | // Intersecting node 921 | innerNodes.push(curNode); 922 | } 923 | if (!startNode && curNode.length + atIndex > matchLocation[0]) { 924 | // We've found the match start 925 | startNode = curNode; 926 | startNodeIndex = matchLocation[0] - atIndex; 927 | } 928 | atIndex += curNode.length; 929 | } 930 | 931 | if (startNode && endNode) { 932 | curNode = replaceFn({ 933 | startNode: startNode, 934 | startNodeIndex: startNodeIndex, 935 | endNode: endNode, 936 | endNodeIndex: endNodeIndex, 937 | innerNodes: innerNodes, 938 | match: matchLocation[2], 939 | matchIndex: matchIndex 940 | }); 941 | // replaceFn has to return the node that replaced the endNode 942 | // and then we step back so we can continue from the end of the 943 | // match: 944 | atIndex -= (endNode.length - endNodeIndex); 945 | startNode = null; 946 | endNode = null; 947 | innerNodes = []; 948 | matchLocation = matches.shift(); 949 | matchIndex++; 950 | if (!matchLocation) { 951 | break; // no more matches 952 | } 953 | } else if (curNode.firstChild || curNode.nextSibling) { 954 | // Move down or forward: 955 | curNode = curNode.firstChild || curNode.nextSibling; 956 | continue; 957 | } 958 | 959 | // Move forward or up: 960 | while (true) { 961 | if (curNode.nextSibling) { 962 | curNode = curNode.nextSibling; 963 | break; 964 | } else if (curNode.parentNode !== node) { 965 | curNode = curNode.parentNode; 966 | } else { 967 | break out; 968 | } 969 | } 970 | 971 | } 972 | 973 | } 974 | 975 | var reverts; 976 | /** 977 | * Reverts the last findAndReplaceDOMText process 978 | */ 979 | findAndReplaceDOMText.revert = function revert() { 980 | for (var i = 0, l = reverts.length; i < l; ++i) { 981 | reverts[i](); 982 | } 983 | reverts = []; 984 | }; 985 | 986 | /** 987 | * Generates the actual replaceFn which splits up text nodes 988 | * and inserts the replacement element. 989 | */ 990 | function _genReplacer(nodeName) { 991 | 992 | reverts = []; 993 | 994 | var makeReplacementNode; 995 | 996 | if (typeof nodeName !== 'function') { 997 | var stencilNode = nodeName.nodeType ? nodeName : document.createElement(nodeName); 998 | makeReplacementNode = function(fill) { 999 | var clone = document.createElement('div'), 1000 | el; 1001 | clone.innerHTML = stencilNode.outerHTML || new window.XMLSerializer().serializeToString(stencilNode); 1002 | el = clone.firstChild; 1003 | if (fill) { 1004 | el.appendChild(document.createTextNode(fill)); 1005 | } 1006 | return el; 1007 | }; 1008 | } else { 1009 | makeReplacementNode = nodeName; 1010 | } 1011 | 1012 | return function replace(range) { 1013 | 1014 | var startNode = range.startNode, 1015 | endNode = range.endNode, 1016 | matchIndex = range.matchIndex, 1017 | before, after; 1018 | 1019 | if (startNode === endNode) { 1020 | var node = startNode; 1021 | if (range.startNodeIndex > 0) { 1022 | // Add `before` text node (before the match) 1023 | before = document.createTextNode(node.data.substring(0, range.startNodeIndex)); 1024 | node.parentNode.insertBefore(before, node); 1025 | } 1026 | 1027 | // Create the replacement node: 1028 | var el = makeReplacementNode(range.match[0], matchIndex, range.match[0]); 1029 | node.parentNode.insertBefore(el, node); 1030 | if (range.endNodeIndex < node.length) { 1031 | // Add `after` text node (after the match) 1032 | after = document.createTextNode(node.data.substring(range.endNodeIndex)); 1033 | node.parentNode.insertBefore(after, node); 1034 | } 1035 | node.parentNode.removeChild(node); 1036 | reverts.push(function() { 1037 | var pnode = el.parentNode; 1038 | pnode.insertBefore(el.firstChild, el); 1039 | pnode.removeChild(el); 1040 | pnode.normalize(); 1041 | }); 1042 | return el; 1043 | } else { 1044 | // Replace startNode -> [innerNodes...] -> endNode (in that order) 1045 | before = document.createTextNode(startNode.data.substring(0, range.startNodeIndex)); 1046 | after = document.createTextNode(endNode.data.substring(range.endNodeIndex)); 1047 | var elA = makeReplacementNode(startNode.data.substring(range.startNodeIndex), matchIndex, range.match[0]); 1048 | var innerEls = []; 1049 | for (var i = 0, l = range.innerNodes.length; i < l; ++i) { 1050 | var innerNode = range.innerNodes[i]; 1051 | var innerEl = makeReplacementNode(innerNode.data, matchIndex, range.match[0]); 1052 | innerNode.parentNode.replaceChild(innerEl, innerNode); 1053 | innerEls.push(innerEl); 1054 | } 1055 | var elB = makeReplacementNode(endNode.data.substring(0, range.endNodeIndex), matchIndex, range.match[0]); 1056 | startNode.parentNode.insertBefore(before, startNode); 1057 | startNode.parentNode.insertBefore(elA, startNode); 1058 | startNode.parentNode.removeChild(startNode); 1059 | endNode.parentNode.insertBefore(elB, endNode); 1060 | endNode.parentNode.insertBefore(after, endNode); 1061 | endNode.parentNode.removeChild(endNode); 1062 | reverts.push(function() { 1063 | innerEls.unshift(elA); 1064 | innerEls.push(elB); 1065 | for (var i = 0, l = innerEls.length; i < l; ++i) { 1066 | var el = innerEls[i]; 1067 | var pnode = el.parentNode; 1068 | pnode.insertBefore(el.firstChild, el); 1069 | pnode.removeChild(el); 1070 | pnode.normalize(); 1071 | } 1072 | }); 1073 | return elB; 1074 | } 1075 | }; 1076 | 1077 | } 1078 | 1079 | return findAndReplaceDOMText; 1080 | 1081 | }()); -------------------------------------------------------------------------------- /tooltipster-sideTip-shadow.min.css: -------------------------------------------------------------------------------- 1 | .tooltipster-sidetip.tooltipster-shadow .tooltipster-box{border:none;border-radius:5px;background:#fff;box-shadow:0 0 10px 6px rgba(0,0,0,.1)}.tooltipster-sidetip.tooltipster-shadow.tooltipster-bottom .tooltipster-box{margin-top:6px}.tooltipster-sidetip.tooltipster-shadow.tooltipster-left .tooltipster-box{margin-right:6px}.tooltipster-sidetip.tooltipster-shadow.tooltipster-right .tooltipster-box{margin-left:6px}.tooltipster-sidetip.tooltipster-shadow.tooltipster-top .tooltipster-box{margin-bottom:6px}.tooltipster-sidetip.tooltipster-shadow .tooltipster-content{color:#8d8d8d}.tooltipster-sidetip.tooltipster-shadow .tooltipster-arrow{height:6px;margin-left:-6px;width:12px}.tooltipster-sidetip.tooltipster-shadow.tooltipster-left .tooltipster-arrow,.tooltipster-sidetip.tooltipster-shadow.tooltipster-right .tooltipster-arrow{height:12px;margin-left:0;margin-top:-6px;width:6px}.tooltipster-sidetip.tooltipster-shadow .tooltipster-arrow-background{display:none}.tooltipster-sidetip.tooltipster-shadow .tooltipster-arrow-border{border:6px solid transparent}.tooltipster-sidetip.tooltipster-shadow.tooltipster-bottom .tooltipster-arrow-border{border-bottom-color:#fff}.tooltipster-sidetip.tooltipster-shadow.tooltipster-left .tooltipster-arrow-border{border-left-color:#fff}.tooltipster-sidetip.tooltipster-shadow.tooltipster-right .tooltipster-arrow-border{border-right-color:#fff}.tooltipster-sidetip.tooltipster-shadow.tooltipster-top .tooltipster-arrow-border{border-top-color:#fff}.tooltipster-sidetip.tooltipster-shadow.tooltipster-bottom .tooltipster-arrow-uncropped{top:-6px}.tooltipster-sidetip.tooltipster-shadow.tooltipster-right .tooltipster-arrow-uncropped{left:-6px} -------------------------------------------------------------------------------- /tooltipster.bundle.css: -------------------------------------------------------------------------------- 1 | /* This is the core CSS of Tooltipster */ 2 | 3 | /* GENERAL STRUCTURE RULES (do not edit this section) */ 4 | 5 | .tooltipster-base { 6 | /* this ensures that a constrained height set by functionPosition, 7 | if greater that the natural height of the tooltip, will be enforced 8 | in browsers that support display:flex */ 9 | display: flex; 10 | pointer-events: none; 11 | /* this may be overriden in JS for fixed position origins */ 12 | position: absolute; 13 | } 14 | 15 | .tooltipster-box { 16 | /* see .tooltipster-base. flex-shrink 1 is only necessary for IE10- 17 | and flex-basis auto for IE11- (at least) */ 18 | flex: 1 1 auto; 19 | } 20 | 21 | .tooltipster-content { 22 | /* prevents an overflow if the user adds padding to the div */ 23 | box-sizing: border-box; 24 | /* these make sure we'll be able to detect any overflow */ 25 | max-height: 100%; 26 | max-width: 100%; 27 | overflow: auto; 28 | } 29 | 30 | .tooltipster-ruler { 31 | /* these let us test the size of the tooltip without overflowing the window */ 32 | bottom: 0; 33 | left: 0; 34 | overflow: hidden; 35 | position: fixed; 36 | right: 0; 37 | top: 0; 38 | visibility: hidden; 39 | } 40 | 41 | /* ANIMATIONS */ 42 | 43 | /* Open/close animations */ 44 | 45 | /* fade */ 46 | 47 | .tooltipster-fade { 48 | opacity: 0; 49 | -webkit-transition-property: opacity; 50 | -moz-transition-property: opacity; 51 | -o-transition-property: opacity; 52 | -ms-transition-property: opacity; 53 | transition-property: opacity; 54 | } 55 | .tooltipster-fade.tooltipster-show { 56 | opacity: 1; 57 | } 58 | 59 | /* grow */ 60 | 61 | .tooltipster-grow { 62 | -webkit-transform: scale(0,0); 63 | -moz-transform: scale(0,0); 64 | -o-transform: scale(0,0); 65 | -ms-transform: scale(0,0); 66 | transform: scale(0,0); 67 | -webkit-transition-property: -webkit-transform; 68 | -moz-transition-property: -moz-transform; 69 | -o-transition-property: -o-transform; 70 | -ms-transition-property: -ms-transform; 71 | transition-property: transform; 72 | -webkit-backface-visibility: hidden; 73 | } 74 | .tooltipster-grow.tooltipster-show { 75 | -webkit-transform: scale(1,1); 76 | -moz-transform: scale(1,1); 77 | -o-transform: scale(1,1); 78 | -ms-transform: scale(1,1); 79 | transform: scale(1,1); 80 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); 81 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 82 | -moz-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 83 | -ms-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 84 | -o-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 85 | transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 86 | } 87 | 88 | /* swing */ 89 | 90 | .tooltipster-swing { 91 | opacity: 0; 92 | -webkit-transform: rotateZ(4deg); 93 | -moz-transform: rotateZ(4deg); 94 | -o-transform: rotateZ(4deg); 95 | -ms-transform: rotateZ(4deg); 96 | transform: rotateZ(4deg); 97 | -webkit-transition-property: -webkit-transform, opacity; 98 | -moz-transition-property: -moz-transform; 99 | -o-transition-property: -o-transform; 100 | -ms-transition-property: -ms-transform; 101 | transition-property: transform; 102 | } 103 | .tooltipster-swing.tooltipster-show { 104 | opacity: 1; 105 | -webkit-transform: rotateZ(0deg); 106 | -moz-transform: rotateZ(0deg); 107 | -o-transform: rotateZ(0deg); 108 | -ms-transform: rotateZ(0deg); 109 | transform: rotateZ(0deg); 110 | -webkit-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 1); 111 | -webkit-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4); 112 | -moz-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4); 113 | -ms-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4); 114 | -o-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4); 115 | transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4); 116 | } 117 | 118 | /* fall */ 119 | 120 | .tooltipster-fall { 121 | -webkit-transition-property: top; 122 | -moz-transition-property: top; 123 | -o-transition-property: top; 124 | -ms-transition-property: top; 125 | transition-property: top; 126 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); 127 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 128 | -moz-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 129 | -ms-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 130 | -o-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 131 | transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 132 | } 133 | .tooltipster-fall.tooltipster-initial { 134 | top: 0 !important; 135 | } 136 | .tooltipster-fall.tooltipster-show { 137 | } 138 | .tooltipster-fall.tooltipster-dying { 139 | -webkit-transition-property: all; 140 | -moz-transition-property: all; 141 | -o-transition-property: all; 142 | -ms-transition-property: all; 143 | transition-property: all; 144 | top: 0 !important; 145 | opacity: 0; 146 | } 147 | 148 | /* slide */ 149 | 150 | .tooltipster-slide { 151 | -webkit-transition-property: left; 152 | -moz-transition-property: left; 153 | -o-transition-property: left; 154 | -ms-transition-property: left; 155 | transition-property: left; 156 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); 157 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 158 | -moz-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 159 | -ms-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 160 | -o-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 161 | transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 162 | } 163 | .tooltipster-slide.tooltipster-initial { 164 | left: -40px !important; 165 | } 166 | .tooltipster-slide.tooltipster-show { 167 | } 168 | .tooltipster-slide.tooltipster-dying { 169 | -webkit-transition-property: all; 170 | -moz-transition-property: all; 171 | -o-transition-property: all; 172 | -ms-transition-property: all; 173 | transition-property: all; 174 | left: 0 !important; 175 | opacity: 0; 176 | } 177 | 178 | /* Update animations */ 179 | 180 | /* We use animations rather than transitions here because 181 | transition durations may be specified in the style tag due to 182 | animationDuration, and we try to avoid collisions and the use 183 | of !important */ 184 | 185 | /* fade */ 186 | 187 | @keyframes tooltipster-fading { 188 | 0% { 189 | opacity: 0; 190 | } 191 | 100% { 192 | opacity: 1; 193 | } 194 | } 195 | 196 | .tooltipster-update-fade { 197 | animation: tooltipster-fading 400ms; 198 | } 199 | 200 | /* rotate */ 201 | 202 | @keyframes tooltipster-rotating { 203 | 25% { 204 | transform: rotate(-2deg); 205 | } 206 | 75% { 207 | transform: rotate(2deg); 208 | } 209 | 100% { 210 | transform: rotate(0); 211 | } 212 | } 213 | 214 | .tooltipster-update-rotate { 215 | animation: tooltipster-rotating 600ms; 216 | } 217 | 218 | /* scale */ 219 | 220 | @keyframes tooltipster-scaling { 221 | 50% { 222 | transform: scale(1.1); 223 | } 224 | 100% { 225 | transform: scale(1); 226 | } 227 | } 228 | 229 | .tooltipster-update-scale { 230 | animation: tooltipster-scaling 600ms; 231 | } 232 | 233 | /** 234 | * DEFAULT STYLE OF THE SIDETIP PLUGIN 235 | * 236 | * All styles are "namespaced" with .tooltipster-sidetip to prevent 237 | * conflicts between plugins. 238 | */ 239 | 240 | /* .tooltipster-box */ 241 | 242 | .tooltipster-sidetip .tooltipster-box { 243 | background: #565656; 244 | border: 2px solid black; 245 | border-radius: 4px; 246 | } 247 | 248 | .tooltipster-sidetip.tooltipster-bottom .tooltipster-box { 249 | margin-top: 8px; 250 | } 251 | 252 | .tooltipster-sidetip.tooltipster-left .tooltipster-box { 253 | margin-right: 8px; 254 | } 255 | 256 | .tooltipster-sidetip.tooltipster-right .tooltipster-box { 257 | margin-left: 8px; 258 | } 259 | 260 | .tooltipster-sidetip.tooltipster-top .tooltipster-box { 261 | margin-bottom: 8px; 262 | } 263 | 264 | /* .tooltipster-content */ 265 | 266 | .tooltipster-sidetip .tooltipster-content { 267 | color: white; 268 | line-height: 18px; 269 | padding: 6px 14px; 270 | } 271 | 272 | /* .tooltipster-arrow : will keep only the zone of .tooltipster-arrow-uncropped that 273 | corresponds to the arrow we want to display */ 274 | 275 | .tooltipster-sidetip .tooltipster-arrow { 276 | overflow: hidden; 277 | position: absolute; 278 | } 279 | 280 | .tooltipster-sidetip.tooltipster-bottom .tooltipster-arrow { 281 | height: 10px; 282 | /* half the width, for centering */ 283 | margin-left: -10px; 284 | top: 0; 285 | width: 20px; 286 | } 287 | 288 | .tooltipster-sidetip.tooltipster-left .tooltipster-arrow { 289 | height: 20px; 290 | margin-top: -10px; 291 | right: 0; 292 | /* top 0 to keep the arrow from overflowing .tooltipster-base when it has not 293 | been positioned yet */ 294 | top: 0; 295 | width: 10px; 296 | } 297 | 298 | .tooltipster-sidetip.tooltipster-right .tooltipster-arrow { 299 | height: 20px; 300 | margin-top: -10px; 301 | left: 0; 302 | /* same as .tooltipster-left .tooltipster-arrow */ 303 | top: 0; 304 | width: 10px; 305 | } 306 | 307 | .tooltipster-sidetip.tooltipster-top .tooltipster-arrow { 308 | bottom: 0; 309 | height: 10px; 310 | margin-left: -10px; 311 | width: 20px; 312 | } 313 | 314 | /* common rules between .tooltipster-arrow-background and .tooltipster-arrow-border */ 315 | 316 | .tooltipster-sidetip .tooltipster-arrow-background, .tooltipster-sidetip .tooltipster-arrow-border { 317 | height: 0; 318 | position: absolute; 319 | width: 0; 320 | } 321 | 322 | /* .tooltipster-arrow-background */ 323 | 324 | .tooltipster-sidetip .tooltipster-arrow-background { 325 | border: 10px solid transparent; 326 | } 327 | 328 | .tooltipster-sidetip.tooltipster-bottom .tooltipster-arrow-background { 329 | border-bottom-color: #565656; 330 | left: 0px; 331 | top: 3px; 332 | } 333 | 334 | .tooltipster-sidetip.tooltipster-left .tooltipster-arrow-background { 335 | border-left-color: #565656; 336 | left: -3px; 337 | top: 0px; 338 | } 339 | 340 | .tooltipster-sidetip.tooltipster-right .tooltipster-arrow-background { 341 | border-right-color: #565656; 342 | left: 3px; 343 | top: 0px; 344 | } 345 | 346 | .tooltipster-sidetip.tooltipster-top .tooltipster-arrow-background { 347 | border-top-color: #565656; 348 | left: 0px; 349 | top: -3px; 350 | } 351 | 352 | /* .tooltipster-arrow-border */ 353 | 354 | .tooltipster-sidetip .tooltipster-arrow-border { 355 | border: 10px solid transparent; 356 | left: 0; 357 | top: 0; 358 | } 359 | 360 | .tooltipster-sidetip.tooltipster-bottom .tooltipster-arrow-border { 361 | border-bottom-color: black; 362 | } 363 | 364 | .tooltipster-sidetip.tooltipster-left .tooltipster-arrow-border { 365 | border-left-color: black; 366 | } 367 | 368 | .tooltipster-sidetip.tooltipster-right .tooltipster-arrow-border { 369 | border-right-color: black; 370 | } 371 | 372 | .tooltipster-sidetip.tooltipster-top .tooltipster-arrow-border { 373 | border-top-color: black; 374 | } 375 | 376 | /* tooltipster-arrow-uncropped */ 377 | 378 | .tooltipster-sidetip .tooltipster-arrow-uncropped { 379 | position: relative; 380 | } 381 | 382 | .tooltipster-sidetip.tooltipster-bottom .tooltipster-arrow-uncropped { 383 | top: -10px; 384 | } 385 | 386 | .tooltipster-sidetip.tooltipster-right .tooltipster-arrow-uncropped { 387 | left: -10px; 388 | } 389 | --------------------------------------------------------------------------------