jquery.uniform.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672
  1. /*
  2. Uniform v1.7.5
  3. Copyright © 2009 Josh Pyles / Pixelmatrix Design LLC
  4. http://pixelmatrixdesign.com
  5. Requires jQuery 1.4 or newer
  6. Much thanks to Thomas Reynolds and Buck Wilson for their help and advice on this
  7. Disabling text selection is made possible by Mathias Bynens <http://mathiasbynens.be/>
  8. and his noSelect plugin. <http://github.com/mathiasbynens/noSelect-jQuery-Plugin>
  9. Also, thanks to David Kaneda and Eugene Bond for their contributions to the plugin
  10. License:
  11. MIT License - http://www.opensource.org/licenses/mit-license.php
  12. Enjoy!
  13. */
  14. (function($) {
  15. $.uniform = {
  16. options: {
  17. selectClass: 'selector',
  18. radioClass: 'radio',
  19. checkboxClass: 'checker',
  20. fileClass: 'uploader',
  21. filenameClass: 'filename',
  22. fileBtnClass: 'action',
  23. fileDefaultText: 'No file selected',
  24. fileBtnText: 'Choose File',
  25. checkedClass: 'checked',
  26. focusClass: 'focus',
  27. disabledClass: 'disabled',
  28. buttonClass: 'button',
  29. activeClass: 'active',
  30. hoverClass: 'hover',
  31. useID: true,
  32. idPrefix: 'uniform',
  33. resetSelector: false,
  34. autoHide: true
  35. },
  36. elements: []
  37. };
  38. if($.browser.msie && $.browser.version < 7){
  39. $.support.selectOpacity = false;
  40. }else{
  41. $.support.selectOpacity = true;
  42. }
  43. $.fn.uniform = function(options) {
  44. options = $.extend($.uniform.options, options);
  45. var el = this;
  46. //code for specifying a reset button
  47. if(options.resetSelector != false){
  48. $(options.resetSelector).mouseup(function(){
  49. function resetThis(){
  50. $.uniform.update(el);
  51. }
  52. setTimeout(resetThis, 10);
  53. });
  54. }
  55. function doInput(elem){
  56. $el = $(elem);
  57. $el.addClass($el.attr("type"));
  58. storeElement(elem);
  59. }
  60. function doTextarea(elem){
  61. $(elem).addClass("uniform");
  62. storeElement(elem);
  63. }
  64. function doButton(elem){
  65. var $el = $(elem);
  66. var divTag = $("<div>"),
  67. spanTag = $("<span>");
  68. divTag.addClass(options.buttonClass);
  69. if(options.useID && $el.attr("id") != "") divTag.attr("id", options.idPrefix+"-"+$el.attr("id"));
  70. var btnText;
  71. if($el.is("a") || $el.is("button")){
  72. btnText = $el.text();
  73. }else if($el.is(":submit") || $el.is(":reset") || $el.is("input[type=button]")){
  74. btnText = $el.attr("value");
  75. }
  76. btnText = btnText == "" ? $el.is(":reset") ? "Reset" : "Submit" : btnText;
  77. spanTag.html(btnText);
  78. $el.css("opacity", 0);
  79. $el.wrap(divTag);
  80. $el.wrap(spanTag);
  81. //redefine variables
  82. divTag = $el.closest("div");
  83. spanTag = $el.closest("span");
  84. if($el.is(":disabled")) divTag.addClass(options.disabledClass);
  85. divTag.bind({
  86. "mouseenter.uniform": function(){
  87. divTag.addClass(options.hoverClass);
  88. },
  89. "mouseleave.uniform": function(){
  90. divTag.removeClass(options.hoverClass);
  91. divTag.removeClass(options.activeClass);
  92. },
  93. "mousedown.uniform touchbegin.uniform": function(){
  94. divTag.addClass(options.activeClass);
  95. },
  96. "mouseup.uniform touchend.uniform": function(){
  97. divTag.removeClass(options.activeClass);
  98. },
  99. "click.uniform touchend.uniform": function(e){
  100. if($(e.target).is("span") || $(e.target).is("div")){
  101. if(elem[0].dispatchEvent){
  102. var ev = document.createEvent('MouseEvents');
  103. ev.initEvent( 'click', true, true );
  104. elem[0].dispatchEvent(ev);
  105. }else{
  106. elem[0].click();
  107. }
  108. }
  109. }
  110. });
  111. elem.bind({
  112. "focus.uniform": function(){
  113. divTag.addClass(options.focusClass);
  114. },
  115. "blur.uniform": function(){
  116. divTag.removeClass(options.focusClass);
  117. }
  118. });
  119. $.uniform.noSelect(divTag);
  120. storeElement(elem);
  121. }
  122. function doSelect(elem){
  123. var $el = $(elem);
  124. var divTag = $('<div />'),
  125. spanTag = $('<span />');
  126. if(!$el.css("display") == "none" && options.autoHide){
  127. divTag.hide();
  128. }
  129. divTag.addClass(options.selectClass);
  130. if(options.useID && elem.attr("id") != ""){
  131. divTag.attr("id", options.idPrefix+"-"+elem.attr("id"));
  132. }
  133. var selected = elem.find(":selected:first");
  134. if(selected.length == 0){
  135. selected = elem.find("option:first");
  136. }
  137. spanTag.html(selected.html());
  138. elem.css('opacity', 0);
  139. elem.wrap(divTag);
  140. elem.before(spanTag);
  141. //redefine variables
  142. divTag = elem.parent("div");
  143. spanTag = elem.siblings("span");
  144. elem.bind({
  145. "change.uniform": function() {
  146. spanTag.text(elem.find(":selected").html());
  147. divTag.removeClass(options.activeClass);
  148. },
  149. "focus.uniform": function() {
  150. divTag.addClass(options.focusClass);
  151. },
  152. "blur.uniform": function() {
  153. divTag.removeClass(options.focusClass);
  154. divTag.removeClass(options.activeClass);
  155. },
  156. "mousedown.uniform touchbegin.uniform": function() {
  157. divTag.addClass(options.activeClass);
  158. },
  159. "mouseup.uniform touchend.uniform": function() {
  160. divTag.removeClass(options.activeClass);
  161. },
  162. "click.uniform touchend.uniform": function(){
  163. divTag.removeClass(options.activeClass);
  164. },
  165. "mouseenter.uniform": function() {
  166. divTag.addClass(options.hoverClass);
  167. },
  168. "mouseleave.uniform": function() {
  169. divTag.removeClass(options.hoverClass);
  170. divTag.removeClass(options.activeClass);
  171. },
  172. "keyup.uniform": function(){
  173. spanTag.text(elem.find(":selected").html());
  174. }
  175. });
  176. //handle disabled state
  177. if($(elem).attr("disabled")){
  178. //box is checked by default, check our box
  179. divTag.addClass(options.disabledClass);
  180. }
  181. $.uniform.noSelect(spanTag);
  182. storeElement(elem);
  183. }
  184. function doCheckbox(elem){
  185. var $el = $(elem);
  186. var divTag = $('<div />'),
  187. spanTag = $('<span />');
  188. if(!$el.css("display") == "none" && options.autoHide){
  189. divTag.hide();
  190. }
  191. divTag.addClass(options.checkboxClass);
  192. //assign the id of the element
  193. if(options.useID && elem.attr("id") != ""){
  194. divTag.attr("id", options.idPrefix+"-"+elem.attr("id"));
  195. }
  196. //wrap with the proper elements
  197. $(elem).wrap(divTag);
  198. $(elem).wrap(spanTag);
  199. //redefine variables
  200. spanTag = elem.parent();
  201. divTag = spanTag.parent();
  202. //hide normal input and add focus classes
  203. $(elem)
  204. .css("opacity", 0)
  205. .bind({
  206. "focus.uniform": function(){
  207. divTag.addClass(options.focusClass);
  208. },
  209. "blur.uniform": function(){
  210. divTag.removeClass(options.focusClass);
  211. },
  212. "click.uniform touchend.uniform": function(){
  213. if(!$(elem).attr("checked")){
  214. //box was just unchecked, uncheck span
  215. spanTag.removeClass(options.checkedClass);
  216. }else{
  217. //box was just checked, check span.
  218. spanTag.addClass(options.checkedClass);
  219. }
  220. },
  221. "mousedown.uniform touchbegin.uniform": function() {
  222. divTag.addClass(options.activeClass);
  223. },
  224. "mouseup.uniform touchend.uniform": function() {
  225. divTag.removeClass(options.activeClass);
  226. },
  227. "mouseenter.uniform": function() {
  228. divTag.addClass(options.hoverClass);
  229. },
  230. "mouseleave.uniform": function() {
  231. divTag.removeClass(options.hoverClass);
  232. divTag.removeClass(options.activeClass);
  233. }
  234. });
  235. //handle defaults
  236. if($(elem).attr("checked")){
  237. //box is checked by default, check our box
  238. spanTag.addClass(options.checkedClass);
  239. }
  240. //handle disabled state
  241. if($(elem).attr("disabled")){
  242. //box is checked by default, check our box
  243. divTag.addClass(options.disabledClass);
  244. }
  245. storeElement(elem);
  246. }
  247. function doRadio(elem){
  248. var $el = $(elem);
  249. var divTag = $('<div />'),
  250. spanTag = $('<span />');
  251. if(!$el.css("display") == "none" && options.autoHide){
  252. divTag.hide();
  253. }
  254. divTag.addClass(options.radioClass);
  255. if(options.useID && elem.attr("id") != ""){
  256. divTag.attr("id", options.idPrefix+"-"+elem.attr("id"));
  257. }
  258. //wrap with the proper elements
  259. $(elem).wrap(divTag);
  260. $(elem).wrap(spanTag);
  261. //redefine variables
  262. spanTag = elem.parent();
  263. divTag = spanTag.parent();
  264. //hide normal input and add focus classes
  265. $(elem)
  266. .css("opacity", 0)
  267. .bind({
  268. "focus.uniform": function(){
  269. divTag.addClass(options.focusClass);
  270. },
  271. "blur.uniform": function(){
  272. divTag.removeClass(options.focusClass);
  273. },
  274. "click.uniform touchend.uniform": function(){
  275. if(!$(elem).attr("checked")){
  276. //box was just unchecked, uncheck span
  277. spanTag.removeClass(options.checkedClass);
  278. }else{
  279. //box was just checked, check span
  280. var classes = options.radioClass.split(" ")[0];
  281. $("." + classes + " span." + options.checkedClass + ":has([name='" + $(elem).attr('name') + "'])").removeClass(options.checkedClass);
  282. spanTag.addClass(options.checkedClass);
  283. }
  284. },
  285. "mousedown.uniform touchend.uniform": function() {
  286. if(!$(elem).is(":disabled")){
  287. divTag.addClass(options.activeClass);
  288. }
  289. },
  290. "mouseup.uniform touchbegin.uniform": function() {
  291. divTag.removeClass(options.activeClass);
  292. },
  293. "mouseenter.uniform touchend.uniform": function() {
  294. divTag.addClass(options.hoverClass);
  295. },
  296. "mouseleave.uniform": function() {
  297. divTag.removeClass(options.hoverClass);
  298. divTag.removeClass(options.activeClass);
  299. }
  300. });
  301. //handle defaults
  302. if($(elem).attr("checked")){
  303. //box is checked by default, check span
  304. spanTag.addClass(options.checkedClass);
  305. }
  306. //handle disabled state
  307. if($(elem).attr("disabled")){
  308. //box is checked by default, check our box
  309. divTag.addClass(options.disabledClass);
  310. }
  311. storeElement(elem);
  312. }
  313. function doFile(elem){
  314. //sanitize input
  315. var $el = $(elem);
  316. var divTag = $('<div />'),
  317. filenameTag = $('<span>'+options.fileDefaultText+'</span>'),
  318. btnTag = $('<span>'+options.fileBtnText+'</span>');
  319. if(!$el.css("display") == "none" && options.autoHide){
  320. divTag.hide();
  321. }
  322. divTag.addClass(options.fileClass);
  323. filenameTag.addClass(options.filenameClass);
  324. btnTag.addClass(options.fileBtnClass);
  325. if(options.useID && $el.attr("id") != ""){
  326. divTag.attr("id", options.idPrefix+"-"+$el.attr("id"));
  327. }
  328. //wrap with the proper elements
  329. $el.wrap(divTag);
  330. $el.after(btnTag);
  331. $el.after(filenameTag);
  332. //redefine variables
  333. divTag = $el.closest("div");
  334. filenameTag = $el.siblings("."+options.filenameClass);
  335. btnTag = $el.siblings("."+options.fileBtnClass);
  336. //set the size
  337. if(!$el.attr("size")){
  338. var divWidth = divTag.width();
  339. //$el.css("width", divWidth);
  340. $el.attr("size", divWidth/10);
  341. }
  342. //actions
  343. var setFilename = function()
  344. {
  345. var filename = $el.val();
  346. if (filename === '')
  347. {
  348. filename = options.fileDefaultText;
  349. }
  350. else
  351. {
  352. filename = filename.split(/[\/\\]+/);
  353. filename = filename[(filename.length-1)];
  354. }
  355. filenameTag.text(filename);
  356. };
  357. // Account for input saved across refreshes
  358. setFilename();
  359. $el
  360. .css("opacity", 0)
  361. .bind({
  362. "focus.uniform": function(){
  363. divTag.addClass(options.focusClass);
  364. },
  365. "blur.uniform": function(){
  366. divTag.removeClass(options.focusClass);
  367. },
  368. "mousedown.uniform": function() {
  369. if(!$(elem).is(":disabled")){
  370. divTag.addClass(options.activeClass);
  371. }
  372. },
  373. "mouseup.uniform": function() {
  374. divTag.removeClass(options.activeClass);
  375. },
  376. "mouseenter.uniform": function() {
  377. divTag.addClass(options.hoverClass);
  378. },
  379. "mouseleave.uniform": function() {
  380. divTag.removeClass(options.hoverClass);
  381. divTag.removeClass(options.activeClass);
  382. }
  383. });
  384. // IE7 doesn't fire onChange until blur or second fire.
  385. if ($.browser.msie){
  386. // IE considers browser chrome blocking I/O, so it
  387. // suspends tiemouts until after the file has been selected.
  388. $el.bind('click.uniform.ie7', function() {
  389. setTimeout(setFilename, 0);
  390. });
  391. }else{
  392. // All other browsers behave properly
  393. $el.bind('change.uniform', setFilename);
  394. }
  395. //handle defaults
  396. if($el.attr("disabled")){
  397. //box is checked by default, check our box
  398. divTag.addClass(options.disabledClass);
  399. }
  400. $.uniform.noSelect(filenameTag);
  401. $.uniform.noSelect(btnTag);
  402. storeElement(elem);
  403. }
  404. $.uniform.restore = function(elem){
  405. if(elem == undefined){
  406. elem = $($.uniform.elements);
  407. }
  408. $(elem).each(function(){
  409. if($(this).is(":checkbox")){
  410. //unwrap from span and div
  411. $(this).unwrap().unwrap();
  412. }else if($(this).is("select")){
  413. //remove sibling span
  414. $(this).siblings("span").remove();
  415. //unwrap parent div
  416. $(this).unwrap();
  417. }else if($(this).is(":radio")){
  418. //unwrap from span and div
  419. $(this).unwrap().unwrap();
  420. }else if($(this).is(":file")){
  421. //remove sibling spans
  422. $(this).siblings("span").remove();
  423. //unwrap parent div
  424. $(this).unwrap();
  425. }else if($(this).is("button, :submit, :reset, a, input[type='button']")){
  426. //unwrap from span and div
  427. $(this).unwrap().unwrap();
  428. }
  429. //unbind events
  430. $(this).unbind(".uniform");
  431. //reset inline style
  432. $(this).css("opacity", "1");
  433. //remove item from list of uniformed elements
  434. var index = $.inArray($(elem), $.uniform.elements);
  435. $.uniform.elements.splice(index, 1);
  436. });
  437. };
  438. function storeElement(elem){
  439. //store this element in our global array
  440. elem = $(elem).get();
  441. if(elem.length > 1){
  442. $.each(elem, function(i, val){
  443. $.uniform.elements.push(val);
  444. });
  445. }else{
  446. $.uniform.elements.push(elem);
  447. }
  448. }
  449. //noSelect v1.0
  450. $.uniform.noSelect = function(elem) {
  451. function f() {
  452. return false;
  453. };
  454. $(elem).each(function() {
  455. this.onselectstart = this.ondragstart = f; // Webkit & IE
  456. $(this)
  457. .mousedown(f) // Webkit & Opera
  458. .css({ MozUserSelect: 'none' }); // Firefox
  459. });
  460. };
  461. $.uniform.update = function(elem){
  462. if(elem == undefined){
  463. elem = $($.uniform.elements);
  464. }
  465. //sanitize input
  466. elem = $(elem);
  467. elem.each(function(){
  468. //do to each item in the selector
  469. //function to reset all classes
  470. var $e = $(this);
  471. if($e.is("select")){
  472. //element is a select
  473. var spanTag = $e.siblings("span");
  474. var divTag = $e.parent("div");
  475. divTag.removeClass(options.hoverClass+" "+options.focusClass+" "+options.activeClass);
  476. //reset current selected text
  477. spanTag.html($e.find(":selected").html());
  478. if($e.is(":disabled")){
  479. divTag.addClass(options.disabledClass);
  480. }else{
  481. divTag.removeClass(options.disabledClass);
  482. }
  483. }else if($e.is(":checkbox")){
  484. //element is a checkbox
  485. var spanTag = $e.closest("span");
  486. var divTag = $e.closest("div");
  487. divTag.removeClass(options.hoverClass+" "+options.focusClass+" "+options.activeClass);
  488. spanTag.removeClass(options.checkedClass);
  489. if($e.is(":checked")){
  490. spanTag.addClass(options.checkedClass);
  491. }
  492. if($e.is(":disabled")){
  493. divTag.addClass(options.disabledClass);
  494. }else{
  495. divTag.removeClass(options.disabledClass);
  496. }
  497. }else if($e.is(":radio")){
  498. //element is a radio
  499. var spanTag = $e.closest("span");
  500. var divTag = $e.closest("div");
  501. divTag.removeClass(options.hoverClass+" "+options.focusClass+" "+options.activeClass);
  502. spanTag.removeClass(options.checkedClass);
  503. if($e.is(":checked")){
  504. spanTag.addClass(options.checkedClass);
  505. }
  506. if($e.is(":disabled")){
  507. divTag.addClass(options.disabledClass);
  508. }else{
  509. divTag.removeClass(options.disabledClass);
  510. }
  511. }else if($e.is(":file")){
  512. var divTag = $e.parent("div");
  513. var filenameTag = $e.siblings(options.filenameClass);
  514. btnTag = $e.siblings(options.fileBtnClass);
  515. divTag.removeClass(options.hoverClass+" "+options.focusClass+" "+options.activeClass);
  516. filenameTag.text($e.val());
  517. if($e.is(":disabled")){
  518. divTag.addClass(options.disabledClass);
  519. }else{
  520. divTag.removeClass(options.disabledClass);
  521. }
  522. }else if($e.is(":submit") || $e.is(":reset") || $e.is("button") || $e.is("a") || elem.is("input[type=button]")){
  523. var divTag = $e.closest("div");
  524. divTag.removeClass(options.hoverClass+" "+options.focusClass+" "+options.activeClass);
  525. if($e.is(":disabled")){
  526. divTag.addClass(options.disabledClass);
  527. }else{
  528. divTag.removeClass(options.disabledClass);
  529. }
  530. }
  531. });
  532. };
  533. return this.each(function() {
  534. if($.support.selectOpacity){
  535. var elem = $(this);
  536. if(elem.is("select")){
  537. //element is a select
  538. if(elem.attr("multiple") != true){
  539. //element is not a multi-select
  540. if(elem.attr("size") == undefined || elem.attr("size") <= 1){
  541. doSelect(elem);
  542. }
  543. }
  544. }else if(elem.is(":checkbox")){
  545. //element is a checkbox
  546. doCheckbox(elem);
  547. }else if(elem.is(":radio")){
  548. //element is a radio
  549. doRadio(elem);
  550. }else if(elem.is(":file")){
  551. //element is a file upload
  552. doFile(elem);
  553. }else if(elem.is(":text, :password, input[type='email']")){
  554. doInput(elem);
  555. }else if(elem.is("textarea")){
  556. doTextarea(elem);
  557. }else if(elem.is("a") || elem.is(":submit") || elem.is(":reset") || elem.is("button") || elem.is("input[type=button]")){
  558. doButton(elem);
  559. }
  560. }
  561. });
  562. };
  563. })(jQuery);