bplist00_WebMainResource_WebSubresources _WebResourceMIMEType_WebResourceData^WebResourceURL_WebResourceTextEncodingName_WebResourceFrameNameYtext/htmlO Service and Repair

Service and Repair

You can see your service options and arrange a repair online for selected products and locations.

To proceed, simply let us know your hardware serial number and your location. Apple will find you the help you need.

Finding your serial number is easy. See how.
_*https://selfsolve.apple.com/GetWarranty.doUUTF-8P""&*/37;?DIMQUY]bfjnrvz~_WebResourceResponseXtext/cssOhB/* RESET */ html,body,div,ul,ol,li,dl,dt,dd,h1,h2,h3,h4,h5,h6,pre,form,p,blockquote,fieldset,input { margin: 0; padding: 0; } h1,h2,h3,h4,h5,h6,pre,code,address,caption,cite,code,em,strong,th { font-size: 1em; font-weight: normal; font-style: normal; } ul,ol { list-style: none; } fieldset,img { border: none; } caption,th { text-align: left; } table { border-collapse: collapse; border-spacing: 0; } /* LAYOUT */ .clear { clear: both; } .clearer { clear: both; display: block; margin: 0; padding: 0; height: 0; line-height: 1px; font-size: 1px; } img, .search-wrapper .left, .search-wrapper .right, ul.sp-results li.viewall a, ul.sp-results li .replacementimg, #globalfooter #breadcrumbs, #globalfooter #breadcrumbs span, #directorynav .capbottom, #productheader h1 a, #productheader h2 a, #productheader a.buynow, #productheader a.ordernow, #productheader a.joinnow, #productheader a.preorder, #productheader a.freetrial, #productheader a.downloadnow, #productheader a.upgradenow { behavior: url(/global/scripts/lib/iepngfix.htc); } img { border: 0; } img.left { float: left; margin: 2px 20px 16px 0; } img.right { float: right; margin: 2px 0 16px 20px; } img.across { margin: 2px 0 16px 0; } img.flushleft { margin-left: -20px; } img.flushright { margin-right: -20px; } #omniture, #top { position: absolute; top: 0; } #container { width: 980px; margin: 0 auto; position: relative; } #main { width: 100%; position: relative; } #content { padding: 18px 20px; position: relative; color: #333; } #breadcrumb { clear: both; text-align: center; margin: 18px auto; clear: both; font-size: 10px; color: #686868; } /* GRID */ .column { float: left; } .grid2col, .grid2cola, .grid2colb, .grid2colc, .grid2cold, .grid2cole, .grid2colf, .grid3col, .grid3cola, .grid4col, .grid5col, .grid6col { width: 100%; } .grid2col .column { width: 49%; } .grid2col .grid2col .column { width: 47.8%; } .grid3col .grid2col .column { width: 46%; } .grid4col .grid2col .column { width: 45%; } .grid2cola .column.first { width: 66%; } .grid2cola .column.last { width: 32%; } .grid2colb .column.first { width: 74.9%; } .grid2colb .column.last { width: 23%; } .grid2colc .column.first { width: 32%; } .grid2colc .column.last { width: 66%; } .grid2cold .column.first { width: 23%; } .grid2cold .column.last { width: 74.9%; } .grid2cole .column.first { width: 79%; } .grid2cole .column.last { width: 19%; } .grid2colf .column.first { width: 19%; } .grid2colf .column.last { width: 79%; } .grid3col .column { width: 32%; margin-left: 2%; } .grid2col .grid3col .column { width: 31%; } .grid3cola .column { width: 58%; margin-left: 2%; } .grid3cola .column.first, .grid3cola .column.last { width: 19%; } .grid4col .column { width: 23%; margin-left: 3%; } .grid5col .column { width: 18.4%; margin-left: 2%; } .grid6col .column { width: 15%; margin-left: 2%; } .column.first, .column.last { margin-left: 0 !important; } .column.last { float: right !important; } p.last, ul.last, ol.last, li.last { _width: auto !important; _float: none !important; } #container:after, #content:after, .grid2col:after, .grid2cola:after, .grid2colb:after, .grid2colc:after, .grid2cold:after, .grid2cole:after, .grid2colf:after, .grid3col:after, .grid3cola:after, .grid4col:after, .grid5col:after, .grid6col:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } #container, #content, .grid2col, .grid2cola, .grid2colb, .grid2colc, .grid2cold, .grid2cole, .grid2colf, .grid3col, .grid3cola, .grid4col, .grid5col, .grid6col { zoom: 1; } /* TYPE */ body { font: 12px/18px "Lucida Grande", "Lucida Sans Unicode", Arial, Verdana, sans-serif; background-color: #fff; color: #333; } a { color: #08c; } a:link, a:visited, a:active { text-decoration: none; } a:hover { text-decoration: underline; } a.more { white-space: nowrap; padding-right: 10px; background: url(https://ssl.apple.com/global/elements/arrows/morearrow_08c.gif) no-repeat 100% 50%; zoom: 1; } a.external { white-space: nowrap; padding-right: 15px; background: url(https://ssl.apple.com/global/elements/icons/external10x10.gif) no-repeat 100% 49%; zoom: 1; } a[rel="external"] { white-space: nowrap; padding-right: 15px; background: url(https://ssl.apple.com/global/elements/icons/external10x10.gif) no-repeat 100% 49%; zoom: 1; } strong, b { font-weight: bold; } em, i { font-style: italic; } sup { padding-left: 1px; font-size: 10px !important; font-weight: normal !important; vertical-align: baseline; position: relative; bottom: 0.33em; color: #76797c; _position: static !important; } abbr { border: 0; } .sosumi { font-size: 10px !important; color:#76797c; } .sosumi_features { font-size: 10px !important; color:#76797c; } p { margin-bottom: 18px; } h1 { font-weight: bold; font-size: 24px; line-height: 36px; margin-bottom: 18px; } h2 { font-weight: bold; font-size: 16px; line-height: 18px; margin-bottom: 18px; } h3 { font-weight: bold; font-size: 1em; line-height: 18px; } h4 { font-weight: bold; font-size: 10px; line-height: 18px; } p.intro { font-weight: bold; } .more { text-align: right;} ul { margin-bottom: 18px; list-style: none outside; } ol { margin-bottom: 18px; list-style: decimal; margin-left: 2.2em; } ul.square, ul.circle { margin-left: 2em; } ul.square { list-style: square outside; } ul.circle { list-style: circle outside; } ul ul.circle, ul ul.square { margin-top: 4px; margin-bottom: 5px; } ol.sosumi { margin-left: 0; padding-left: 2em; } a.pdf { background: url(https://ssl.apple.com/global/elements/icons/globaliconpdf12x12.gif) 0 0.4em no-repeat; display: block; padding-left: 20px; } a.html { background: url(https://ssl.apple.com/global/elements/icons/globaliconhtml12x12.gif) 0 0.4em no-repeat; display: block; padding-left: 20px; } a.qt { background: url(https://ssl.apple.com/global/elements/icons/globaliconqt12x12.gif) 0 0.4em no-repeat; display: block; padding-left: 20px; } a.ical { background: url(https://ssl.apple.com/global/elements/icons/globaliconical12x12.gif) 0 0.4em no-repeat; display: block; padding-left: 20px; } a.dl { background: url(https://ssl.apple.com/global/elements/icons/globalicondl11x10.gif) 0 0.4em no-repeat; display: block; padding-left: 20px; } a.dmg { background: url(https://ssl.apple.com/global/elements/icons/globalicondmg12x12.gif) 0 0.4em no-repeat; display: block; padding-left: 20px; } a.zip { background: url(https://ssl.apple.com/global/elements/icons/globaliconzip12x12.gif) 0 0.4em no-repeat; display: block; padding-left: 20px; } a.keynote { background: url(https://ssl.apple.com/global/elements/icons/globaliconkeynote12x12.gif) 0 0.4em no-repeat; display: block; padding-left: 20px; } a.audio { background: url(https://ssl.apple.com/global/elements/icons/globaliconaudio12x12.gif) 0 0.4em no-repeat; display: block; padding-left: 20px; } .last { margin-bottom: 0; } #main .sidebar { font-size: 10px; line-height: 18px; color:#686868; } #main .callout { font-size: 11px; line-height: 18px; margin-bottom: 18px; } /* PIPED LINKS */ .piped { display: block; zoom: 1; } .piped:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } .piped li { float: left; display: inline; } .piped a { border-left: 1px solid #797c80; padding: 0 0 0 0.75em; margin-left: 0.75em; } .piped a.first { border-left: 0 !important; padding-left: 0; margin-left: 0 !important; } /* PRETTY SEARCH */ input.prettysearch { width:200px; height: 16px; background: url(https://ssl.apple.com/global/elements/prettysearch/searchfield_repeat.png) center top repeat-x; border: 0px; margin: 0; padding: 3px 0 0 0; font: 11px "Lucida Grande", "Lucida Sans Unicode", Arial, sans-serif; } .search-wrapper { position: relative; width: 200px; } .search-wrapper input.prettysearch { width: 171px; margin-left: 20px; *margin-top:-1px; *margin-right:-2px; *margin-left:10px; } .search-wrapper .left { display: block; position: absolute; left: 0; top: 0; width: 20px; height: 19px; background: url(https://ssl.apple.com/global/elements/prettysearch/searchfield_leftcap.png) left top no-repeat; } .search-wrapper .right { display: block; position: absolute; right: 0; top: 0; width: 10px; height: 19px; background: url(https://ssl.apple.com/global/elements/prettysearch/searchfield_rightcap.png) right top no-repeat; } .search-wrapper.empty.blurred input { color: #7e7e7e; } .search-wrapper .reset { position: absolute; width: 11px; height: 11px; overflow:hidden; z-index: 1; right: 4px; top: 4px; background: url(https://ssl.apple.com/global/elements/prettysearch/close.gif); display: block; cursor: pointer; _cursor:hand; } .search-wrapper.empty .reset { display: none; } label .prettyplaceholder { display: block; overflow: hidden; text-indent: -9999px; height: 0; width: 0;} /* GLOBALHEADER */ #globalheader { width: 982px; height: 38px; margin: 18px auto; position: relative; z-index: 9998; } #globalheader #globalnav { margin: 0; padding: 0; } #globalheader #globalnav li { display: inline; } #globalheader #globalnav li a { float: left; width: 117px; height: 0; padding-top: 38px; overflow: hidden; } #globalheader #globalnav li a, #globalheader #globalsearch { background-image: url(https://ssl.apple.com/global/nav/images/globalnavbg.png); _background-image: url(https://ssl.apple.com/global/nav/images/globalnavbg.gif); background-repeat: no-repeat; } /* BUTTONS */ #globalheader #globalnav li#gn-store a { background-position: 0 0; } #globalheader #globalnav li#gn-store a { background-position: -117px 0; } #globalheader #globalnav li#gn-mac a { background-position: -234px 0; } #globalheader #globalnav li#gn-ipoditunes a { background-position: -351px 0; } #globalheader #globalnav li#gn-iphone a { background-position: -468px 0; } #globalheader #globalnav li#gn-downloads a { background-position: -585px 0; } #globalheader #globalnav li#gn-support a { background-position: -702px 0; } /* OVER STATES */ #globalheader #globalnav li#gn-apple a:hover { background-position: 0 -38px; } #globalheader #globalnav li#gn-store a:hover { background-position: -117px -38px; } #globalheader #globalnav li#gn-mac a:hover { background-position: -234px -38px; } #globalheader #globalnav li#gn-ipoditunes a:hover { background-position: -351px -38px; } #globalheader #globalnav li#gn-iphone a:hover { background-position: -468px -38px; } #globalheader #globalnav li#gn-downloads a:hover { background-position: -585px -38px; } #globalheader #globalnav li#gn-support a:hover { background-position: -702px -38px; } /* PRESSED STATES */ #globalheader #globalnav li#gn-apple a:active { background-position: 0 -76px; } #globalheader #globalnav li#gn-store a:active { background-position: -117px -76px; } #globalheader #globalnav li#gn-mac a:active { background-position: -234px -76px; } #globalheader #globalnav li#gn-ipoditunes a:active { background-position: -351px -76px; } #globalheader #globalnav li#gn-iphone a:active { background-position: -468px -76px; } #globalheader #globalnav li#gn-downloads a:active { background-position: -585px -76px; } #globalheader #globalnav li#gn-support a:active { background-position: -702px -76px; } /* ON STATES */ #globalheader.home #globalnav li#gn-apple a:hover { background-position: 0 0; cursor: default; } #globalheader.store #globalnav li#gn-store a { background-position: -117px -114px !important; } #globalheader.mac #globalnav li#gn-mac a { background-position: -234px -114px !important; } #globalheader.ipoditunes #globalnav li#gn-ipoditunes a { background-position: -351px -114px !important; } #globalheader.iphone #globalnav li#gn-iphone a { background-position: -468px -114px !important; } #globalheader.downloads #globalnav li#gn-downloads a { background-position: -585px -114px !important; } #globalheader.support #globalnav li#gn-support a { background-position: -702px -114px !important; } /* Testing everywhere search */ input[type=search].not-round { /*background: #ABABAB;*/ height: 19px; outline: none; -webkit-border-radius: 9px; -webkit-border-image: url(https://ssl.apple.com/global/elements/prettysearch/searchfield_border.png) 2 2 2 2 stretch stretch; width: 200px; } /* GLOBAL SEARCH */ #globalsearch { width: 163px; height: 38px; position: absolute; top: 0; right: 0; background-position: 100% 0; background-repeat: no-repeat; } #globalsearch.active { background-position: 100% -38px; } #globalsearch input.g-prettysearch, #globalsearch .search-wrapper input.g-prettysearch {background: url(https://ssl.apple.com/global/nav/images/searchfield_repeat.png) center top repeat-x; } #globalsearch input.g-prettysearch { width:140px; height: 16px; margin-top: 9px; margin-left: 11px; } #globalsearch .search-wrapper { position: relative; width: 140px; margin-top: 9px; margin-left: 11px; } #globalsearch .search-wrapper input.g-prettysearch { width: 110px; margin-left: 20px; *margin-top:-1px; *margin-right:-2px; *margin-left:10px; } #globalsearch .search-wrapper .left, #globalsearch .search-wrapper .left { display: block; position: absolute; left: 0; top: 0; width: 20px; height: 19px; background: url(https://ssl.apple.com/global/nav/images/searchfield_leftcap.png) left top no-repeat; } #globalsearch .search-wrapper .right { display: block; position: absolute; right: 0; top: 0; width: 10px; height: 19px; background: url(https://ssl.apple.com/global/nav/images/searchfield_rightcap.png) right top no-repeat; } #globalsearch .search-wrapper.empty.blurred input { color: #7E7E7E; } #globalsearch .search-wrapper .reset { position: absolute; width: 11px; height: 11px; overflow:hidden; z-index: 1; right: 4px; top: 4px; background: url(https://ssl.apple.com/global/nav/images/close.gif); display: block; cursor: pointer; _cursor:hand; } #globalsearch .search-wrapper.empty .reset { display: none; } #globalsearch .search-wrapper input.g-prettysearch { position: absolute; width: 110px; top: 0; right: 10px; border: 0px; margin: 0; padding: 3px 0 0 0; font: 11px "Lucida Grande", Arial, sans-serif; } #globalsearch label .prettyplaceholder { display: block; overflow: hidden; text-indent: -9999px; height: 0; width: 0;} #globalsearch input[type=search].not-round { background: #ABABAB; height: 19px; outline: none; -webkit-border-radius: 9px; -webkit-border-image: url(https://ssl.apple.com/global/elements/prettysearch/searchfield_border.png) 2 2 2 2 stretch stretch; width: 133px; } /* SEARCH SHORTCUTS */ #sp-results { position: absolute; margin-right: -2px; margin-bottom: 0; margin-left: 0; top: 61px; left: 165px; height: 0; } #sp-results .inside { width: 328px; height: auto; position: absolute; top: 0; right: 0; line-height: 1px; font-size: 1px; } #sp-results .resultCat { position: relative; color: #f6f6f6; background: #919191; width: 308px; height: 8px; margin: 0; padding-bottom: 12px; width: 302px; font: 11px "Lucida Grande", "Lucida Sans Unicode", Arial, Verdana, sans-serif; font-weight: bold; border: 1px none #fb6bff; } ul.sp-results { background: url(https://ssl.apple.com/global/nav/images/shortcuts_bg_mid_grey.png) repeat-y 0 0; _background: url(https://ssl.apple.com/global/nav/images/shortcuts_bg_mid_grey.gif) repeat-y 0 0; color: #333; padding: 0 3px; margin: 0; width: 328px; text-align: left; font: 10px/14px "Lucida Grande", "Lucida Sans Unicode", Arial, Verdana, sans-serif; } ul.sp-results li { margin: 0 0 -3px 0; padding: 5px 10px; list-style-type: none; height: 4.6em; position: relative; border-left: 1px solid #919191; border-right: 1px solid #919191; width: 300px; } ul.sp-results li.viewall { width: 308px; height: 20px; text-align: right; color: #000; position: absolute; bottom: -30px; *bottom: -27px; left: 0px; background: url(https://ssl.apple.com/global/nav/images/shortcuts_bg_foot_grey.png) no-repeat left bottom; _background: url(https://ssl.apple.com/global/nav/images/shortcuts_bg_foot_grey.gif) no-repeat left bottom; border-style: none; } ul.sp-results li.viewall a { color: #fff; padding-right: 23px; background: url(https://ssl.apple.com/global/nav/images/shortcuts_arrow.gif) no-repeat 99% 50%; padding-top: 3px; padding-bottom: 3px; font: bold 11px "Lucida Grande", "Lucida Sans Unicode", Arial, Verdana, sans-serif; } ul.sp-results li.hoverli { background: #b7b7b7 none repeat-x; color: #fff; cursor: pointer; } ul.sp-results li.hoverli h4 a { color: #fff; } ul.sp-results li.hoverli p { color: #f1f1f1; } ul.sp-results li span.text { display: block; position: absolute; left: 68px; width: 240px; } ul.sp-results li h4 { margin: 0; font-size: 11px; font-weight: bold; } ul.sp-results li p { margin: 0; font-size: 10px; overflow: hidden; height: 2.7em; color: #555; } ul.sp-results li a { color: #606060; text-decoration: none; } ul.sp-results li img, ul.sp-results li .replacementimg { position: absolute; left: 10px; width: 46px; height: 46px; } ul.sp-results li h4 a { color: #191919; } ul.sp-results li.viewall.hover { background: url(https://ssl.apple.com/global/nav/images/shortcuts_bg_foot_grey.png) no-repeat bottom left; } #sp-search-spinner { position: absolute; top: 13px; right: 16px; z-index: 10; display: none; } #sp-search-cancel img { cursor: pointer; } #sp-results .firstCat { position: absolute; top: -25px; left: 0; width: 308px; height: 8px; background: url(https://ssl.apple.com/global/nav/images/shortcuts_bg_head_grey.png) no-repeat left top; _background: url(https://ssl.apple.com/global/nav/images/shortcuts_bg_head_grey.gif) no-repeat left top; } #sp-result-none.viewall {bottom: -27px; *bottom: -27px;} #sp-result-none.viewall a { font-size: 10px; } /*--- Global Footer (legacy) ---*/ #globalfooter .gf-buy { float: left; width: 60%; margin: 18px 0 9px; } #globalfooter .gf-links { float: right; margin: 18px 0 9px; } #globalfooter .gf-links a { padding: 0 10px; white-space: nowrap; } #globalfooter .gf-links a.last { padding-right: 0; _float: none !important; width: auto !important; } /*--- Global Footer ---*/ #globalfooter { width: 980px; color: #888; font-size: 10px; margin: 18px auto; padding-bottom: 36px; text-align: left !important; } #globalfooter a { color: #08c; } #globalfooter p { margin-bottom: 1em; } #globalfooter p.gf-buy { float: left; width: 52%; margin: 18px 0 9px 3px; } #globalfooter ul.piped a { padding: 0 0 0 1.5em; margin-left: 1.5em; border-left: 1px solid #d0d0d0; } #globalfooter .gf-links { float: right; margin: 18px 3px 9px 0; } #globalfooter .gf-sosumi { clear: both; width: 100%; border-top: 1px solid #ddd; padding-top: 9px; } #globalfooter .gf-sosumi a { padding: 0 10px; } #globalfooter .gf-sosumi p { float: left; margin-left: 3px; } #globalfooter form { margin: 18px 10px; } #globalfooter .search-wrapper { margin: 0 auto; } #globalfooter .search-wrapper input.prettysearch { margin-left: 10px; } #globalfooter ul.piped a.contact_us { padding-right: 1.5em; border-right: 1px solid #d0d0d0; } #globalfooter ul.piped a.choose { margin-left: 0; border: 0; } #globalfooter ul.piped a.choose img { vertical-align: middle; margin-top: -5px; position: relative; } /*--- Breadcrumbs (legacy) ---*/ #globalfooter #breadcrumbs { font-size: 11px; color: #444; background: url(https://ssl.apple.com/global/nav/images/breadcrumb_bg.png) no-repeat; overflow: hidden; height: 36px; line-height: 34px; font-weight: bold; text-shadow: 2px 2px 1px #fff; } #globalfooter #breadcrumbs a { color: #444; text-decoration: none; float: left; padding: 0 10px; position: relative; margin-left: -10px; _cursor: hand; } #globalfooter #breadcrumbs a:hover { color: #333; text-decoration: none !important; } #globalfooter #breadcrumbs a.home { margin: 0; width: 15px; height: 0; padding-top: 36px; overflow: hidden; } #globalfooter #breadcrumbs span { float: left; width: 9px; margin: 0 10px 0 0; position: relative; height: 0; padding-top: 34px; margin-top: 1px; overflow: hidden; background: url(https://ssl.apple.com/global/nav/images/breadcrumb_sep.png) no-repeat; } /*--- Breadcrumbs ---*/ #globalfooter ol#breadcrumbs { font-size: 11px; color: #444; background: url(https://ssl.apple.com/global/nav/images/breadcrumb_bg.png) no-repeat; height: 36px; line-height: 34px; margin: 0; list-style: none; font-weight: bold; text-shadow: 2px 2px 1px #fff; } #globalfooter ol#breadcrumbs li { float: left; margin: 0; padding: 0 0 0 20px; background: url(https://ssl.apple.com/global/nav/images/breadcrumb_sep_20080909.png) no-repeat; } #globalfooter ol#breadcrumbs li a { float: left; color: #444; text-decoration: none; padding: 0 10px; margin-left: -10px; } #globalfooter ol#breadcrumbs li a:hover { color: #333; text-decoration: none; } #globalfooter ol#breadcrumbs li.home { background: none; margin: 0; padding: 0; } #globalfooter ol#breadcrumbs li.home a { margin: 0; padding: 0 10px; width: 15px; text-indent: -9999px; overflow: hidden; } /*--- Directory Nav ---*/ #directorynav { font-size: 11px; background: url(https://ssl.apple.com/global/nav/images/directory_bg.png) repeat-y; border-top: 1px solid #e5e5e5; float: left; width: 100%; position: relative; margin-top: -4px; } #directorynav .column { width: 122px; padding: 9px 0 4px 18px; } #directorynav .column.last { float: left !important; padding-right: 0; } #directorynav h3 { color: #666; font-weight: bold; } #directorynav h3.standalone { margin-bottom: 18px; } #directorynav a { color: #888; text-decoration: none; display: block; zoom: 1; } #directorynav h3.standalone a:link, #directorynav h3.standalone a:visited { color: #444; } #directorynav a:hover { color: #333 !important; text-decoration: none !important; } #directorynav .capbottom { clear: both; position: relative; top: 5px; _top: 12px; height: 5px; width: 980px; background: url(https://ssl.apple.com/global/nav/images/directory_capbg.png) no-repeat; } #directorynav ul { margin-bottom: 0; padding-bottom: 9px; } #directorynav .column { width: 120px; } #directorynav.mac #dn-cola { width: 120px; } #directorynav.mac #dn-colb { width: 115px; } #directorynav.mac #dn-cold { width: 110px; } #directorynav.mac #dn-colg { width: 130px; } #directorynav.iphone .column { width: 146px; padding: 9px 0 0 45px; } #directorynav.ipoditunes .column { width: 177px; } /*--- BREADORY ---*/ #breadory { border: 1px solid #ddd; width: 978px; margin: 0 auto; -moz-border-radius: 4px; -webkit-border-radius: 4px; } #globalfooter #breadory ol#breadcrumbs { background: none; clear: both; float: none; height: 3em; line-height: 3em; font-size: 11px; color: #666; margin: 0; list-style: none; font-weight: bold; text-shadow: 2px 2px 1px #fff; } #breadory ol#breadcrumbs li { background: none; float: left; margin: 0; padding: 0 0 0 1em; } #breadory ol#breadcrumbs li a { float: left; color: #666; text-decoration: none; padding: 0 1.75em 0 0; margin-left: 0px; background: url(https://ssl.apple.com/global/nav/images/breadcrumb_separator.png) no-repeat 100% 50%; } #breadory ol#breadcrumbs li a:hover { color: #333; text-decoration: none; } #breadory ol#breadcrumbs li.home { background: none; margin: 0; padding: 0; } #breadory ol#breadcrumbs li.home a { background: url(https://ssl.apple.com/global/nav/images/breadcrumb_home.png) no-repeat 1.25em 50%; margin: 0; padding: 0 0 0 1.25em; width: 30px; text-indent: -9999px; overflow: hidden; } #breadory ol#breadcrumbs li.home a:hover { background-image: url(https://ssl.apple.com/global/nav/images/breadcrumb_home_over.png); } #breadory #directorynav { background: none; clear: both; float: none; margin-top: 0; } #breadory #directorynav .capbottom { height: 0; font-size: 1px; _display: none; } /* PRODUCTHEADER */ #productheader { position: relative; border-bottom: 1px solid #ddd; padding: 1em 0 0.2em; overflow: hidden; width: 980px; margin: 0 auto; *height: 39px; } #productheader h1, #productheader h2 { line-height: 32px; display: inline; float: left; margin: 1px 0 6px 8px; padding: 0; margin-bottom: 6px !important; } #productheader h1 a, #productheader h2 a { line-height: 32px; background-position: 0 0; background-repeat: no-repeat; color: #888; display: block; font-weight: normal; height: 32px; position: relative; outline: none; text-decoration: none; text-indent: -9999px; } body#overview #productheader h1 a, body#overview #productheader h2 a { cursor: default; } #productheader ul { display: inline; float: right; margin: 0; } #productheader ul li { display: inline; } #productheader ul li a { color: #999; float: left !important; margin-top: 1em; margin-left: 30px; margin-right: 8px; padding: 0; text-decoration: none; } #productheader ul li a:hover { color: #08c; } #productheader a.buynow, #productheader a.ordernow, #productheader a.joinnow, #productheader a.preorder, #productheader a.preorder_blue, #productheader a.freetrial, #productheader a.downloadnow, #productheader a.upgradenow { height: 25px; margin: 0.7em 0 0 20px; background-position: 0 0; background-repeat: no-repeat; display: block; float: right; position: relative; text-decoration: none; text-indent: -9999px; outline: none; overflow: hidden; behavior: url(/global/scripts/lib/iepngfix.htc); } #productheader a.buynow { width: 72px; background-image: url(https://ssl.apple.com/global/elements/buttons/buynow.png); } #productheader a.ordernow { width: 81px; background-image: url(https://ssl.apple.com/global/elements/buttons/ordernow.png); } #productheader a.joinnow { width: 72px; background-image: url(https://ssl.apple.com/global/elements/buttons/joinnow.png); } #productheader a.preorder { width: 99px; background-image: url(https://ssl.apple.com/global/elements/buttons/preorder.png); } #productheader a.preorder_blue { width: 75px; background-image: url(https://ssl.apple.com/global/elements/buttons/preorder_blue.png); } #productheader a.freetrial { width: 72px; background-image: url(https://ssl.apple.com/global/elements/buttons/freetrial.png); } #productheader a.downloadnow { width: 108px; height: 26px; background-image: url(https://ssl.apple.com/global/elements/buttons/downloadnow.png); } #productheader a.upgradenow { width: 104px; background-image: url(https://ssl.apple.com/global/elements/buttons/upgradenow.png); } /* holiday promos */ #promofooter #promos li.holiday { background: #e3f4fd; } #promofooter #promos li.holiday h4, #promofooter #promos li.holiday p { z-index: 5; position: relative; } #promofooter #promos li.holiday a.image { z-index: 4; } /* PRINT */ @media print { body, #main, #content { color: #000 !important; } a, a:link, a:visited { color: #000 !important; text-decoration:none !important; } #tabs, #globalheader, #globalfooter, #directorynav, .noprint, .hide { display: none !important; } #main a.pdf, #main a.html, #main a.qt, #main a.ical, #main a.dl, #main a.dmg, #main a.zip, #main a.keynote, #main a.audio { padding-left: 0 !important; background-image: none !important; } } /* iPhone */ @media screen and (max-device-width: 480px) { html { -webkit-text-size-adjust: none; } } _.https://ssl.apple.com/support/css/ssl/base.cssObplist00 X$versionT$topY$archiverX$objects_WebResourceResponse_NSKeyedArchiver( &,-3%45WXYZ[\]^_`abcdefghijklmnopqrswxU$null  !"#$%V$classR$3R$8S$10S$11R$5R$6R$4R$7R$2R$9R$0R$1'& '()$+WNS.base[NS.relative_.https://ssl.apple.com/support/css/ssl/base.css./01X$classesZ$classname12UNSURLXNSObject#A/w5. 6789HWNS.keysZNS.objects%:;<=>?@ABCDEFG IJKLMNOPQRSTUV !"#$]Cache-Control_Content-Encoding\Content-TypeVServerTDate^Ntcoent-Length]X-Cached-TimeTEtag^Content-LengthSAgeWExpires]Accept-Ranges[X-Cache-Ttl]Last-Modified[max-age=600TgzipXtext/css_Apache/2.2.11 (Unix)_Sat, 20 Feb 2010 01:36:04 GMTU26690_Fri, 19 Feb 2010 09:26:53 GMT_"6842-476149defbb00"T5566S164_Sat, 20 Feb 2010 01:46:04 GMTUbytesS436_Fri, 16 Oct 2009 22:07:08 GMT./tuuv2_NSMutableDictionary\NSDictionaryhB./yzz{2_NSHTTPURLResponse]NSURLResponse)27:PRdGLU`cir{}$)8FKZ^ft!%EKOotx|Yimage/pngOsPNG  IHDRSq3gAMAOX2tEXtSoftwareAdobe ImageReadyqe<rIDATxT]`U*{W5vͧQcE%11$&%j5h"***Fb/J^w;3͝ov݅)/ϝym޻{=s \5#F8 8CY}o߾n…V Ʃ85`C3"NO;wu?7Hctȑ#GsVZKrf0N Ʃ8585] }}B_zð- ? 6lP*Zފ(Ʃ85`C_:Ϯ ׵o~Ey*\,rgSqj0N Ʃqj0,?X  X85`S`XbOc]Smٳgӧ޽{WܻY`Sqj K58A5Ex}7j(7oHQ|In]w} ֻ;]ҿg}֪U+7kˆݍ7 W]uղ/ &i𪁎)SmۺZuդ93UVYE6A06;?&Lp>!+XnD~ _vmc=̙#y7֭hLNo;v{E} LWssnr4L:5O&hedI%/Ur @Gt NCuH t+a3g=ChQ}^sl`nĉnڴB{~x ."ׯ_/r[Ϗ|8c.{G4pΏu *Fa/zW^yō3F>N_|!A5\ӭʲ~~ٳgK/7b߻M6]v?9_ufEu"a 749mfPy׿ץKw0>}^nfi`8 [fuu|uZR[&8Էv Kѣԃc9Fta2[Pru%Dx^}UwWP_jЗvu'Ous̒My紫q7pVWB9>FJ8Diyv ڤ+­U+ʍ$}2DÞ,j誶(ssr. 6@.O#<qliմ:ƞ^q .} y6/N8)[ʟѳ:K. /-ܲɜ6yQGW_]8!^K[R[&dѩ-X@UmRDe`#̱.)DV^>sV(dvAhD2u1}FEzͺw.JH_Ly cP rg;έJ@Ho':M6M F'|RM6ejUn&6| sK uGF)bPnn})=rO?T ph +/?l![oFh!7^{Cc1zk?8蠃޽Rt wޑuKl! ̐]cGYaz衑D 'K+SqwlMt\9E9ƽPFݫlA! sR~ wSy!cu]':^N@/ztg}&˗RIKc)SLYLrjH/v) ?ߥ$ef# TɕFzm, 4Cf"4'nVxcǎr.3`0 0q˽ O)M8=(q &0.LoF /hQjpѱ0;sNJ#bF`007nFČ3d? n=Kdž*129f TR148=Q H/&?| gE+NK[n90~}IVO د üةS'1䝿-J RSG2ZNakQ2' rF]w%|RgO믿rFs\6:qEjֽq' K`x[đպ}뭷/8/<|L/r1vf8u>iiy,9Eb]z饢:)^ )gĈM:YF:.36r"z3g 5Pkj,XƎ}[#qQ\Tc^JF%rn1Plp[om1DkO;41 W[m59u^{=r>o.;zG/qڲt6iOxկ~% z0!+q0b '<Y49uye]{)c *QC9DCIK걦Sik$l>t>>d^2IcqvȜ+. 9:uOd33c=~aIZ8Ȕ/򉃥|:}9~di Gp=fFݛT@CO'K2orM6ç4[ ,)_xS]t'Zn4*\:&*ZW铖r=Sʃ!;{#Y=[1]5nPLR}/]p.[X6P })g(~VBA@;4ǺRb2)+KzO?-6ci8guYGޏH+q^G-^V۪L:"#scXchv9-4n& 886ȞsV#7ɱb"B}~> :z\ڢSB9<+sG43WrTuIpjh#Zh+S;_2Āl8WiꪫJܖt*x|!u@UNij:.<*s[tY'u~9]b: &ZcB2xкRLj`p _QsP:^ ?v;sO *ojbPYSidԹGYCOZ!ε^N#26:=j4;C(~϶n+}gք<4(r qc N˥|AmؑM4Q 0e,fp|RrD^:bc[T:ɤ{zg@Y zᖠ g}3g;ܛ6x撩RӤ::R>i3=jŤI'aǯc_~1 ,/)N' YЏ|'z#RdR,v,!hË{ ?^Lgpo,V*OZREN_t.C=ʳ5U>c24 YdXu)WqLv ZnkΜ'Bck t߱j 0ye-z9–3-%h4/f*e̤yagRׅYOiiDj  f: -, PGJ0]4^zdn1&^:%Uʖ0Y뉞4~<OO3 M*? t#A"-TrW;:M92/^4 9+W!ӱZW'-) :6^y .ӅdM=2bWIvH#Knab%tXFZ@\TguE/VMS085``ؿo~q`h^ 8WEL^>f}RMIk!5UӔHG# 皴J(ġ``S4k\=7N GŌa ] pI5ұLzqYבxr𕋍5F85N Ʃ85 }ľմ=n -XWRnr'tHcg0yYFXI鮔2]e7Ʃqj0N Ʃ8eݟr85̱npP3N6=̪ Čf 85``0: ]Ze,$5`Sqj Kɱ1 [85`S`X u%V;tJ7NS`Sqj0N %X[De)k`Sqj KƱN/Zhf*`Q "wƩ85`Cˣ~&zф _vebbm`Sqj0NSa _:o/;w'V,`Sqj - |h|i|j6 .8?{ѢELSqj0NS85CC3;CKScw ٿ-"3 `0 !ќ6-TOK AP 6Vc`0 `0 kNnsCZQ /_>}nY`3gά*OչeY}w[`SqZќ-\ İ~pşgKjIKnPnv >L-U]k烡Jd/=m6rs5N$b qL"uYG 4C[gcω 3 ɰ8q̷zi3 l.3<͚5K x\v8sM@`yͲ;K/n%:jK_ uW^nb밡.REeʥ7c] z9 ՇB5Wu?oJ#ՔF\Rʍ$`@@H=W_d`P2LC唞j }o[o16tSq\|Rڳs![!q2?Q`bo|I$82s";y(Ug,]wٴ' 1G: )u6xF:.!ǔ?eH+iBEX+pNjV=tKSunL4)OngΜ)uhz \sM96j(;8|8̹C8P}oLgp=}}ݗ\rȮH!%x#sޅ:FNacs0h )lcVRo{'"H˝9€^S*F^+uCכ &r}U r.k!R_CLBը{ձ_ЏO?8 5*n_.rk\!7d 8dh]7cl$qrF? :1A9묳y{-OZREN iy$s]Lrs)s5>#bǛ"˴\\sԛ]ƳZ*f`ͷt Q6 A B˅?iLwyDuc  B[0QtvWtMb ӳO4WCƞF . ƣ>Zq~zȈnFЈsC/qڲ1^Z(i'Y  4r-K q&x/~yImsrDyAa= )g&b!/X+_>|ֱ*S{I}¿w|]=;,Nbc~QGIYaR7i:Tr{2~he3p@هe̾ ;Ę~2Ko1}[L<l@5>:1d.;<#cHӮRwo,m d-rTpC9yӷ9{Ny]TZƎ}[$Nj(!TRKvoKt^H7QՋ.HXcD~&roviw_cƯH8K4d8hiBðÈ HA C H9G.q1Xi<]!.N8Uv7*?:܏'R g}Od8 Iؾxu?|^1fcNY&GGT&!C3#Qat:\Qg(?"dmvrАA6$Du{w9&1N/lդ{dzgrmӿ&Eu&G>pCKov\ksq}\+IKc)d 5  7*d9hcǛ*) RS6c=jSB7rH'g q0+MqiW^yE^SN9Ezl8hDDgsj64VlŌy]-W)S ' F6qio6򍱨a̅\F/zp0hp&n&9֤(p a>k#dh7cF]bN _c9FRX>&!m!b^>uI(`B={杯:8~? Uj3/)NAQW|7d(3 fR@zDu9Q2~Y/C&՘@hcW񜋣OZRIN ([v̅8Mх@d1eS7U7Mf#̱v N*IߺښZW۪ OћBNz Jwi2>Rs*a_aEEO 11 pOa?V\> 1N[:N;R9tEz,TIgpiS 20x .18h2JNhIbl֣>~y%N3)$3[haQ3NkVk*wɶHW^cHN:!s˩_FHSWpp.20"3{u2/šKzVpazQ >"8cCtNFNZ/ [/3k*OZRANM||Gdٚ R1YV)WqTf7c] 3FCVc'&ҘBa,S9f&zsGL0D4^>򪫮wc2 "LA{ DCo.c)k:0nI1b\#AF9/Ӥcr!2,>Qz1tFBϠ_9s!Fyf-fKVR|ױUq4@d4^FIzP}U23x|$N:dhLgܷZuVRϩL5mgl2unt=<uⷵ'-) +@Y)-@SLj@@t,;eRŗZ*b=O8ᄉ"(aCnI$ gAÉVZZíغuki2 ()WU3N Ʃ85ipDpYxqPBl|aia*"FOZ@Hդ-{s$=ʽ,9m``Сޣq`h~TL*8ե4fD$]7t5s\ꬉ ġ``S db(v85̱nLPÌ̬3h8_gāfR3zqYqE1`u?x%rj=s]vu r{HzÈMo6g |p_}xWJ!`85`9?Ny@3a 3ÇG*XCrrA``SrjdJq*}tYO崘o4*j7S`Sqj0PIX`Sqj0NSP2E*:EcSqj0N Ʃ85N %Xs]Y FƩ85`V n(:]WWh֬Y5VM&Ʃ85`V,1c(c¿T1`SqZ ZP*W^y3gv")o;Sqj0N Ʃ8dN Rq~Gÿ֭[;Mym۶n…"wƩ85`V:C) .3w`0 `0 CCL OM­M՘cm0 `0 Cn"y;K.gΝ;SlPZ Ig@ cǎNsW\q1c @685`ipڷo_K 7,QuqZ7_׿sϋWKhhժ ,p[vQgC\t?1G6m".І4N Ʃ85NS8Nm-R@sFO36 ZRwap(n`JWɨRAWR\qj0N Ʃ85NJԖ2,-zcaÆ uLZVVή-S{50eSZE Jm޼yPp >p`S8Nڰ4Ѿ}phZJSmFCo/ `SqjƩX2:SXhO55[<%%ń |?4ʧ?vN Ʃ8585N+S6jpMѨ*u+i7|>#vە{8t>F`},Z48585NS8kC vqǚD*r_|ŹOֱ&R ƟW3dqj0N Ʃqji%p quY-ݒ(w_g}V{qz*[+(ϭ2N Ʃ85ƩqZIZdk_heUR)?tMz'd9+sOaX`Sqj©9ֆq*r]fM&K.PϞ=]zr]vu'Nt;wvm۶-;s'Xsl4`Sqjĩ9ֆqtr ܸqܜ9s$ǚ9quW_۷lŦ+#6w}Ν+-2F8\9$:u+lHNg̘!sFP_C"S?7pUVYEte]Et,mewG*ɹiL/%-[&|b !ka85P2uƷr_>w9=#ջ[o=#WvpLR1k7e]*ߗ[nS0I@sJm֭!9?1(F9cv~asb8nyηqvɝnС"++{W_}mf+C=ƌPo^EDӧOw'O69mfznwÇgĩc6d{NVnNMNE&~k-Q'%_Ruw;dP~ghbieMT׸6cWLq Г# /.ZT) X`VOChPwHov޽s7 ([ oV8xSO=%y1&ҍJ4#|C_͟7M<5T]iZ I+H̀ϙ.C\b=\vd9ώ/KdN^8 &#mJ+Eאj1ǏڑjJPJVi0Iӈ2j"F>N KY$ PĹǩv9"Cq[o-AM7T +@kϲk-g!\[eN?AF-6'D#ȯ>'ИswމRq6'PrzuE' {Gq;蠃lԱrRVL䖺S!e  pc=:R+N 1iҤ<9syʞڣ 1\s5بQ4X w|WqpDsE p2ߘzx.$铟* '|>Q@dzӅVX!5o,+dKJIN p mK+¾89Q+M9+tY.,TܔS܌ʼn<ҮP00KtPo( Frx7|Sl}F7` 7FvuW\ "468h7dIsmg-k:"/q|ထYBʩᄏUh0k/I޽8ipc`h5rd.xP.Xc zL,7ؘp=Cf0я9첋ӧuK.#)qd}λPI0lLq $:-3v؊Ss7wOQiYŸCޏH:NnFűrxƸS`ssQt׿b,rѴg4}y˧{s|2Di0/Kt l1K~e $K4j!G3c+brnN'Foӳ|iSL0twJR!9E6ٔ;NZz|wI;ߥׇ2+&Gu</魩9n:{w:˘3ĵ;aB>L"hFa@qC8s|-: GwVݛ$lRH c=&yC/HwMdC8hSov>"#;cdLߵ`C_7k])OC]N/x#[axRY( hS3eN)Ǜ"SRbmW,q%S=48}B%?se]T+`"7v qƀWZk(rp9Iu/Ni艎 'zEIcD.J}i9nj_#pR0Hy㴅KѓD捇W #/guA)A[ӵSE!k~z|aILF pmcuD^>I=ffcNYHD9rv8JӤ2dhu2Dk sEaH'%`"4dG> )qw"8r￿dQAo?}5$~2 p(w86k2E.rL݆_3>_zX]UJ1}S䔉2Ӌb^4  7*d9hEcǛ*g-6)ZPQtX4iҷնqÆ>.cMqg JwiҒTN9ղXD9%MT0xs'8FT+*g8m9k:uH9DR'I!RSM$q^ G PrqNp CKe$i5ƠNI#$Y4'iz w ;=zqɤ]sOi^zHҹwE1.M݉&ݏ0ɞPc~ir)pe]B=eD!Q hNwPzOv^I89i u\NjSO=UNL\4\96C85NS`bJ4>9kڳ8r[>v =\yn]Ouqf ޕZrr%-3ƣi5Ʃqj`S6c=)7Cg)410"NÇGuYCr`T4_%qZ qjƩ85ϩku*5::B9sβѣG_Ӛ2e8 u&|J㴒aƩqj0N Ʃqjd뤈VNK9x:SR~85N Ʃ85NS8NmVpC8~Ǟ!C)xNjL|iSqj0NS95 %X8Q!ƚgALj,Sym`ƩqjV n(:PʄJ31ES: F… # S8585NS8kDXgRUqJdz?f=ئ`JOc،Ʃqj0N Ʃqji%qj0, L0~|jyӧOk׮H4RI)1lJCl7m m5N Ʃ85ƩqZ) K sdSX.^k;tplP:45)-cK%x,*g?`b0N Ʃ85NS8-wN %>ꫯ/N§V́%zfƗ"3 `0 !ќ6-TOK AP 6Vc`0 `0 kNnsCZQ]FqN]]I.V^ Rb^~es\*Hm};85N Ʃ85o߾2Ī_:=mܹ\k9r)['{V,[6BS0NSqj0N Ʃ!ܖa)K]]9[oa}!uͰaRul.Aжm۰hR2 ' U%z7 Hg 8C'pWk]#DgRn*Op:<9<=/;s:{J}t]|/*{37/}Zhٓ{g<ۙJ FS85NS85Nr[|h|vl(ODP,mZqu\MXLźU v _6ҁ5XK:qjƩqjƩq̩X&?X3YYGTTjRudK2 i:xaj\oo.J RQ\4R 8OgA6bEnqrG!;?C9S,{QOd"?s:A> mTgqbE3CqjƩqjƩq̩X2:SK*xExfϞOz]q%\:MVUby GVùhgt5j 2t.*J%#iTA3{o~??]kC6]*ېy/=aYFX:טhzXϙ %j$c,ƩqjƩqjɜZPcTSwFrsj O&5`Ƀecimh)MzG[C* ^N6NS85NS85Nrj=ֆAPX5s>;#AkQnP\=#]}u{׳hy\WQB梮&RNr~jlYuOdקrjT6 ?ܩ>{MM}~)7MM>qܮ&.wwq3>íUVn֬9ϻoAe_`PvoMLx/Z-BMfL{k-FJ2&SL2b[G-Gz-oDnFnחcCjHNW_muw)'oýƛns  ?S8BzuȐhm驧:ovcĉOIFftsukȭf9]wovۆ@l3f4"2ܱ fΜyC-ZT1-X`(i~nUV㢋.r+rQ, {o&[1sM-}o q/rQ8]|Nyݻ+ǎpE?NIN4p7V,hf"ٵkl4-7x3f{KFNi`0':u[ynYsYRtf LfL.N'hFN_y׽{w1*A T"ũ k |QaRSoCygcwݽR&B;= cK/cl;S}vI阤;pO>1T=3|;%Ja*ezf\}RVo;s vm'*Rf]Y8pN jp w]wѸ*׽N&[U} ԓo^~UWͭJΡGNf̘׮];|R:{K/q^r _c$;Cn:nI'I]m`y&JS|}R޽iT}S 姕x ׽[7 A;>}F+)`s ;_hT':i_LEwQ>c~]Do&q(O>dwdo&=Ytt}&JTP7ú*3t^Ik{w__S>(#g묻SðQvBPl圗E^͕r B3suEI$"y<wG:SW_-C% _{ o/?ӡUmK򪲨Y^oxQY^si$ n()Ǻ}I6tjܰ>}NcB3MC;_(?<WPO, *'iz(qx9oا%q!_s5xJkj2תsF /{DCBo4ţ!PN9!=#c,TӃE{"_%wxYW2IF1g_5l`N)7!HԹ*Ā!;?:TtQIK2rǧwFƊF ua(.~:/A\iG% 16gP\8y܃^1=ԵJݛT Zm"^Fu`鱖 IG۵k#tk!"?C|RoLgC7zOx((bc)57qaMutrP|y]Y]1 hiʩcm()Ǻ#cNKl=&V y*M}:j<;#%j {>|}֬2NPDŽ{,'&t R޹sSi0i;4 4&J)!HJGP:ukte0h|)HܼqFgdwQEӋB߅abV}}~anР#ilU'hӺg9*;_2ҩ_.?7[O1-dJ#CTzBV?4ŵ0 2LNa:HE|:aX\B^zرrh a ~<~|7 }Cz㰧eg`̾ZUiܯ}=zveO~F0F3 ,g|=Y N.c9#)oyܼAgMEcn  I0yfVMh ipzXO~wZx'':?'FqHBNcLzCNNMs)ΐwX˗fg fӸFwhkV ෪Vfb e=9m['ևmq2O#ʘvm/|YiiS)5QM58!3C:ct u]ro*pO"y|9ytˆ肈Oʖ yjkۡ0ѾFYFwK/u.A>E=ۆ:{̳)9>묳$R hϛoyb4řFpձֱp 1QXe U&qi׾k㢾F$s<}JRjcQ| ri<N %:H!AȌ $Bp=c ^OҨhQ_~8={.v ;ƶtF4+&w.k<ԲBd3Lp_Ӆ/&j:=,VPrNÆs7_3#Nv8KYqaXF;w>+IN(W)ÚP~u]PNЇ|&I'Ox;R= V XI<+eݨ^c"y!gM z2Kp9yo&NwjVN_Fe=Hѫ)O]:g&_J[JZfΉe\krSժ{AO֡]&K,h5$sDӷ)O{,wٝ?o~V_tND6q6o<(\=3礲Ro]]+9lv2;3鳒sўsjzD?5߯2C _Lr%(N:2CLf_J_d{+ɔE~0N;w 99)]s/5g.z鵽{ΕglLT9 fAL/>:wuݨ3YNSV{XGRG>!lUi(ܔSK!N132"N38m߶}vRTQNqW {;wn{vo]=N]"\ ({uĝrJQeF_'l}h[6 ];w/{ۅ[!+mxjާ"i @9oFBmO=C;*Qez6Sڶonszrk 9mׁ9EڬRAEL^uS QVR %/W$p/wh/|˅NSTtdtsbK{ʞ O\~މwf t@\R5%?ᢋR.XJNCjYD TFF6xNEHu)i+34K*嗸<`q>UcƩqjƩqq9q ANI׀JsjJʱc#FY+IUtJRtIRFԌllf|o%C\\|V ;F~K)${ 977AE 9M*nVzK0Di]:*!ohƌq])eEcȟ2H2*& 7y-E4Ot*IZ'(r"pyF4Cm SXdOX2 -Nq^^,_ ?n.]v"3b\^#:Zʛ85NS85NSNu6nzTcm0Ǻ|5Ld@5%dӣ=tPףG͌\%)WZ'Ɠ{qżYJKzN2Er5}+_,؛# fTt 4JNfuY :& їʛ3j?!6HN25LA.mRXGKޠ&hxoH2GS85NS85Nӆcm0Ǻì4,_~3+ɩK8*/꘷B(I뺸twsT5|x7>CƩqjƩqjiCNmVpC8֕c[̄5QSNyWԟlVsx-Lkj4o0.I^uBN[F`DR?'kڈFGi4X%M$C.ƠeNFrS~CQDODmu<5QAy\8085NS85NS!8ԕj(cR'*˱˦p/MT7T~dԟH;a {8pB<^9PH=Ua'񌝂PQ_R;le- "Ҩ$+^])q.p̤:j)gr]j 폚FÒLS[ #=زjO]8Utq%6):+>H9ՅS8S8S8S8S89p:8M~kd&tV6+XrS(}ֿ3hvB)H TzT)f Vy_ꎍbS1$)9XބS8S8S8S8ӑS~2w$>󤩒Ui+C HLFU*d9A\vIKpavmmtʩڄd%MΡs+9-b LuSp9.I{7Y_D[+;!6l^HS8S8S8S8ӑS~DK,]bX_i ѿ~B2@L٦M\iW~uLl@uJ-xRwVAΑ+w/oQɂS8S8S8S8?3ع%.1~3%7Xo5.>x~lU}M` NJ{-,Ic޳IENDB`_7https://ssl.apple.com/global/nav/images/globalnavbg.pngObplist00 X$versionT$topY$archiverX$objects_WebResourceResponse_NSKeyedArchiver$ &,-3%45STUVWXYZ[\]^_`abcdefghijkopU$null  !"#$%V$classR$3R$8S$10S$11R$5R$6R$4R$7R$2R$9R$0R$1#" '()$+WNS.base[NS.relative_7https://ssl.apple.com/global/nav/images/globalnavbg.png./01X$classesZ$classname12UNSURLXNSObject#A/w6G 6789FWNS.keysZNS.objects!:;<=>?@ABCDE GHIJKLMNOPQR ]Last-ModifiedSAgeWExpires]Cache-Control]Accept-Ranges\Content-TypeVServerTDate^Content-Length]X-Cached-TimeTEtag[X-Cache-Ttl_Sun, 10 Jun 2007 18:52:13 GMTT1361_Sat, 20 Feb 2010 02:27:01 GMT\max-age=3600UbytesYimage/png_Apache/2.2.11 (Unix)_Sat, 20 Feb 2010 01:27:01 GMTU29471_Fri, 19 Feb 2010 04:39:56 GMT_"731f-43291c32d1140"T2239./lmmn2_NSMutableDictionary\NSDictionarys./qrrs2_NSHTTPURLResponse]NSURLResponse)27:PRd LQZehnw+27FTYe$;@EI_lotxtOPNG  IHDR5^KMgAMAOX2tEXtSoftwareAdobe ImageReadyqe<0IDATxb,//g```<~8#?bbZP,Xnݺ <~EIENDB`_>https://ssl.apple.com/global/nav/images/searchfield_repeat.pngOtbplist00 X$versionT$topY$archiverX$objects_WebResourceResponse_NSKeyedArchiver" &,-3%45QRSTUVWXYZ[\]^_`abcdefgklU$null  !"#$%V$classR$3R$8S$10S$11R$5R$6R$4R$7R$2R$9R$0R$1!  '()$+WNS.base[NS.relative_>https://ssl.apple.com/global/nav/images/searchfield_repeat.png./01X$classesZ$classname12UNSURLXNSObject#A/w7  6789EWNS.keysZNS.objects:;<=>?@ABCD FGHIJKLMNOP]Cache-ControlWExpiresSViaSAge\Content-TypeVServerTDate^Content-LengthTEtagZConnection]Last-Modified\max-age=3600_Sat, 20 Feb 2010 02:25:22 GMT_1.1 cup-www-squid03:80T1460Yimage/png_Apache/2.2.11 (Unix)_Sat, 20 Feb 2010 01:25:22 GMTS158_"9e-43291c32d1140"ZKeep-Alive_Sun, 10 Jun 2007 18:52:13 GMT./hiij2_NSMutableDictionary\NSDictionary./mnno2_NSHTTPURLResponse]NSURLResponse)27:PRd  QV_jms|-2=KXx $:GINRfpt !OPNG  IHDR#uBtEXtSoftwareAdobe ImageReadyqe<&IDATxMKcg77MTRBN;w7fՁY  XVqT5yC2L7& GCoAK&'tttvrT*o=u<3څ4<֥R1ys[l6+αcKǠV!T*e#ЂzCj 5jo?,Jammg6 MPW*vwwC__ [q~~tXXX]^6lnnӐNC. SSS\.PVCP###6 jѼxw|u lA󏘎nnnj󹱱fm>88hzL>!4:nzLoooeuCwwwc}ggg nlzqX__'''6 C[[텭-@PGMҚiu#k377WoxI_Ѱ666B:vwP(. TX (8u _@PA 5pYVmZPocPxL <#sl1?.<==|&rlαbd$S2C%g2' ܄D KIENDB`_9https://ssl.apple.com/global/nav/images/breadcrumb_bg.pngObplist00 X$versionT$topY$archiverX$objects_WebResourceResponse_NSKeyedArchiver$ &,-3%45STUVWXYZ[\]^_`abcdefghijkopU$null  !"#$%V$classR$3R$8S$10S$11R$5R$6R$4R$7R$2R$9R$0R$1#" '()$+WNS.base[NS.relative_9https://ssl.apple.com/global/nav/images/breadcrumb_bg.png./01X$classesZ$classname12UNSURLXNSObject#A/w7In 6789FWNS.keysZNS.objects!:;<=>?@ABCDE GHIJKLMNOPQR ]Last-ModifiedSAgeWExpires]Cache-Control]Accept-Ranges\Content-TypeVServerTDate^Content-Length]X-Cached-TimeTEtag[X-Cache-Ttl_Sun, 10 Jun 2007 18:52:10 GMTS617_Sat, 20 Feb 2010 02:39:26 GMT\max-age=3600UbytesYimage/png_Apache/2.2.11 (Unix)_Sat, 20 Feb 2010 01:39:26 GMTS900_Fri, 19 Feb 2010 04:41:15 GMT_"384-43291c2ff4a80"T2983./lmmn2_NSMutableDictionary\NSDictionary./qrrs2_NSHTTPURLResponse]NSURLResponse)27:PRd NS\gjpy -49HV[g#9>CG]jmrvt#$%OEPNG  IHDR ! nKtEXtSoftwareAdobe ImageReadyqe<IDATxڄ= 0q(c xcx 3zd=k$@&9cZZL|,W m~pqEMqVQ"Q܈in5?j@E&4.i\ӤIc Eq$eJt,K:=)f2E&6J, ?*~U܈U܈UHTHTh誼PI8+JZIENDB`_:https://ssl.apple.com/global/nav/images/breadcrumb_sep.pngObplist00 X$versionT$topY$archiverX$objects_WebResourceResponse_NSKeyedArchiver$ &,-3%45STUVWXYZ[\]^_`abcdefghijkopU$null  !"#$%V$classR$3R$8S$10S$11R$5R$6R$4R$7R$2R$9R$0R$1#" '()$+WNS.base[NS.relative_:https://ssl.apple.com/global/nav/images/breadcrumb_sep.png./01X$classesZ$classname12UNSURLXNSObject#A/w7P 6789FWNS.keysZNS.objects!:;<=>?@ABCDE GHIJKLMNOPQR ]Last-ModifiedSAgeWExpires]Cache-Control]Accept-Ranges\Content-TypeVServerTDate^Content-Length]X-Cached-TimeTEtag[X-Cache-Ttl_Sun, 10 Jun 2007 18:52:11 GMTT1187_Sat, 20 Feb 2010 02:19:32 GMT\max-age=3600UbytesYimage/png_Apache/2.2.11 (Unix)_Sat, 20 Feb 2010 01:19:32 GMTS325_Fri, 19 Feb 2010 05:47:35 GMT_"145-43291c30e8cc0"T2413./lmmn2_NSMutableDictionary\NSDictionaryE./qrrs2_NSHTTPURLResponse]NSURLResponse)27:PRd OT]hkqz!.5:IW\h%;@EI_lotxt'()OK#main h1 { font-weight: normal; } #main h2 { font-size:110%; margin-bottom:0; } #main ul { margin-bottom:0; } #main ul.square { margin-left: 1.5em; } #main ul.square li { line-height: 1.3em; padding: 4px 0; } #main ul.video li { line-height: 1.3em; padding: 4px 0; padding-left: 18px; background: url(https://ssl.apple.com/support/_images/icon_video_sm.gif) no-repeat 0 5px; } #main ul.manual li { line-height: 1.3em; padding: 4px 0; padding-left: 18px; background: url(https://ssl.apple.com/support/_images/icon_manual_sm.png) no-repeat 0 5px; } #main li.manual { display:inline; line-height: 1.3em; padding: 4px 0; padding-left: 18px; background: url(https://ssl.apple.com/support/_images/icon_manual_sm.png) no-repeat 0 5px; } #main li.video { display:inline; line-height: 1.3em; padding: 4px 0; padding-left: 18px; background: url(https://ssl.apple.com/support/_images/icon_video_sm.gif) no-repeat 0 5px; } #main a.more { text-align:left; background: url(https://ssl.apple.com/support/_images/morearrow.png) 100% 0.4em no-repeat; padding-right: 9px; *display:inline-block; } a { text-decoration: none; } a:hover { text-decoration:underline; } hr { margin: 14px 0; border:0; height:1px; color:#ccc; background-color:#ccc; } .divider { border-top:1px solid #ccc; margin-bottom:10px; } /* original search */ #country { padding-bottom: 10px; } #country select { font-size: 85%; } #globalfooter { margin-top: 30px; } #search { float: right; margin-top:1px; } #search .restrict { padding:5px 0 5px 5px; font-size:10px; color:#686868; } /* make pretty search fit sidebar */ input.prettysearch { width:175px; } .search-wrapper { width: 175px; } .search-wrapper input.prettysearch { width: 146px; *margin-left: 20px; } /* UTILITY BAR */ #utilbar { padding:7px 10px; background: url(https://ssl.apple.com/support/_images/utilbar.gif) no-repeat center top; } #utilbar .first #search { height:25px; float:left; } #utilbar .first #search a { color:#666; } #utilbar .first input.prettysearch { width:220px; } #utilbar .first .search-wrapper { width: 220px; } #utilbar .first .search-wrapper input.prettysearch { width: 191px; } #utilbar .column { width:470px; } #utilbar #searchbox { float:left; } #utilbar #searchutils { float:left; color:#666; font-size:10px; padding:1px 10px; } #utilbar #articleutils { float:right; } #utilbar #articleutils .tool { position:relative; float:left; margin-right:10px; font-size:10px; color:#666; } #utilbar #articleutils .tool.last { } #utilbar #internal { line-height:14px; height:13px; margin:1px; padding:1px 6px 3px; text-align:center; font-size:10px; background: url(https://ssl.apple.com/support/iknow/images/button_internal.png) center center; } #utilbar #internal a { color:white; } #utilbar #internal a:hover { text-decoration:none; } #utilbar #countryselector { text-align:right; font-size:11px } #utilbar #email-container { width:250px; } #utilbar #email-send { margin-top:2px; padding-left:16px; background: url(https://ssl.apple.com/support/iknow/images/aqua2spinner12.gif) no-repeat center left } #utilbar #email-sent { margin-top:2px; padding-left:16px; background: url(https://ssl.apple.com/support/iknow/images/i_greencheck.gif) no-repeat center left } #utilbar #email-address { width:120px; height:13px; font-size:11px; margin:1px 2px; } #utilbar #sendbutton { font-size:11px; } /* wide pretty search for product browser */ #pb-search, #pb-search a { color:#fff; font-size:13px; } #pb-search { padding:10px; background:url(https://ssl.apple.com/support/iknow/images/pb_searchbg.gif) no-repeat bottom; } #pb-search input.prettysearch { width:320px; } #pb-search .search-wrapper { width: 320px; } #pb-search .search-wrapper input.prettysearch { width: 291px; } #pb-searchlabel { float:left; max-width:130px; margin:1px 8px 0 0; line-height:1.2em; } #pb-searchfield { float:left; } /* new utilbar for advanced search */ #utilbar-advanced #pb-search-topcap { height:5px; background:url(https://ssl.apple.com/support/iknow/images/pb_searchbg_topcap.gif) no-repeat bottom; } #utilbar-advanced #pb-search { padding:4px 10px; background:url(https://ssl.apple.com/support/iknow/images/pb_searchbg_advanced.gif) no-repeat bottom; } #utilbar-advanced #pb-search a { display:block; font-size:10px; margin:2px 0 0 5px; color:#ccc; } #utilbar-advanced a.searchtips { padding-left:12px; background:url(https://ssl.apple.com/support/iknow/images/searchtips.gif) no-repeat 1px 5px; } #utilbar-advanced a.searchtips-down { background:url(https://ssl.apple.com/support/iknow/images/searchtipsdown.gif) no-repeat 1px 5px; } #utilbar-advanced #pb-searchtips { margin:5px 0; font-size:10px; color:#eee; } #utilbar-advanced #pb-searchtips td { padding-left:16px; } #utilbar-advanced #pb-searchtips .arrowlink { text-align:right; padding:0 16px 0 0; background-image:url(https://ssl.apple.com/support/iknow/images/arrow_jump.gif); } #utilbar-advanced #pb-searchtips .column.first { width:100%; max-width:650px; min-height:60px; _height:60px; } #utilbar-advanced #pb-searchtips .column.last { position:absolute; top:73px; right:11px; _top:83px; } #utilbar-advanced #searchbox { float:left; } #utilbar-advanced #articleutils { position:absolute; top:14px; right:1px; } #utilbar-advanced #articleutils .tool { position:relative; float:left; margin-right:10px; font-size:10px; color:#ccc; } #utilbar-advanced #articleutils .tool.last { } #utilbar-advanced #searchutils { position:absolute; top:14px; right:11px; _top:24px; } #utilbar-advanced #searchutils .tool { float:right; } #utilbar-advanced #searchutils #country { float:right; line-height:1.8em; padding:1px 12px 0 5px; background:url(https://ssl.apple.com/support/iknow/images/searchtips.gif) no-repeat right 55%; } #utilbar-advanced #searchutils a { cursor:pointer; } #utilbar-advanced #searchutils a:hover { _background:none; } /* modification to reposition #articleutils for unified search */ #article #articleutils { float:right; margin:8px -10px 0 0; } #article #articleutils .tool { position:relative; float:left; margin-right:10px; font-size:10px; color:#444; } #article #articleutils #email-form, #articleutils #email-address { margin:0 3px; } /* non-expanding version */ #utilbar-advanced #searchlinks { margin:1px 0 0 1px; } #utilbar-advanced #searchlinks a { display:inline; padding:0 12px 0 0; margin-right:10px; background:url(https://ssl.apple.com/support/iknow/images/searchtips.gif) no-repeat right 55%; } #utilbar-advanced #pb-search.noexpand { height:36px; } /*#utilbar-advanced #email-container { width:250px; margin-top:2px; }*/ #utilbar-advanced #email-container { margin-top:2px; white-space:nowrap; } #utilbar-advanced #email-send { margin-top:3px; padding-left:20px; background: url(https://ssl.apple.com/support/iknow/images/aqua2spinner_adv.gif) no-repeat center left } #utilbar-advanced #email-sent { margin-top:3px; padding-left:18px; background: url(https://ssl.apple.com/support/iknow/images/i_greencheck_adv.gif) no-repeat center left } #utilbar-advanced #email-address { width:120px; height:13px; font-size:11px; margin:1px 2px; } #utilbar-advanced #sendbutton { font-size:11px; } /* SIDEBAR FOR 2 COLUMN LAYOUTS */ #sidebar { width:228px; float:left; } #main ul.buttons { margin:0; padding:4px 8px 10px 8px; font-size:11px; } #main ul.buttons li { margin:3px 2px 0 2px; list-style-type:none; } #main ul.buttons li a { display:block; height:13px; padding:2px 12px 4px 12px; color:#5c5c5c; text-decoration:none; font-weight:bold; } #main ul.buttons li a.selected { color:#fff; background:url(https://ssl.apple.com/support/iknow/images/button_selected.png) 0 0 no-repeat; } #main ul.buttons .count { font-size:10px; color:#a9a9a9; } #main ul.buttons li a.selected .count { color:#d0d0d0; } /* rounded corners */ /* !!!! make these into 1 image !!!! */ .module { border:1px solid #e5e5e5; background: url(https://ssl.apple.com/support/_images/module_background.gif) repeat-x bottom; _background: url(https://ssl.apple.com/support/_images/module_background_ie.gif) repeat-x bottom; *background: url(https://ssl.apple.com/support/_images/module_background_ie.gif) repeat-x bottom; } .tl, .tr, .bl, .br { position:relative; } .tl { background: transparent url(https://ssl.apple.com/support/_images/tl.gif) no-repeat top left; top:-1px; left: -1px; } .tr { background: transparent url(https://ssl.apple.com/support/_images/tr.gif) no-repeat top right; right: -2px; } .bl { background: transparent url(https://ssl.apple.com/support/_images/bl.gif) no-repeat bottom left; bottom: -2px; left: -2px; } .br { background: transparent url(https://ssl.apple.com/support/_images/br.gif) no-repeat bottom right; right: -2px; *bottom: 0; } .arrowlink { text-align: left; padding:2px 16px 2px 0; background: url(https://ssl.apple.com/support/_images/arrow_jump.gif) no-repeat center right; } .arrowlinklast { text-align: left; padding:2px 16px 2px 0; background: url(https://ssl.apple.com/support/_images/arrow_jump.gif) no-repeat center right; } .titleicon { float:right; padding:0 10px; } /* left menu bar */ #menu h2 { position:relative; top:-1px; left:-1px; padding: 3px 7px; color:white; font-weight:normal; background-color:#aaa; background: url(https://ssl.apple.com/support/_images/module_headerbg.png) no-repeat center top; } #menu h2 a { color: white; } #menu h2 a:hover { text-decoration:underline; color: white; } #menu h3 { padding: 1px 10px; padding-top: 12px; } #menu ul { padding-bottom: 10px; } #menu li { line-height: 1.2em; padding: 4px 10px; } #menu hr { margin: 8px 15px; border:0; height:1px; color:#ccc; background-color:#ccc; } #menu a { color: #666; } #menu a:hover { text-decoration:underline; color: #333; } #menu select { font-size: 85%; margin: 0 10px; width:140px; } #menu .arrowlink { background: url(https://ssl.apple.com/support/_images/arrow_jump_white.gif) no-repeat center right; } #menu .module { background-color: transparent; margin: 0 0 15px 0; font-size: 95%; } #menu .hilite { position:relative; left:-1px; background-color: #e8e8e8; } /*#main h2 { font-weight:normal; }*/ #resourcespsp .module h2 { position:relative; top:-1px; left:-1px; padding: 3px 10px; color:white; font-weight:normal; background-color:#aaa; background: url(https://ssl.apple.com/support/_images/module_headerbg_wide.png) no-repeat center top; } #resourcespsp .module h2 a { color:white; } #resourcespsp .module h2 .arrowlink { background: url(https://ssl.apple.com/support/_images/arrow_jump_white.gif) no-repeat center right; } #resourcespsp .module h2 .headerlinkright { float:right; position:relative; left:0px; } /* right sidebar */ #rightsidebar img { padding:8px 0; } #rightsidebar ul { padding-bottom: 5px; } #rightsidebar .module h2 { position:relative; top:-1px; left:-1px; padding: 3px 7px; color:white; font-size:11px; font-weight:normal; background-color:#aaa; background: url(https://ssl.apple.com/support/_images/module_headerbg.png) no-repeat center top; } #rightsidebar .lefticon { float:left; padding:0; margin:5px 10px 5px 0; } #rightsidebar .desc { padding-bottom:10px; } /* featured group */ #featured h1 { margin-bottom:5px; } #featured li { margin-bottom:4px; } #main .subbar { font-size:14px; font-weight:bold; color:#8390a7; margin-bottom:18px; } #main h1.subbar { font-size:24px; font-weight:normal; color:black; margin-bottom:0; } /* resources group */ #featured #resourcelinks { padding:0; } /* new featured area with borders */ #resourcelinks { padding:15px 0; } /* old featured area without borders */ #resourcelinks li { float: left; margin-right:10px; padding-right:15px; font-size: 95%; } #resourcelinkshome { padding-top:10px; } #resourcelinkshome li { float: left; margin-right:25px; padding-right:25px; font-size: 100%; } #resourceshome ul { padding-top:18px; } #resourceshome .column { padding-right: 15px; border-right: 1px solid #e0e0e0; } #resourceshome .column.last { padding-right:0; border-right: none; } #resourcespsp h3 { font-size:14px; font-weight:bold; color:#8390a7; } #resourcespsp h4 { font-size:12px; font-weight:bold;} #resourcespsp ul { padding-bottom:10px; } #resourcespsp .column { padding-right: 20px; border-right: none; } #resourcespsp .column.last { width:48%; padding-right:0; border-right: none; } #coveragetool { margin-bottom:8px; } #coveragetool ul { padding-top:0; } #coveragetool .inputtext { width:175px; } #coveragetool .column { padding-right:0; border-right: none; } /* family pages */ #navgrid h1 { padding-top:20px; } #navgrid ul { margin: 0 0 40px 0; } #navgrid li { text-align: center; } #navgrid img { margin: 10px; } #navgrid .arrowlink { text-align: left; padding: 5px 15px 5px 0; border-bottom: 1px solid #e0e0e0; } #navgrid .arrowlink.last { border-bottom:none; } #navgrid .column { padding-right:20px; border-right: 1px solid #e0e0e0; } #navgrid .column.last { padding-right:0; border-right: none; } /* tables of information */ #tablegrid th { font-size:10px; color:#666; padding:5px 15px 10px 0; } #tablegrid td { font-size:10px; color:#666; padding:5px 15px 5px 0; border-bottom:1px solid #e0e0e0 } #tablegrid td.last { padding:5px 15px 20px 0; border-bottom:none } /* basic table styles */ #main .smallfont { font-size:10px; } #main .maxwidth { width:100%; } #main table.basictable th, #main table.basictable td { padding: 5px 10px; } #main table.basictable th { font-weight:bold; border-right:1px solid #ddd; background:#bababa url(https://ssl.apple.com/support/_images/table_headerbg.gif) repeat-x 0 100%; } #main table.basictable th.sorted { background:#909090 url(https://ssl.apple.com/support/_images/table_headerbg_sorted.gif) repeat-x 0 100%; } #main table.basictable th.ascending { background:#797979 url(https://ssl.apple.com/support/_images/table_headerbg_sorted_asc.gif) no-repeat center right; padding-right:25px; } #main table.basictable th.descending { background:#797979 url(https://ssl.apple.com/support/_images/table_headerbg_sorted_desc.gif) no-repeat center right; padding-right:25px; } #main table.basictable th a { color:#fff; } #main table.basictable td { border-bottom: 1px solid #ddd; } #main table.basictable tr.odd { background:#fff; } #main table.basictable tr.even { background:#efefef; } #main table.basictable tr.odd td, #main table.basictable tr.even td { border:none; } /* sitemap */ #sitemap h3 { padding-top:15px; } #sitemap li { font-weight:bold; } #sitemap li a { font-weight:normal; } /* flow pages */ #flow h2 { font-size:130%; margin-bottom:15px; color:#8a96ad; } #flow .note { padding:10px; border:1px solid #ccc; background:#ffffe8; } #flow ul { margin:1em 0; } #buttongroup { text-align:right; margin-bottom:15px; } #buttongroup a { height: 20px; padding: 3px 0 3px 20px; color: white; font-weight:bold; background:transparent url(https://ssl.apple.com/support/_images/acbutton_background_l.gif) no-repeat center left; } .acbutton { height: 20px; padding: 3px 20px 3px 0; background:transparent url(https://ssl.apple.com/support/_images/acbutton_background_r.gif) no-repeat center right; } #errorbox { width:640px; margin-top:50px; margin-left:auto; margin-right:auto; } #alert { border:1px solid #ddd; padding:8px 15px 8px 38px; margin-bottom:10px; background:#ffffd9 url(https://ssl.apple.com/support/home/images/icon_alert.gif) no-repeat 5px top; } /* alerts */ .alert { border:1px solid #ddd; padding:8px; margin-bottom:10px; background:transparent no-repeat 5px top; } .alert.yellow { background-color:#ffffd9; } .alert.icn { padding:8px 15px 8px 38px; background-image: url(https://ssl.apple.com/support/home/images/icon_alert.gif); } /* warranty checker */ #personalization { float:right; margin:-10px 0 0 10px; font-size:11px; text-align:right; } #warranty h1 { padding:20px 0 0 20px; margin-bottom:0; } #warranty #tagline { color:#888; margin-left:20px; } #warranty #serialnumber { font-size:12px; padding:2px; margin:5px 0; } #warranty button.happy { font-size:12px; font-weight:bold; color:black; padding:3px 12px; } #warranty #warrantycheckspinner { position:absolute; margin:6px 0 0 4px; } #warranty #product { padding:10px; margin:20px 20px 0 20px; border:1px solid #ddd; background:#fff url(https://ssl.apple.com/support/applecare/images/warranty_product_bg.jpg) repeat-x 0 0; } #warranty #productimage { display:block; float:left; padding:5px 20px 5px 15px;} #warranty #productinfo { padding-top:8px; } #warranty #productinfo h2 { font-size:18px; font-weight:normal; margin-bottom:5px; } #warranty #productinfo .sosumi { margin:10px 0 0 0; } #warranty #dateofpurchase { margin:5px 0 35px; } #warranty #dateofpurchase label { margin-right:10px; } #warranty #register, #warranty #results { padding:20px; } #warranty #results .status { padding-left:50px; min-height:40px; } #warranty #results .green { background:url(https://ssl.apple.com/support/applecare/images/warranty_status_green.png) no-repeat 5px 5px; } #warranty #results .yellow { background:url(https://ssl.apple.com/support/applecare/images/warranty_status_yellow.png) no-repeat 5px 5px; } #warranty #results .red { background:url(https://ssl.apple.com/support/applecare/images/warranty_status_red.png) no-repeat 5px 5px; } #warranty #results table { width:100%; } #warranty #results td { border-bottom:1px solid #dedede; padding:10px 0; } #warranty #results td p { margin-bottom:0; } #warranty #results td.button { width:200px; text-align:right; vertical-align:center; } #warranty #results td.button button { width:170px; } .rightbuttons { text-align:right; } /* text pages */ .grid1col { width:75%; } .pad10 { padding: 10px; } .pad15 { padding: 15px; } .pad20 { padding: 20px; } .padtop5 { padding-top: 5px;} .padtop10 { padding-top: 10px;} .padtop15 { padding-top: 15px;} .padtop20 { padding-top: 20px;} .padtop25 { padding-top: 25px;} .padtop30 { padding-top: 30px;} .padtop35 { padding-top: 35px;} .padright10 { padding-right: 10px;} .padright20 { padding-right: 20px;} /* base.css page grid overrides */ .grid2colc .grid2cola .column.first { width: 66%;} .grid2colc .grid2cola .column.last { width: 32%;} .grid2colc .grid2colb .column.first { width: 582px;} .grid2colc .grid2colb .column.last { width: 184px;} .grid2colc .grid2colb .grid2col .column.first { width: 47%;} .grid2colc .grid2colb .grid2col .column.last { width: 46%;} .grid2colc .column.first { width: 184px; } .grid2colc .column.last { width: 781px; } .grid2colc .grid2col .column { width: 49%; } .grid2colc .grid4col .column { width: 23%; margin-left: 2%; } .grid2colc:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } .grid3col .column { width: 29%; } .grid3col .column.first { width: 29%; } .grid3col .column.last { width: 32%; float: right; } /* hack for sites with old header */ #tabs { padding-bottom: 15px; } /* global footer with country selector flag */ #globalfooter .gf-sosumi ul.piped li.country_selector { float:right; text-align:right; } #globalfooter .gf-sosumi ul.piped li.country_selector a { display:inline; border-left:none; margin-left:0px; padding-left:0; cursor:pointer; line-height:19px; } #globalfooter .gf-sosumi ul.piped li.country_selector p { float:right; padding:0 9px 0 5px; margin:0; background:transparent url(http://images.apple.com/support/home/images/morearrow.png) no-repeat right center; } #globalfooter .gf-sosumi ul.piped li.country_selector p:hover { text-decoration:underline; } #globalfooter .gf-sosumi ul.piped li.country_selector img { width:20px; height:20px; margin-top:-1px; border:none; } _-https://ssl.apple.com/support/css/support.cssObplist00 X$versionT$topY$archiverX$objects_WebResourceResponse_NSKeyedArchiver( &,-3%45WXYZ[\]^_`abcdefghijklmnopqrswxU$null  !"#$%V$classR$3R$8S$10S$11R$5R$6R$4R$7R$2R$9R$0R$1'& '()$+WNS.base[NS.relative_-https://ssl.apple.com/support/css/support.css./01X$classesZ$classname12UNSURLXNSObject#A/w51 6789HWNS.keysZNS.objects%:;<=>?@ABCDEFG IJKLMNOPQRSTUV !"#$]Cache-Control_Content-Encoding\Content-TypeVServerTDate^Ntcoent-Length]X-Cached-TimeTEtag^Content-LengthSAgeWExpires]Accept-Ranges[X-Cache-Ttl]Last-Modified[max-age=600TgzipXtext/css_Apache/2.2.11 (Unix)_Sat, 20 Feb 2010 01:37:03 GMTU19414_Fri, 19 Feb 2010 09:28:02 GMT_"4bd6-479c7cd614780"T4344S105_Sat, 20 Feb 2010 01:47:03 GMTUbytesS495_Thu, 03 Dec 2009 00:09:18 GMT./tuuv2_NSMutableDictionary\NSDictionaryK./yzz{2_NSHTTPURLResponse]NSURLResponse)27:PRdFKT_bhqz|#(7EJY]es $DJNnsw|+,-.Yimage/gifO.GIF89a !, ;_;https://ssl.apple.com/support/_images/module_background.gifObplist00 X$versionT$topY$archiverX$objects_WebResourceResponse_NSKeyedArchiver$ &,-3%45STUVWXYZ[\]^_`abcdefghijkopU$null  !"#$%V$classR$3R$8S$10S$11R$5R$6R$4R$7R$2R$9R$0R$1#" '()$+WNS.base[NS.relative_;https://ssl.apple.com/support/_images/module_background.gif./01X$classesZ$classname12UNSURLXNSObject#A/w7c  6789FWNS.keysZNS.objects!:;<=>?@ABCDE GHIJKLMNOPQR ]Last-ModifiedSAgeWExpires]Cache-Control]Accept-Ranges\Content-TypeVServerTDate^Content-Length]X-Cached-TimeTEtag[X-Cache-Ttl_Wed, 06 Jun 2007 22:37:35 GMTS716_Sat, 20 Feb 2010 02:26:54 GMT\max-age=3600UbytesYimage/gif_Apache/2.2.11 (Unix)_Sat, 20 Feb 2010 01:26:54 GMTR46_Fri, 19 Feb 2010 09:26:19 GMT_"2e-4324471c8e9c0"T2884./lmmn2_NSMutableDictionary\NSDictionary../qrrs2_NSHTTPURLResponse]NSURLResponse)27:PRd PU^ilr{"/6;JX]i$9>CG]jlqut+012OpGIF89a !, P`PW!_x ȕeq`¶[;_,https://ssl.apple.com/support/_images/tl.gifObplist00 X$versionT$topY$archiverX$objects_WebResourceResponse_NSKeyedArchiver$ &,-3%45STUVWXYZ[\]^_`abcdefghijkopU$null  !"#$%V$classR$3R$8S$10S$11R$5R$6R$4R$7R$2R$9R$0R$1#" '()$+WNS.base[NS.relative_,https://ssl.apple.com/support/_images/tl.gif./01X$classesZ$classname12UNSURLXNSObject#A/w7 6789FWNS.keysZNS.objects!:;<=>?@ABCDE GHIJKLMNOPQR ]Last-ModifiedSAgeWExpires]Cache-Control]Accept-Ranges\Content-TypeVServerTDate^Content-Length]X-Cached-TimeTEtag[X-Cache-Ttl_Wed, 06 Jun 2007 22:26:58 GMTT1301_Sat, 20 Feb 2010 02:17:39 GMT\max-age=3600UbytesYimage/gif_Apache/2.2.11 (Unix)_Sat, 20 Feb 2010 01:17:39 GMTS112_Fri, 19 Feb 2010 05:46:42 GMT_"70-432444bd11080"T2299./lmmn2_NSMutableDictionary\NSDictionaryp./qrrs2_NSHTTPURLResponse]NSURLResponse)27:PRd AFOZ]cluw~ ',;INZz,16:P]_dh|t+456OqGIF89a !, 0ILPji ٶI ޹%dz[I;_,https://ssl.apple.com/support/_images/tr.gifObplist00 X$versionT$topY$archiverX$objects_WebResourceResponse_NSKeyedArchiver$ &,-3%45STUVWXYZ[\]^_`abcdefghijkopU$null  !"#$%V$classR$3R$8S$10S$11R$5R$6R$4R$7R$2R$9R$0R$1#" '()$+WNS.base[NS.relative_,https://ssl.apple.com/support/_images/tr.gif./01X$classesZ$classname12UNSURLXNSObject#A/w7 6789FWNS.keysZNS.objects!:;<=>?@ABCDE GHIJKLMNOPQR ]Last-ModifiedSAgeWExpires]Cache-Control]Accept-Ranges\Content-TypeVServerTDate^Content-Length]X-Cached-TimeTEtag[X-Cache-Ttl_Wed, 06 Jun 2007 22:26:59 GMTS359_Sat, 20 Feb 2010 02:33:21 GMT\max-age=3600UbytesYimage/gif_Apache/2.2.11 (Unix)_Sat, 20 Feb 2010 01:33:21 GMTS113_Fri, 19 Feb 2010 05:46:44 GMT_"71-432444be052c0"T3241./lmmn2_NSMutableDictionary\NSDictionaryq./qrrs2_NSHTTPURLResponse]NSURLResponse)27:PRd AFOZ]cluw~ ',;INZz~+059O\^cg{t+89:OGIF89a 蹹ﳳ!, + e$)剎CZ͒?@ABCD FGHIJKLMNOP]Cache-ControlWExpiresSViaSAge\Content-TypeVServerTDate^Content-LengthTEtagZConnection]Last-Modified\max-age=3600_Sat, 20 Feb 2010 02:42:00 GMT_1.1 cup-www-squid03:80S463Yimage/gif_Apache/2.2.11 (Unix)_Sat, 20 Feb 2010 01:42:00 GMTS174_"ae-432444c78e940"ZKeep-Alive_Wed, 06 Jun 2007 22:27:09 GMT./hiij2_NSMutableDictionary\NSDictionary./mnno2_NSHTTPURLResponse]NSURLResponse)27:PRd  ?DMX[ajsu|  +9Ff '46;?Spa+<=>OGIF89a 鴴г!, *%cEY#C4L exH ;%;_,https://ssl.apple.com/support/_images/br.gifObplist00 X$versionT$topY$archiverX$objects_WebResourceResponse_NSKeyedArchiver$ &,-3%45STUVWXYZ[\]^_`abcdefghijkopU$null  !"#$%V$classR$3R$8S$10S$11R$5R$6R$4R$7R$2R$9R$0R$1#" '()$+WNS.base[NS.relative_,https://ssl.apple.com/support/_images/br.gif./01X$classesZ$classname12UNSURLXNSObject#A/w7p 6789FWNS.keysZNS.objects!:;<=>?@ABCDE GHIJKLMNOPQR ]Last-ModifiedSAgeWExpires]Cache-Control]Accept-Ranges\Content-TypeVServerTDate^Content-Length]X-Cached-TimeTEtag[X-Cache-Ttl_Wed, 06 Jun 2007 22:27:09 GMTS881_Sat, 20 Feb 2010 02:35:02 GMT\max-age=3600UbytesYimage/gif_Apache/2.2.11 (Unix)_Sat, 20 Feb 2010 01:35:02 GMTS173_Fri, 19 Feb 2010 04:39:00 GMT_"ad-432444c78e940"T2719./lmmn2_NSMutableDictionary\NSDictionary./qrrs2_NSHTTPURLResponse]NSURLResponse)27:PRd AFOZ]cluw~ ',;INZz~+059O\^cg{t@ABCZimage/jpegOJFIFddDuckyPAdobed      dZ QabS ?uP۪ 4rPP*W*0V@V@ jm`F|# # aa?_Fhttps://ssl.apple.com/support/applecare/images/warranty_product_bg.jpgObplist00 X$versionT$topY$archiverX$objects_WebResourceResponse_NSKeyedArchiver$ &,-3%45STUVWXYZ[\]^_`abcdefghijkopU$null  !"#$%V$classR$3R$8S$10S$11R$5R$6R$4R$7R$2R$9R$0R$1#" '()$+WNS.base[NS.relative_Fhttps://ssl.apple.com/support/applecare/images/warranty_product_bg.jpg./01X$classesZ$classname12UNSURLXNSObject#A/w7Q 6789FWNS.keysZNS.objects!:;<=>?@ABCDE GHIJKLMNOPQR ]Last-ModifiedSAgeWExpires]Cache-Control]Accept-Ranges\Content-TypeVServerTDate^Content-Length]X-Cached-TimeTEtag[X-Cache-Ttl_Tue, 14 Jul 2009 21:36:21 GMTT2338_Sat, 20 Feb 2010 02:00:21 GMT\max-age=3600UbytesZimage/jpeg_Apache/2.2.11 (Unix)_Sat, 20 Feb 2010 01:00:21 GMTS392_Fri, 19 Feb 2010 05:48:15 GMT_"188-46eb13ac37f40"T1262./lmmn2_NSMutableDictionary\NSDictionary./qrrs2_NSHTTPURLResponse]NSURLResponse)27:PRd [`itw} -:AFUcht2HMRVly|tEFGH_application/x-javascriptO/* Prototype JavaScript framework, version 1.6.0.2 * (c) 2005-2008 Sam Stephenson * * Prototype is freely distributable under the terms of an MIT-style license. * For details, see the Prototype web site: http://www.prototypejs.org/ * *--------------------------------------------------------------------------*/ var Prototype = { Version: '1.6.0.2', Browser: { IE: !!(window.attachEvent && !window.opera), Opera: !!window.opera, WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1, MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/) }, BrowserFeatures: { XPath: !!document.evaluate, ElementExtensions: !!window.HTMLElement, SpecificElementExtensions: document.createElement('div').__proto__ && document.createElement('div').__proto__ !== document.createElement('form').__proto__ }, ScriptFragment: ']*>([\\S\\s]*?)<\/script>', JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/, emptyFunction: function() { }, K: function(x) { return x } }; if (Prototype.Browser.MobileSafari) Prototype.BrowserFeatures.SpecificElementExtensions = false; /* Based on Alex Arnell's inheritance implementation. */ var Class = { create: function() { var parent = null, properties = $A(arguments); if (Object.isFunction(properties[0])) parent = properties.shift(); function klass() { this.initialize.apply(this, arguments); } Object.extend(klass, Class.Methods); klass.superclass = parent; klass.subclasses = []; if (parent) { var subclass = function() { }; subclass.prototype = parent.prototype; klass.prototype = new subclass; parent.subclasses.push(klass); } for (var i = 0; i < properties.length; i++) klass.addMethods(properties[i]); if (!klass.prototype.initialize) klass.prototype.initialize = Prototype.emptyFunction; klass.prototype.constructor = klass; return klass; } }; Class.Methods = { addMethods: function(source) { var ancestor = this.superclass && this.superclass.prototype; var properties = Object.keys(source); if (!Object.keys({ toString: true }).length) properties.push("toString", "valueOf"); for (var i = 0, length = properties.length; i < length; i++) { var property = properties[i], value = source[property]; if (ancestor && Object.isFunction(value) && value.argumentNames().first() == "$super") { var method = value, value = Object.extend((function(m) { return function() { return ancestor[m].apply(this, arguments) }; })(property).wrap(method), { valueOf: function() { return method }, toString: function() { return method.toString() } }); } this.prototype[property] = value; } return this; } }; var Abstract = { }; Object.extend = function(destination, source) { for (var property in source) destination[property] = source[property]; return destination; }; Object.extend(Object, { inspect: function(object) { try { if (Object.isUndefined(object)) return 'undefined'; if (object === null) return 'null'; return object.inspect ? object.inspect() : String(object); } catch (e) { if (e instanceof RangeError) return '...'; throw e; } }, toJSON: function(object) { var type = typeof object; switch (type) { case 'undefined': case 'function': case 'unknown': return; case 'boolean': return object.toString(); } if (object === null) return 'null'; if (object.toJSON) return object.toJSON(); if (Object.isElement(object)) return; var results = []; for (var property in object) { var value = Object.toJSON(object[property]); if (!Object.isUndefined(value)) results.push(property.toJSON() + ': ' + value); } return '{' + results.join(', ') + '}'; }, toQueryString: function(object) { return $H(object).toQueryString(); }, toHTML: function(object) { return object && object.toHTML ? object.toHTML() : String.interpret(object); }, keys: function(object) { var keys = []; for (var property in object) keys.push(property); return keys; }, values: function(object) { var values = []; for (var property in object) values.push(object[property]); return values; }, clone: function(object) { return Object.extend({ }, object); }, isElement: function(object) { return object && object.nodeType == 1; }, isArray: function(object) { return object != null && typeof object == "object" && 'splice' in object && 'join' in object; }, isHash: function(object) { return object instanceof Hash; }, isFunction: function(object) { return typeof object == "function"; }, isString: function(object) { return typeof object == "string"; }, isNumber: function(object) { return typeof object == "number"; }, isUndefined: function(object) { return typeof object == "undefined"; } }); Object.extend(Function.prototype, { argumentNames: function() { var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip"); return names.length == 1 && !names[0] ? [] : names; }, bind: function() { if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; var __method = this, args = $A(arguments), object = args.shift(); return function() { return __method.apply(object, args.concat($A(arguments))); } }, bindAsEventListener: function() { var __method = this, args = $A(arguments), object = args.shift(); return function(event) { return __method.apply(object, [event || window.event].concat(args)); } }, curry: function() { if (!arguments.length) return this; var __method = this, args = $A(arguments); return function() { return __method.apply(this, args.concat($A(arguments))); } }, delay: function() { var __method = this, args = $A(arguments), timeout = args.shift() * 1000; return window.setTimeout(function() { return __method.apply(__method, args); }, timeout); }, wrap: function(wrapper) { var __method = this; return function() { return wrapper.apply(this, [__method.bind(this)].concat($A(arguments))); } }, methodize: function() { if (this._methodized) return this._methodized; var __method = this; return this._methodized = function() { return __method.apply(null, [this].concat($A(arguments))); }; } }); Function.prototype.defer = Function.prototype.delay.curry(0.01); Date.prototype.toJSON = function() { return '"' + this.getUTCFullYear() + '-' + (this.getUTCMonth() + 1).toPaddedString(2) + '-' + this.getUTCDate().toPaddedString(2) + 'T' + this.getUTCHours().toPaddedString(2) + ':' + this.getUTCMinutes().toPaddedString(2) + ':' + this.getUTCSeconds().toPaddedString(2) + 'Z"'; }; var Try = { these: function() { var returnValue; for (var i = 0, length = arguments.length; i < length; i++) { var lambda = arguments[i]; try { returnValue = lambda(); break; } catch (e) { } } return returnValue; } }; RegExp.prototype.match = RegExp.prototype.test; RegExp.escape = function(str) { return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); }; /*--------------------------------------------------------------------------*/ var PeriodicalExecuter = Class.create({ initialize: function(callback, frequency) { this.callback = callback; this.frequency = frequency; this.currentlyExecuting = false; this.registerCallback(); }, registerCallback: function() { this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); }, execute: function() { this.callback(this); }, stop: function() { if (!this.timer) return; clearInterval(this.timer); this.timer = null; }, onTimerEvent: function() { if (!this.currentlyExecuting) { try { this.currentlyExecuting = true; this.execute(); } finally { this.currentlyExecuting = false; } } } }); Object.extend(String, { interpret: function(value) { return value == null ? '' : String(value); }, specialChar: { '\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '\\': '\\\\' } }); Object.extend(String.prototype, { gsub: function(pattern, replacement) { var result = '', source = this, match; replacement = arguments.callee.prepareReplacement(replacement); while (source.length > 0) { if (match = source.match(pattern)) { result += source.slice(0, match.index); result += String.interpret(replacement(match)); source = source.slice(match.index + match[0].length); } else { result += source, source = ''; } } return result; }, sub: function(pattern, replacement, count) { replacement = this.gsub.prepareReplacement(replacement); count = Object.isUndefined(count) ? 1 : count; return this.gsub(pattern, function(match) { if (--count < 0) return match[0]; return replacement(match); }); }, scan: function(pattern, iterator) { this.gsub(pattern, iterator); return String(this); }, truncate: function(length, truncation) { length = length || 30; truncation = Object.isUndefined(truncation) ? '...' : truncation; return this.length > length ? this.slice(0, length - truncation.length) + truncation : String(this); }, strip: function() { return this.replace(/^\s+/, '').replace(/\s+$/, ''); }, stripTags: function() { return this.replace(/<\/?[^>]+>/gi, ''); }, stripScripts: function() { return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); }, extractScripts: function() { var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); return (this.match(matchAll) || []).map(function(scriptTag) { return (scriptTag.match(matchOne) || ['', ''])[1]; }); }, evalScripts: function() { return this.extractScripts().map(function(script) { return eval(script) }); }, escapeHTML: function() { var self = arguments.callee; self.text.data = this; return self.div.innerHTML; }, unescapeHTML: function() { var div = new Element('div'); div.innerHTML = this.stripTags(); return div.childNodes[0] ? (div.childNodes.length > 1 ? $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : div.childNodes[0].nodeValue) : ''; }, toQueryParams: function(separator) { var match = this.strip().match(/([^?#]*)(#.*)?$/); if (!match) return { }; return match[1].split(separator || '&').inject({ }, function(hash, pair) { if ((pair = pair.split('='))[0]) { var key = decodeURIComponent(pair.shift()); var value = pair.length > 1 ? pair.join('=') : pair[0]; if (value != undefined) value = decodeURIComponent(value); if (key in hash) { if (!Object.isArray(hash[key])) hash[key] = [hash[key]]; hash[key].push(value); } else hash[key] = value; } return hash; }); }, toArray: function() { return this.split(''); }, succ: function() { return this.slice(0, this.length - 1) + String.fromCharCode(this.charCodeAt(this.length - 1) + 1); }, times: function(count) { return count < 1 ? '' : new Array(count + 1).join(this); }, camelize: function() { var parts = this.split('-'), len = parts.length; if (len == 1) return parts[0]; var camelized = this.charAt(0) == '-' ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) : parts[0]; for (var i = 1; i < len; i++) camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); return camelized; }, capitalize: function() { return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); }, underscore: function() { return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase(); }, dasherize: function() { return this.gsub(/_/,'-'); }, inspect: function(useDoubleQuotes) { var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) { var character = String.specialChar[match[0]]; return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16); }); if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; return "'" + escapedString.replace(/'/g, '\\\'') + "'"; }, toJSON: function() { return this.inspect(true); }, unfilterJSON: function(filter) { return this.sub(filter || Prototype.JSONFilter, '#{1}'); }, isJSON: function() { var str = this; if (str.blank()) return false; str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str); }, evalJSON: function(sanitize) { var json = this.unfilterJSON(); try { if (!sanitize || json.isJSON()) return eval('(' + json + ')'); } catch (e) { } throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); }, include: function(pattern) { return this.indexOf(pattern) > -1; }, startsWith: function(pattern) { return this.indexOf(pattern) === 0; }, endsWith: function(pattern) { var d = this.length - pattern.length; return d >= 0 && this.lastIndexOf(pattern) === d; }, empty: function() { return this == ''; }, blank: function() { return /^\s*$/.test(this); }, interpolate: function(object, pattern) { return new Template(this, pattern).evaluate(object); } }); if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { escapeHTML: function() { return this.replace(/&/g,'&').replace(//g,'>'); }, unescapeHTML: function() { return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); } }); String.prototype.gsub.prepareReplacement = function(replacement) { if (Object.isFunction(replacement)) return replacement; var template = new Template(replacement); return function(match) { return template.evaluate(match) }; }; String.prototype.parseQuery = String.prototype.toQueryParams; Object.extend(String.prototype.escapeHTML, { div: document.createElement('div'), text: document.createTextNode('') }); with (String.prototype.escapeHTML) div.appendChild(text); var Template = Class.create({ initialize: function(template, pattern) { this.template = template.toString(); this.pattern = pattern || Template.Pattern; }, evaluate: function(object) { if (Object.isFunction(object.toTemplateReplacements)) object = object.toTemplateReplacements(); return this.template.gsub(this.pattern, function(match) { if (object == null) return ''; var before = match[1] || ''; if (before == '\\') return match[2]; var ctx = object, expr = match[3]; var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/; match = pattern.exec(expr); if (match == null) return before; while (match != null) { var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1]; ctx = ctx[comp]; if (null == ctx || '' == match[3]) break; expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); match = pattern.exec(expr); } return before + String.interpret(ctx); }); } }); Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; var $break = { }; var Enumerable = { each: function(iterator, context) { var index = 0; iterator = iterator.bind(context); try { this._each(function(value) { iterator(value, index++); }); } catch (e) { if (e != $break) throw e; } return this; }, eachSlice: function(number, iterator, context) { iterator = iterator ? iterator.bind(context) : Prototype.K; var index = -number, slices = [], array = this.toArray(); while ((index += number) < array.length) slices.push(array.slice(index, index+number)); return slices.collect(iterator, context); }, all: function(iterator, context) { iterator = iterator ? iterator.bind(context) : Prototype.K; var result = true; this.each(function(value, index) { result = result && !!iterator(value, index); if (!result) throw $break; }); return result; }, any: function(iterator, context) { iterator = iterator ? iterator.bind(context) : Prototype.K; var result = false; this.each(function(value, index) { if (result = !!iterator(value, index)) throw $break; }); return result; }, collect: function(iterator, context) { iterator = iterator ? iterator.bind(context) : Prototype.K; var results = []; this.each(function(value, index) { results.push(iterator(value, index)); }); return results; }, detect: function(iterator, context) { iterator = iterator.bind(context); var result; this.each(function(value, index) { if (iterator(value, index)) { result = value; throw $break; } }); return result; }, findAll: function(iterator, context) { iterator = iterator.bind(context); var results = []; this.each(function(value, index) { if (iterator(value, index)) results.push(value); }); return results; }, grep: function(filter, iterator, context) { iterator = iterator ? iterator.bind(context) : Prototype.K; var results = []; if (Object.isString(filter)) filter = new RegExp(filter); this.each(function(value, index) { if (filter.match(value)) results.push(iterator(value, index)); }); return results; }, include: function(object) { if (Object.isFunction(this.indexOf)) if (this.indexOf(object) != -1) return true; var found = false; this.each(function(value) { if (value == object) { found = true; throw $break; } }); return found; }, inGroupsOf: function(number, fillWith) { fillWith = Object.isUndefined(fillWith) ? null : fillWith; return this.eachSlice(number, function(slice) { while(slice.length < number) slice.push(fillWith); return slice; }); }, inject: function(memo, iterator, context) { iterator = iterator.bind(context); this.each(function(value, index) { memo = iterator(memo, value, index); }); return memo; }, invoke: function(method) { var args = $A(arguments).slice(1); return this.map(function(value) { return value[method].apply(value, args); }); }, max: function(iterator, context) { iterator = iterator ? iterator.bind(context) : Prototype.K; var result; this.each(function(value, index) { value = iterator(value, index); if (result == null || value >= result) result = value; }); return result; }, min: function(iterator, context) { iterator = iterator ? iterator.bind(context) : Prototype.K; var result; this.each(function(value, index) { value = iterator(value, index); if (result == null || value < result) result = value; }); return result; }, partition: function(iterator, context) { iterator = iterator ? iterator.bind(context) : Prototype.K; var trues = [], falses = []; this.each(function(value, index) { (iterator(value, index) ? trues : falses).push(value); }); return [trues, falses]; }, pluck: function(property) { var results = []; this.each(function(value) { results.push(value[property]); }); return results; }, reject: function(iterator, context) { iterator = iterator.bind(context); var results = []; this.each(function(value, index) { if (!iterator(value, index)) results.push(value); }); return results; }, sortBy: function(iterator, context) { iterator = iterator.bind(context); return this.map(function(value, index) { return {value: value, criteria: iterator(value, index)}; }).sort(function(left, right) { var a = left.criteria, b = right.criteria; return a < b ? -1 : a > b ? 1 : 0; }).pluck('value'); }, toArray: function() { return this.map(); }, zip: function() { var iterator = Prototype.K, args = $A(arguments); if (Object.isFunction(args.last())) iterator = args.pop(); var collections = [this].concat(args).map($A); return this.map(function(value, index) { return iterator(collections.pluck(index)); }); }, size: function() { return this.toArray().length; }, inspect: function() { return '#'; } }; Object.extend(Enumerable, { map: Enumerable.collect, find: Enumerable.detect, select: Enumerable.findAll, filter: Enumerable.findAll, member: Enumerable.include, entries: Enumerable.toArray, every: Enumerable.all, some: Enumerable.any }); function $A(iterable) { if (!iterable) return []; if (iterable.toArray) return iterable.toArray(); var length = iterable.length || 0, results = new Array(length); while (length--) results[length] = iterable[length]; return results; } if (Prototype.Browser.WebKit) { $A = function(iterable) { if (!iterable) return []; if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') && iterable.toArray) return iterable.toArray(); var length = iterable.length || 0, results = new Array(length); while (length--) results[length] = iterable[length]; return results; }; } Array.from = $A; Object.extend(Array.prototype, Enumerable); if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse; Object.extend(Array.prototype, { _each: function(iterator) { for (var i = 0, length = this.length; i < length; i++) iterator(this[i]); }, clear: function() { this.length = 0; return this; }, first: function() { return this[0]; }, last: function() { return this[this.length - 1]; }, compact: function() { return this.select(function(value) { return value != null; }); }, flatten: function() { return this.inject([], function(array, value) { return array.concat(Object.isArray(value) ? value.flatten() : [value]); }); }, without: function() { var values = $A(arguments); return this.select(function(value) { return !values.include(value); }); }, reverse: function(inline) { return (inline !== false ? this : this.toArray())._reverse(); }, reduce: function() { return this.length > 1 ? this : this[0]; }, uniq: function(sorted) { return this.inject([], function(array, value, index) { if (0 == index || (sorted ? array.last() != value : !array.include(value))) array.push(value); return array; }); }, intersect: function(array) { return this.uniq().findAll(function(item) { return array.detect(function(value) { return item === value }); }); }, clone: function() { return [].concat(this); }, size: function() { return this.length; }, inspect: function() { return '[' + this.map(Object.inspect).join(', ') + ']'; }, toJSON: function() { var results = []; this.each(function(object) { var value = Object.toJSON(object); if (!Object.isUndefined(value)) results.push(value); }); return '[' + results.join(', ') + ']'; } }); // use native browser JS 1.6 implementation if available if (Object.isFunction(Array.prototype.forEach)) Array.prototype._each = Array.prototype.forEach; if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) { i || (i = 0); var length = this.length; if (i < 0) i = length + i; for (; i < length; i++) if (this[i] === item) return i; return -1; }; if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) { i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; var n = this.slice(0, i).reverse().indexOf(item); return (n < 0) ? n : i - n - 1; }; Array.prototype.toArray = Array.prototype.clone; function $w(string) { if (!Object.isString(string)) return []; string = string.strip(); return string ? string.split(/\s+/) : []; } if (Prototype.Browser.Opera){ Array.prototype.concat = function() { var array = []; for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); for (var i = 0, length = arguments.length; i < length; i++) { if (Object.isArray(arguments[i])) { for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) array.push(arguments[i][j]); } else { array.push(arguments[i]); } } return array; }; } Object.extend(Number.prototype, { toColorPart: function() { return this.toPaddedString(2, 16); }, succ: function() { return this + 1; }, times: function(iterator) { $R(0, this, true).each(iterator); return this; }, toPaddedString: function(length, radix) { var string = this.toString(radix || 10); return '0'.times(length - string.length) + string; }, toJSON: function() { return isFinite(this) ? this.toString() : 'null'; } }); $w('abs round ceil floor').each(function(method){ Number.prototype[method] = Math[method].methodize(); }); function $H(object) { return new Hash(object); }; var Hash = Class.create(Enumerable, (function() { function toQueryPair(key, value) { if (Object.isUndefined(value)) return key; return key + '=' + encodeURIComponent(String.interpret(value)); } return { initialize: function(object) { this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); }, _each: function(iterator) { for (var key in this._object) { var value = this._object[key], pair = [key, value]; pair.key = key; pair.value = value; iterator(pair); } }, set: function(key, value) { return this._object[key] = value; }, get: function(key) { return this._object[key]; }, unset: function(key) { var value = this._object[key]; delete this._object[key]; return value; }, toObject: function() { return Object.clone(this._object); }, keys: function() { return this.pluck('key'); }, values: function() { return this.pluck('value'); }, index: function(value) { var match = this.detect(function(pair) { return pair.value === value; }); return match && match.key; }, merge: function(object) { return this.clone().update(object); }, update: function(object) { return new Hash(object).inject(this, function(result, pair) { result.set(pair.key, pair.value); return result; }); }, toQueryString: function() { return this.map(function(pair) { var key = encodeURIComponent(pair.key), values = pair.value; if (values && typeof values == 'object') { if (Object.isArray(values)) return values.map(toQueryPair.curry(key)).join('&'); } return toQueryPair(key, values); }).join('&'); }, inspect: function() { return '#'; }, toJSON: function() { return Object.toJSON(this.toObject()); }, clone: function() { return new Hash(this); } } })()); Hash.prototype.toTemplateReplacements = Hash.prototype.toObject; Hash.from = $H; var ObjectRange = Class.create(Enumerable, { initialize: function(start, end, exclusive) { this.start = start; this.end = end; this.exclusive = exclusive; }, _each: function(iterator) { var value = this.start; while (this.include(value)) { iterator(value); value = value.succ(); } }, include: function(value) { if (value < this.start) return false; if (this.exclusive) return value < this.end; return value <= this.end; } }); var $R = function(start, end, exclusive) { return new ObjectRange(start, end, exclusive); }; var Ajax = { getTransport: function() { return Try.these( function() {return new XMLHttpRequest()}, function() {return new ActiveXObject('Msxml2.XMLHTTP')}, function() {return new ActiveXObject('Microsoft.XMLHTTP')} ) || false; }, activeRequestCount: 0 }; Ajax.Responders = { responders: [], _each: function(iterator) { this.responders._each(iterator); }, register: function(responder) { if (!this.include(responder)) this.responders.push(responder); }, unregister: function(responder) { this.responders = this.responders.without(responder); }, dispatch: function(callback, request, transport, json) { this.each(function(responder) { if (Object.isFunction(responder[callback])) { try { responder[callback].apply(responder, [request, transport, json]); } catch (e) { } } }); } }; Object.extend(Ajax.Responders, Enumerable); Ajax.Responders.register({ onCreate: function() { Ajax.activeRequestCount++ }, onComplete: function() { Ajax.activeRequestCount-- } }); Ajax.Base = Class.create({ initialize: function(options) { this.options = { method: 'post', asynchronous: true, contentType: 'application/x-www-form-urlencoded', encoding: 'UTF-8', parameters: '', evalJSON: true, evalJS: true }; Object.extend(this.options, options || { }); this.options.method = this.options.method.toLowerCase(); if (Object.isString(this.options.parameters)) this.options.parameters = this.options.parameters.toQueryParams(); else if (Object.isHash(this.options.parameters)) this.options.parameters = this.options.parameters.toObject(); } }); Ajax.Request = Class.create(Ajax.Base, { _complete: false, initialize: function($super, url, options) { $super(options); this.transport = Ajax.getTransport(); this.request(url); }, request: function(url) { this.url = url; this.method = this.options.method; var params = Object.clone(this.options.parameters); if (!['get', 'post'].include(this.method)) { // simulate other verbs over post params['_method'] = this.method; this.method = 'post'; } this.parameters = params; if (params = Object.toQueryString(params)) { // when GET, append parameters to URL if (this.method == 'get') this.url += (this.url.include('?') ? '&' : '?') + params; else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) params += '&_='; } try { var response = new Ajax.Response(this); if (this.options.onCreate) this.options.onCreate(response); Ajax.Responders.dispatch('onCreate', this, response); this.transport.open(this.method.toUpperCase(), this.url, this.options.asynchronous); if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1); this.transport.onreadystatechange = this.onStateChange.bind(this); this.setRequestHeaders(); this.body = this.method == 'post' ? (this.options.postBody || params) : null; this.transport.send(this.body); /* Force Firefox to handle ready state 4 for synchronous requests */ if (!this.options.asynchronous && this.transport.overrideMimeType) this.onStateChange(); } catch (e) { this.dispatchException(e); } }, onStateChange: function() { var readyState = this.transport.readyState; if (readyState > 1 && !((readyState == 4) && this._complete)) this.respondToReadyState(this.transport.readyState); }, setRequestHeaders: function() { var headers = { 'X-Requested-With': 'XMLHttpRequest', 'X-Prototype-Version': Prototype.Version, 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' }; if (this.method == 'post') { headers['Content-type'] = this.options.contentType + (this.options.encoding ? '; charset=' + this.options.encoding : ''); /* Force "Connection: close" for older Mozilla browsers to work * around a bug where XMLHttpRequest sends an incorrect * Content-length header. See Mozilla Bugzilla #246651. */ if (this.transport.overrideMimeType && (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) headers['Connection'] = 'close'; } // user-defined headers if (typeof this.options.requestHeaders == 'object') { var extras = this.options.requestHeaders; if (Object.isFunction(extras.push)) for (var i = 0, length = extras.length; i < length; i += 2) headers[extras[i]] = extras[i+1]; else $H(extras).each(function(pair) { headers[pair.key] = pair.value }); } for (var name in headers) this.transport.setRequestHeader(name, headers[name]); }, success: function() { var status = this.getStatus(); return !status || (status >= 200 && status < 300); }, getStatus: function() { try { return this.transport.status || 0; } catch (e) { return 0 } }, respondToReadyState: function(readyState) { var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this); if (state == 'Complete') { try { this._complete = true; (this.options['on' + response.status] || this.options['on' + (this.success() ? 'Success' : 'Failure')] || Prototype.emptyFunction)(response, response.headerJSON); } catch (e) { this.dispatchException(e); } var contentType = response.getHeader('Content-type'); if (this.options.evalJS == 'force' || (this.options.evalJS && this.isSameOrigin() && contentType && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))) this.evalResponse(); } try { (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON); Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON); } catch (e) { this.dispatchException(e); } if (state == 'Complete') { // avoid memory leak in MSIE: clean up this.transport.onreadystatechange = Prototype.emptyFunction; } }, isSameOrigin: function() { var m = this.url.match(/^\s*https?:\/\/[^\/]*/); return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({ protocol: location.protocol, domain: document.domain, port: location.port ? ':' + location.port : '' })); }, getHeader: function(name) { try { return this.transport.getResponseHeader(name) || null; } catch (e) { return null } }, evalResponse: function() { try { return eval((this.transport.responseText || '').unfilterJSON()); } catch (e) { this.dispatchException(e); } }, dispatchException: function(exception) { (this.options.onException || Prototype.emptyFunction)(this, exception); Ajax.Responders.dispatch('onException', this, exception); } }); Ajax.Request.Events = ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; Ajax.Response = Class.create({ initialize: function(request){ this.request = request; var transport = this.transport = request.transport, readyState = this.readyState = transport.readyState; if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) { this.status = this.getStatus(); this.statusText = this.getStatusText(); this.responseText = String.interpret(transport.responseText); this.headerJSON = this._getHeaderJSON(); } if(readyState == 4) { var xml = transport.responseXML; this.responseXML = Object.isUndefined(xml) ? null : xml; this.responseJSON = this._getResponseJSON(); } }, status: 0, statusText: '', getStatus: Ajax.Request.prototype.getStatus, getStatusText: function() { try { return this.transport.statusText || ''; } catch (e) { return '' } }, getHeader: Ajax.Request.prototype.getHeader, getAllHeaders: function() { try { return this.getAllResponseHeaders(); } catch (e) { return null } }, getResponseHeader: function(name) { return this.transport.getResponseHeader(name); }, getAllResponseHeaders: function() { return this.transport.getAllResponseHeaders(); }, _getHeaderJSON: function() { var json = this.getHeader('X-JSON'); if (!json) return null; json = decodeURIComponent(escape(json)); try { return json.evalJSON(this.request.options.sanitizeJSON || !this.request.isSameOrigin()); } catch (e) { this.request.dispatchException(e); } }, _getResponseJSON: function() { var options = this.request.options; if (!options.evalJSON || (options.evalJSON != 'force' && !(this.getHeader('Content-type') || '').include('application/json')) || this.responseText.blank()) return null; try { return this.responseText.evalJSON(options.sanitizeJSON || !this.request.isSameOrigin()); } catch (e) { this.request.dispatchException(e); } } }); Ajax.Updater = Class.create(Ajax.Request, { initialize: function($super, container, url, options) { this.container = { success: (container.success || container), failure: (container.failure || (container.success ? null : container)) }; options = Object.clone(options); var onComplete = options.onComplete; options.onComplete = (function(response, json) { this.updateContent(response.responseText); if (Object.isFunction(onComplete)) onComplete(response, json); }).bind(this); $super(url, options); }, updateContent: function(responseText) { var receiver = this.container[this.success() ? 'success' : 'failure'], options = this.options; if (!options.evalScripts) responseText = responseText.stripScripts(); if (receiver = $(receiver)) { if (options.insertion) { if (Object.isString(options.insertion)) { var insertion = { }; insertion[options.insertion] = responseText; receiver.insert(insertion); } else options.insertion(receiver, responseText); } else receiver.update(responseText); } } }); Ajax.PeriodicalUpdater = Class.create(Ajax.Base, { initialize: function($super, container, url, options) { $super(options); this.onComplete = this.options.onComplete; this.frequency = (this.options.frequency || 2); this.decay = (this.options.decay || 1); this.updater = { }; this.container = container; this.url = url; this.start(); }, start: function() { this.options.onComplete = this.updateComplete.bind(this); this.onTimerEvent(); }, stop: function() { this.updater.options.onComplete = undefined; clearTimeout(this.timer); (this.onComplete || Prototype.emptyFunction).apply(this, arguments); }, updateComplete: function(response) { if (this.options.decay) { this.decay = (response.responseText == this.lastText ? this.decay * this.options.decay : 1); this.lastText = response.responseText; } this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency); }, onTimerEvent: function() { this.updater = new Ajax.Updater(this.container, this.url, this.options); } }); function $(element) { if (arguments.length > 1) { for (var i = 0, elements = [], length = arguments.length; i < length; i++) elements.push($(arguments[i])); return elements; } if (Object.isString(element)) element = document.getElementById(element); return Element.extend(element); } if (Prototype.BrowserFeatures.XPath) { document._getElementsByXPath = function(expression, parentElement) { var results = []; var query = document.evaluate(expression, $(parentElement) || document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); for (var i = 0, length = query.snapshotLength; i < length; i++) results.push(Element.extend(query.snapshotItem(i))); return results; }; } /*--------------------------------------------------------------------------*/ if (!window.Node) var Node = { }; if (!Node.ELEMENT_NODE) { // DOM level 2 ECMAScript Language Binding Object.extend(Node, { ELEMENT_NODE: 1, ATTRIBUTE_NODE: 2, TEXT_NODE: 3, CDATA_SECTION_NODE: 4, ENTITY_REFERENCE_NODE: 5, ENTITY_NODE: 6, PROCESSING_INSTRUCTION_NODE: 7, COMMENT_NODE: 8, DOCUMENT_NODE: 9, DOCUMENT_TYPE_NODE: 10, DOCUMENT_FRAGMENT_NODE: 11, NOTATION_NODE: 12 }); } (function() { var element = this.Element; this.Element = function(tagName, attributes) { attributes = attributes || { }; tagName = tagName.toLowerCase(); var cache = Element.cache; if (Prototype.Browser.IE && attributes.name) { tagName = '<' + tagName + ' name="' + attributes.name + '">'; delete attributes.name; return Element.writeAttribute(document.createElement(tagName), attributes); } if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName)); return Element.writeAttribute(cache[tagName].cloneNode(false), attributes); }; Object.extend(this.Element, element || { }); }).call(window); Element.cache = { }; Element.Methods = { visible: function(element) { return $(element).style.display != 'none'; }, toggle: function(element) { element = $(element); Element[Element.visible(element) ? 'hide' : 'show'](element); return element; }, hide: function(element) { $(element).style.display = 'none'; return element; }, show: function(element) { $(element).style.display = ''; return element; }, remove: function(element) { element = $(element); element.parentNode.removeChild(element); return element; }, update: function(element, content) { element = $(element); if (content && content.toElement) content = content.toElement(); if (Object.isElement(content)) return element.update().insert(content); content = Object.toHTML(content); element.innerHTML = content.stripScripts(); content.evalScripts.bind(content).defer(); return element; }, replace: function(element, content) { element = $(element); if (content && content.toElement) content = content.toElement(); else if (!Object.isElement(content)) { content = Object.toHTML(content); var range = element.ownerDocument.createRange(); range.selectNode(element); content.evalScripts.bind(content).defer(); content = range.createContextualFragment(content.stripScripts()); } element.parentNode.replaceChild(content, element); return element; }, insert: function(element, insertions) { element = $(element); if (Object.isString(insertions) || Object.isNumber(insertions) || Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) insertions = {bottom:insertions}; var content, insert, tagName, childNodes; for (var position in insertions) { content = insertions[position]; position = position.toLowerCase(); insert = Element._insertionTranslations[position]; if (content && content.toElement) content = content.toElement(); if (Object.isElement(content)) { insert(element, content); continue; } content = Object.toHTML(content); tagName = ((position == 'before' || position == 'after') ? element.parentNode : element).tagName.toUpperCase(); childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); if (position == 'top' || position == 'after') childNodes.reverse(); childNodes.each(insert.curry(element)); content.evalScripts.bind(content).defer(); } return element; }, wrap: function(element, wrapper, attributes) { element = $(element); if (Object.isElement(wrapper)) $(wrapper).writeAttribute(attributes || { }); else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes); else wrapper = new Element('div', wrapper); if (element.parentNode) element.parentNode.replaceChild(wrapper, element); wrapper.appendChild(element); return wrapper; }, inspect: function(element) { element = $(element); var result = '<' + element.tagName.toLowerCase(); $H({'id': 'id', 'className': 'class'}).each(function(pair) { var property = pair.first(), attribute = pair.last(); var value = (element[property] || '').toString(); if (value) result += ' ' + attribute + '=' + value.inspect(true); }); return result + '>'; }, recursivelyCollect: function(element, property) { element = $(element); var elements = []; while (element = element[property]) if (element.nodeType == 1) elements.push(Element.extend(element)); return elements; }, ancestors: function(element) { return $(element).recursivelyCollect('parentNode'); }, descendants: function(element) { return $(element).select("*"); }, firstDescendant: function(element) { element = $(element).firstChild; while (element && element.nodeType != 1) element = element.nextSibling; return $(element); }, immediateDescendants: function(element) { if (!(element = $(element).firstChild)) return []; while (element && element.nodeType != 1) element = element.nextSibling; if (element) return [element].concat($(element).nextSiblings()); return []; }, previousSiblings: function(element) { return $(element).recursivelyCollect('previousSibling'); }, nextSiblings: function(element) { return $(element).recursivelyCollect('nextSibling'); }, siblings: function(element) { element = $(element); return element.previousSiblings().reverse().concat(element.nextSiblings()); }, match: function(element, selector) { if (Object.isString(selector)) selector = new Selector(selector); return selector.match($(element)); }, up: function(element, expression, index) { element = $(element); if (arguments.length == 1) return $(element.parentNode); var ancestors = element.ancestors(); return Object.isNumber(expression) ? ancestors[expression] : Selector.findElement(ancestors, expression, index); }, down: function(element, expression, index) { element = $(element); if (arguments.length == 1) return element.firstDescendant(); return Object.isNumber(expression) ? element.descendants()[expression] : element.select(expression)[index || 0]; }, previous: function(element, expression, index) { element = $(element); if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); var previousSiblings = element.previousSiblings(); return Object.isNumber(expression) ? previousSiblings[expression] : Selector.findElement(previousSiblings, expression, index); }, next: function(element, expression, index) { element = $(element); if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); var nextSiblings = element.nextSiblings(); return Object.isNumber(expression) ? nextSiblings[expression] : Selector.findElement(nextSiblings, expression, index); }, select: function() { var args = $A(arguments), element = $(args.shift()); return Selector.findChildElements(element, args); }, adjacent: function() { var args = $A(arguments), element = $(args.shift()); return Selector.findChildElements(element.parentNode, args).without(element); }, identify: function(element) { element = $(element); var id = element.readAttribute('id'), self = arguments.callee; if (id) return id; do { id = 'anonymous_element_' + self.counter++ } while ($(id)); element.writeAttribute('id', id); return id; }, readAttribute: function(element, name) { element = $(element); if (Prototype.Browser.IE) { var t = Element._attributeTranslations.read; if (t.values[name]) return t.values[name](element, name); if (t.names[name]) name = t.names[name]; if (name.include(':')) { return (!element.attributes || !element.attributes[name]) ? null : element.attributes[name].value; } } return element.getAttribute(name); }, writeAttribute: function(element, name, value) { element = $(element); var attributes = { }, t = Element._attributeTranslations.write; if (typeof name == 'object') attributes = name; else attributes[name] = Object.isUndefined(value) ? true : value; for (var attr in attributes) { name = t.names[attr] || attr; value = attributes[attr]; if (t.values[attr]) name = t.values[attr](element, value); if (value === false || value === null) element.removeAttribute(name); else if (value === true) element.setAttribute(name, name); else element.setAttribute(name, value); } return element; }, getHeight: function(element) { return $(element).getDimensions().height; }, getWidth: function(element) { return $(element).getDimensions().width; }, classNames: function(element) { return new Element.ClassNames(element); }, hasClassName: function(element, className) { if (!(element = $(element))) return; var elementClassName = element.className; return (elementClassName.length > 0 && (elementClassName == className || new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName))); }, addClassName: function(element, className) { if (!(element = $(element))) return; if (!element.hasClassName(className)) element.className += (element.className ? ' ' : '') + className; return element; }, removeClassName: function(element, className) { if (!(element = $(element))) return; element.className = element.className.replace( new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip(); return element; }, toggleClassName: function(element, className) { if (!(element = $(element))) return; return element[element.hasClassName(className) ? 'removeClassName' : 'addClassName'](className); }, // removes whitespace-only text node children cleanWhitespace: function(element) { element = $(element); var node = element.firstChild; while (node) { var nextNode = node.nextSibling; if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) element.removeChild(node); node = nextNode; } return element; }, empty: function(element) { return $(element).innerHTML.blank(); }, descendantOf: function(element, ancestor) { element = $(element), ancestor = $(ancestor); var originalAncestor = ancestor; if (element.compareDocumentPosition) return (element.compareDocumentPosition(ancestor) & 8) === 8; if (element.sourceIndex && !Prototype.Browser.Opera) { var e = element.sourceIndex, a = ancestor.sourceIndex, nextAncestor = ancestor.nextSibling; if (!nextAncestor) { do { ancestor = ancestor.parentNode; } while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode); } if (nextAncestor && nextAncestor.sourceIndex) return (e > a && e < nextAncestor.sourceIndex); } while (element = element.parentNode) if (element == originalAncestor) return true; return false; }, scrollTo: function(element) { element = $(element); var pos = element.cumulativeOffset(); window.scrollTo(pos[0], pos[1]); return element; }, getStyle: function(element, style) { element = $(element); style = style == 'float' ? 'cssFloat' : style.camelize(); var value = element.style[style]; if (!value) { var css = document.defaultView.getComputedStyle(element, null); value = css ? css[style] : null; } if (style == 'opacity') return value ? parseFloat(value) : 1.0; return value == 'auto' ? null : value; }, getOpacity: function(element) { return $(element).getStyle('opacity'); }, setStyle: function(element, styles) { element = $(element); var elementStyle = element.style, match; if (Object.isString(styles)) { element.style.cssText += ';' + styles; return styles.include('opacity') ? element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element; } for (var property in styles) if (property == 'opacity') element.setOpacity(styles[property]); else elementStyle[(property == 'float' || property == 'cssFloat') ? (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') : property] = styles[property]; return element; }, setOpacity: function(element, value) { element = $(element); element.style.opacity = (value == 1 || value === '') ? '' : (value < 0.00001) ? 0 : value; return element; }, getDimensions: function(element) { element = $(element); var display = $(element).getStyle('display'); if (display != 'none' && display != null) // Safari bug return {width: element.offsetWidth, height: element.offsetHeight}; // All *Width and *Height properties give 0 on elements with display none, // so enable the element temporarily var els = element.style; var originalVisibility = els.visibility; var originalPosition = els.position; var originalDisplay = els.display; els.visibility = 'hidden'; els.position = 'absolute'; els.display = 'block'; var originalWidth = element.clientWidth; var originalHeight = element.clientHeight; els.display = originalDisplay; els.position = originalPosition; els.visibility = originalVisibility; return {width: originalWidth, height: originalHeight}; }, makePositioned: function(element) { element = $(element); var pos = Element.getStyle(element, 'position'); if (pos == 'static' || !pos) { element._madePositioned = true; element.style.position = 'relative'; // Opera returns the offset relative to the positioning context, when an // element is position relative but top and left have not been defined if (window.opera) { element.style.top = 0; element.style.left = 0; } } return element; }, undoPositioned: function(element) { element = $(element); if (element._madePositioned) { element._madePositioned = undefined; element.style.position = element.style.top = element.style.left = element.style.bottom = element.style.right = ''; } return element; }, makeClipping: function(element) { element = $(element); if (element._overflow) return element; element._overflow = Element.getStyle(element, 'overflow') || 'auto'; if (element._overflow !== 'hidden') element.style.overflow = 'hidden'; return element; }, undoClipping: function(element) { element = $(element); if (!element._overflow) return element; element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; element._overflow = null; return element; }, cumulativeOffset: function(element) { var valueT = 0, valueL = 0; do { valueT += element.offsetTop || 0; valueL += element.offsetLeft || 0; element = element.offsetParent; } while (element); return Element._returnOffset(valueL, valueT); }, positionedOffset: function(element) { var valueT = 0, valueL = 0; do { valueT += element.offsetTop || 0; valueL += element.offsetLeft || 0; element = element.offsetParent; if (element) { if (element.tagName == 'BODY') break; var p = Element.getStyle(element, 'position'); if (p !== 'static') break; } } while (element); return Element._returnOffset(valueL, valueT); }, absolutize: function(element) { element = $(element); if (element.getStyle('position') == 'absolute') return; // Position.prepare(); // To be done manually by Scripty when it needs it. var offsets = element.positionedOffset(); var top = offsets[1]; var left = offsets[0]; var width = element.clientWidth; var height = element.clientHeight; element._originalLeft = left - parseFloat(element.style.left || 0); element._originalTop = top - parseFloat(element.style.top || 0); element._originalWidth = element.style.width; element._originalHeight = element.style.height; element.style.position = 'absolute'; element.style.top = top + 'px'; element.style.left = left + 'px'; element.style.width = width + 'px'; element.style.height = height + 'px'; return element; }, relativize: function(element) { element = $(element); if (element.getStyle('position') == 'relative') return; // Position.prepare(); // To be done manually by Scripty when it needs it. element.style.position = 'relative'; var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); element.style.top = top + 'px'; element.style.left = left + 'px'; element.style.height = element._originalHeight; element.style.width = element._originalWidth; return element; }, cumulativeScrollOffset: function(element) { var valueT = 0, valueL = 0; do { valueT += element.scrollTop || 0; valueL += element.scrollLeft || 0; element = element.parentNode; } while (element); return Element._returnOffset(valueL, valueT); }, getOffsetParent: function(element) { if (element.offsetParent) return $(element.offsetParent); if (element == document.body) return $(element); while ((element = element.parentNode) && element != document.body) if (Element.getStyle(element, 'position') != 'static') return $(element); return $(document.body); }, viewportOffset: function(forElement) { var valueT = 0, valueL = 0; var element = forElement; do { valueT += element.offsetTop || 0; valueL += element.offsetLeft || 0; // Safari fix if (element.offsetParent == document.body && Element.getStyle(element, 'position') == 'absolute') break; } while (element = element.offsetParent); element = forElement; do { if (!Prototype.Browser.Opera || element.tagName == 'BODY') { valueT -= element.scrollTop || 0; valueL -= element.scrollLeft || 0; } } while (element = element.parentNode); return Element._returnOffset(valueL, valueT); }, clonePosition: function(element, source) { var options = Object.extend({ setLeft: true, setTop: true, setWidth: true, setHeight: true, offsetTop: 0, offsetLeft: 0 }, arguments[2] || { }); // find page position of source source = $(source); var p = source.viewportOffset(); // find coordinate system to use element = $(element); var delta = [0, 0]; var parent = null; // delta [0,0] will do fine with position: fixed elements, // position:absolute needs offsetParent deltas if (Element.getStyle(element, 'position') == 'absolute') { parent = element.getOffsetParent(); delta = parent.viewportOffset(); } // correct by body offsets (fixes Safari) if (parent == document.body) { delta[0] -= document.body.offsetLeft; delta[1] -= document.body.offsetTop; } // set position if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; if (options.setWidth) element.style.width = source.offsetWidth + 'px'; if (options.setHeight) element.style.height = source.offsetHeight + 'px'; return element; } }; Element.Methods.identify.counter = 1; Object.extend(Element.Methods, { getElementsBySelector: Element.Methods.select, childElements: Element.Methods.immediateDescendants }); Element._attributeTranslations = { write: { names: { className: 'class', htmlFor: 'for' }, values: { } } }; if (Prototype.Browser.Opera) { Element.Methods.getStyle = Element.Methods.getStyle.wrap( function(proceed, element, style) { switch (style) { case 'left': case 'top': case 'right': case 'bottom': if (proceed(element, 'position') === 'static') return null; case 'height': case 'width': // returns '0px' for hidden elements; we want it to return null if (!Element.visible(element)) return null; // returns the border-box dimensions rather than the content-box // dimensions, so we subtract padding and borders from the value var dim = parseInt(proceed(element, style), 10); if (dim !== element['offset' + style.capitalize()]) return dim + 'px'; var properties; if (style === 'height') { properties = ['border-top-width', 'padding-top', 'padding-bottom', 'border-bottom-width']; } else { properties = ['border-left-width', 'padding-left', 'padding-right', 'border-right-width']; } return properties.inject(dim, function(memo, property) { var val = proceed(element, property); return val === null ? memo : memo - parseInt(val, 10); }) + 'px'; default: return proceed(element, style); } } ); Element.Methods.readAttribute = Element.Methods.readAttribute.wrap( function(proceed, element, attribute) { if (attribute === 'title') return element.title; return proceed(element, attribute); } ); } else if (Prototype.Browser.IE) { // IE doesn't report offsets correctly for static elements, so we change them // to "relative" to get the values, then change them back. Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap( function(proceed, element) { element = $(element); var position = element.getStyle('position'); if (position !== 'static') return proceed(element); element.setStyle({ position: 'relative' }); var value = proceed(element); element.setStyle({ position: position }); return value; } ); $w('positionedOffset viewportOffset').each(function(method) { Element.Methods[method] = Element.Methods[method].wrap( function(proceed, element) { element = $(element); var position = element.getStyle('position'); if (position !== 'static') return proceed(element); // Trigger hasLayout on the offset parent so that IE6 reports // accurate offsetTop and offsetLeft values for position: fixed. var offsetParent = element.getOffsetParent(); if (offsetParent && offsetParent.getStyle('position') === 'fixed') offsetParent.setStyle({ zoom: 1 }); element.setStyle({ position: 'relative' }); var value = proceed(element); element.setStyle({ position: position }); return value; } ); }); Element.Methods.getStyle = function(element, style) { element = $(element); style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize(); var value = element.style[style]; if (!value && element.currentStyle) value = element.currentStyle[style]; if (style == 'opacity') { if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) if (value[1]) return parseFloat(value[1]) / 100; return 1.0; } if (value == 'auto') { if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none')) return element['offset' + style.capitalize()] + 'px'; return null; } return value; }; Element.Methods.setOpacity = function(element, value) { function stripAlpha(filter){ return filter.replace(/alpha\([^\)]*\)/gi,''); } element = $(element); var currentStyle = element.currentStyle; if ((currentStyle && !currentStyle.hasLayout) || (!currentStyle && element.style.zoom == 'normal')) element.style.zoom = 1; var filter = element.getStyle('filter'), style = element.style; if (value == 1 || value === '') { (filter = stripAlpha(filter)) ? style.filter = filter : style.removeAttribute('filter'); return element; } else if (value < 0.00001) value = 0; style.filter = stripAlpha(filter) + 'alpha(opacity=' + (value * 100) + ')'; return element; }; Element._attributeTranslations = { read: { names: { 'class': 'className', 'for': 'htmlFor' }, values: { _getAttr: function(element, attribute) { return element.getAttribute(attribute, 2); }, _getAttrNode: function(element, attribute) { var node = element.getAttributeNode(attribute); return node ? node.value : ""; }, _getEv: function(element, attribute) { attribute = element.getAttribute(attribute); return attribute ? attribute.toString().slice(23, -2) : null; }, _flag: function(element, attribute) { return $(element).hasAttribute(attribute) ? attribute : null; }, style: function(element) { return element.style.cssText.toLowerCase(); }, title: function(element) { return element.title; } } } }; Element._attributeTranslations.write = { names: Object.extend({ cellpadding: 'cellPadding', cellspacing: 'cellSpacing' }, Element._attributeTranslations.read.names), values: { checked: function(element, value) { element.checked = !!value; }, style: function(element, value) { element.style.cssText = value ? value : ''; } } }; Element._attributeTranslations.has = {}; $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' + 'encType maxLength readOnly longDesc').each(function(attr) { Element._attributeTranslations.write.names[attr.toLowerCase()] = attr; Element._attributeTranslations.has[attr.toLowerCase()] = attr; }); (function(v) { Object.extend(v, { href: v._getAttr, src: v._getAttr, type: v._getAttr, action: v._getAttrNode, disabled: v._flag, checked: v._flag, readonly: v._flag, multiple: v._flag, onload: v._getEv, onunload: v._getEv, onclick: v._getEv, ondblclick: v._getEv, onmousedown: v._getEv, onmouseup: v._getEv, onmouseover: v._getEv, onmousemove: v._getEv, onmouseout: v._getEv, onfocus: v._getEv, onblur: v._getEv, onkeypress: v._getEv, onkeydown: v._getEv, onkeyup: v._getEv, onsubmit: v._getEv, onreset: v._getEv, onselect: v._getEv, onchange: v._getEv }); })(Element._attributeTranslations.read.values); } else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) { Element.Methods.setOpacity = function(element, value) { element = $(element); element.style.opacity = (value == 1) ? 0.999999 : (value === '') ? '' : (value < 0.00001) ? 0 : value; return element; }; } else if (Prototype.Browser.WebKit) { Element.Methods.setOpacity = function(element, value) { element = $(element); element.style.opacity = (value == 1 || value === '') ? '' : (value < 0.00001) ? 0 : value; if (value == 1) if(element.tagName == 'IMG' && element.width) { element.width++; element.width--; } else try { var n = document.createTextNode(' '); element.appendChild(n); element.removeChild(n); } catch (e) { } return element; }; // Safari returns margins on body which is incorrect if the child is absolutely // positioned. For performance reasons, redefine Element#cumulativeOffset for // KHTML/WebKit only. Element.Methods.cumulativeOffset = function(element) { var valueT = 0, valueL = 0; do { valueT += element.offsetTop || 0; valueL += element.offsetLeft || 0; if (element.offsetParent == document.body) if (Element.getStyle(element, 'position') == 'absolute') break; element = element.offsetParent; } while (element); return Element._returnOffset(valueL, valueT); }; } if (Prototype.Browser.IE || Prototype.Browser.Opera) { // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements Element.Methods.update = function(element, content) { element = $(element); if (content && content.toElement) content = content.toElement(); if (Object.isElement(content)) return element.update().insert(content); content = Object.toHTML(content); var tagName = element.tagName.toUpperCase(); if (tagName in Element._insertionTranslations.tags) { $A(element.childNodes).each(function(node) { element.removeChild(node) }); Element._getContentFromAnonymousElement(tagName, content.stripScripts()) .each(function(node) { element.appendChild(node) }); } else element.innerHTML = content.stripScripts(); content.evalScripts.bind(content).defer(); return element; }; } if ('outerHTML' in document.createElement('div')) { Element.Methods.replace = function(element, content) { element = $(element); if (content && content.toElement) content = content.toElement(); if (Object.isElement(content)) { element.parentNode.replaceChild(content, element); return element; } content = Object.toHTML(content); var parent = element.parentNode, tagName = parent.tagName.toUpperCase(); if (Element._insertionTranslations.tags[tagName]) { var nextSibling = element.next(); var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); parent.removeChild(element); if (nextSibling) fragments.each(function(node) { parent.insertBefore(node, nextSibling) }); else fragments.each(function(node) { parent.appendChild(node) }); } else element.outerHTML = content.stripScripts(); content.evalScripts.bind(content).defer(); return element; }; } Element._returnOffset = function(l, t) { var result = [l, t]; result.left = l; result.top = t; return result; }; Element._getContentFromAnonymousElement = function(tagName, html) { var div = new Element('div'), t = Element._insertionTranslations.tags[tagName]; if (t) { div.innerHTML = t[0] + html + t[1]; t[2].times(function() { div = div.firstChild }); } else div.innerHTML = html; return $A(div.childNodes); }; Element._insertionTranslations = { before: function(element, node) { element.parentNode.insertBefore(node, element); }, top: function(element, node) { element.insertBefore(node, element.firstChild); }, bottom: function(element, node) { element.appendChild(node); }, after: function(element, node) { element.parentNode.insertBefore(node, element.nextSibling); }, tags: { TABLE: ['', '
', 1], TBODY: ['', '
', 2], TR: ['', '
', 3], TD: ['
', '
', 4], SELECT: ['', 1] } }; (function() { Object.extend(this.tags, { THEAD: this.tags.TBODY, TFOOT: this.tags.TBODY, TH: this.tags.TD }); }).call(Element._insertionTranslations); Element.Methods.Simulated = { hasAttribute: function(element, attribute) { attribute = Element._attributeTranslations.has[attribute] || attribute; var node = $(element).getAttributeNode(attribute); return node && node.specified; } }; Element.Methods.ByTag = { }; Object.extend(Element, Element.Methods); if (!Prototype.BrowserFeatures.ElementExtensions && document.createElement('div').__proto__) { window.HTMLElement = { }; window.HTMLElement.prototype = document.createElement('div').__proto__; Prototype.BrowserFeatures.ElementExtensions = true; } Element.extend = (function() { if (Prototype.BrowserFeatures.SpecificElementExtensions) return Prototype.K; var Methods = { }, ByTag = Element.Methods.ByTag; var extend = Object.extend(function(element) { if (!element || element._extendedByPrototype || element.nodeType != 1 || element == window) return element; var methods = Object.clone(Methods), tagName = element.tagName, property, value; // extend methods for specific tags if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); for (property in methods) { value = methods[property]; if (Object.isFunction(value) && !(property in element)) element[property] = value.methodize(); } element._extendedByPrototype = Prototype.emptyFunction; return element; }, { refresh: function() { // extend methods for all tags (Safari doesn't need this) if (!Prototype.BrowserFeatures.ElementExtensions) { Object.extend(Methods, Element.Methods); Object.extend(Methods, Element.Methods.Simulated); } } }); extend.refresh(); return extend; })(); Element.hasAttribute = function(element, attribute) { if (element.hasAttribute) return element.hasAttribute(attribute); return Element.Methods.Simulated.hasAttribute(element, attribute); }; Element.addMethods = function(methods) { var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag; if (!methods) { Object.extend(Form, Form.Methods); Object.extend(Form.Element, Form.Element.Methods); Object.extend(Element.Methods.ByTag, { "FORM": Object.clone(Form.Methods), "INPUT": Object.clone(Form.Element.Methods), "SELECT": Object.clone(Form.Element.Methods), "TEXTAREA": Object.clone(Form.Element.Methods) }); } if (arguments.length == 2) { var tagName = methods; methods = arguments[1]; } if (!tagName) Object.extend(Element.Methods, methods || { }); else { if (Object.isArray(tagName)) tagName.each(extend); else extend(tagName); } function extend(tagName) { tagName = tagName.toUpperCase(); if (!Element.Methods.ByTag[tagName]) Element.Methods.ByTag[tagName] = { }; Object.extend(Element.Methods.ByTag[tagName], methods); } function copy(methods, destination, onlyIfAbsent) { onlyIfAbsent = onlyIfAbsent || false; for (var property in methods) { var value = methods[property]; if (!Object.isFunction(value)) continue; if (!onlyIfAbsent || !(property in destination)) destination[property] = value.methodize(); } } function findDOMClass(tagName) { var klass; var trans = { "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph", "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList", "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading", "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote", "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION": "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD": "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR": "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET": "FrameSet", "IFRAME": "IFrame" }; if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element'; if (window[klass]) return window[klass]; klass = 'HTML' + tagName + 'Element'; if (window[klass]) return window[klass]; klass = 'HTML' + tagName.capitalize() + 'Element'; if (window[klass]) return window[klass]; window[klass] = { }; window[klass].prototype = document.createElement(tagName).__proto__; return window[klass]; } if (F.ElementExtensions) { copy(Element.Methods, HTMLElement.prototype); copy(Element.Methods.Simulated, HTMLElement.prototype, true); } if (F.SpecificElementExtensions) { for (var tag in Element.Methods.ByTag) { var klass = findDOMClass(tag); if (Object.isUndefined(klass)) continue; copy(T[tag], klass.prototype); } } Object.extend(Element, Element.Methods); delete Element.ByTag; if (Element.extend.refresh) Element.extend.refresh(); Element.cache = { }; }; document.viewport = { getDimensions: function() { var dimensions = { }; var B = Prototype.Browser; $w('width height').each(function(d) { var D = d.capitalize(); dimensions[d] = (B.WebKit && !document.evaluate) ? self['inner' + D] : (B.Opera) ? document.body['client' + D] : document.documentElement['client' + D]; }); return dimensions; }, getWidth: function() { return this.getDimensions().width; }, getHeight: function() { return this.getDimensions().height; }, getScrollOffsets: function() { return Element._returnOffset( window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); } }; /* Portions of the Selector class are derived from Jack Slocum’s DomQuery, * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style * license. Please see http://www.yui-ext.com/ for more information. */ var Selector = Class.create({ initialize: function(expression) { this.expression = expression.strip(); this.compileMatcher(); }, shouldUseXPath: function() { if (!Prototype.BrowserFeatures.XPath) return false; var e = this.expression; // Safari 3 chokes on :*-of-type and :empty if (Prototype.Browser.WebKit && (e.include("-of-type") || e.include(":empty"))) return false; // XPath can't do namespaced attributes, nor can it read // the "checked" property from DOM nodes if ((/(\[[\w-]*?:|:checked)/).test(this.expression)) return false; return true; }, compileMatcher: function() { if (this.shouldUseXPath()) return this.compileXPathMatcher(); var e = this.expression, ps = Selector.patterns, h = Selector.handlers, c = Selector.criteria, le, p, m; if (Selector._cache[e]) { this.matcher = Selector._cache[e]; return; } this.matcher = ["this.matcher = function(root) {", "var r = root, h = Selector.handlers, c = false, n;"]; while (e && le != e && (/\S/).test(e)) { le = e; for (var i in ps) { p = ps[i]; if (m = e.match(p)) { this.matcher.push(Object.isFunction(c[i]) ? c[i](m) : new Template(c[i]).evaluate(m)); e = e.replace(m[0], ''); break; } } } this.matcher.push("return h.unique(n);\n}"); eval(this.matcher.join('\n')); Selector._cache[this.expression] = this.matcher; }, compileXPathMatcher: function() { var e = this.expression, ps = Selector.patterns, x = Selector.xpath, le, m; if (Selector._cache[e]) { this.xpath = Selector._cache[e]; return; } this.matcher = ['.//*']; while (e && le != e && (/\S/).test(e)) { le = e; for (var i in ps) { if (m = e.match(ps[i])) { this.matcher.push(Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m)); e = e.replace(m[0], ''); break; } } } this.xpath = this.matcher.join(''); Selector._cache[this.expression] = this.xpath; }, findElements: function(root) { root = root || document; if (this.xpath) return document._getElementsByXPath(this.xpath, root); return this.matcher(root); }, match: function(element) { this.tokens = []; var e = this.expression, ps = Selector.patterns, as = Selector.assertions; var le, p, m; while (e && le !== e && (/\S/).test(e)) { le = e; for (var i in ps) { p = ps[i]; if (m = e.match(p)) { // use the Selector.assertions methods unless the selector // is too complex. if (as[i]) { this.tokens.push([i, Object.clone(m)]); e = e.replace(m[0], ''); } else { // reluctantly do a document-wide search // and look for a match in the array return this.findElements(document).include(element); } } } } var match = true, name, matches; for (var i = 0, token; token = this.tokens[i]; i++) { name = token[0], matches = token[1]; if (!Selector.assertions[name](element, matches)) { match = false; break; } } return match; }, toString: function() { return this.expression; }, inspect: function() { return "#"; } }); Object.extend(Selector, { _cache: { }, xpath: { descendant: "//*", child: "/*", adjacent: "/following-sibling::*[1]", laterSibling: '/following-sibling::*', tagName: function(m) { if (m[1] == '*') return ''; return "[local-name()='" + m[1].toLowerCase() + "' or local-name()='" + m[1].toUpperCase() + "']"; }, className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", id: "[@id='#{1}']", attrPresence: function(m) { m[1] = m[1].toLowerCase(); return new Template("[@#{1}]").evaluate(m); }, attr: function(m) { m[1] = m[1].toLowerCase(); m[3] = m[5] || m[6]; return new Template(Selector.xpath.operators[m[2]]).evaluate(m); }, pseudo: function(m) { var h = Selector.xpath.pseudos[m[1]]; if (!h) return ''; if (Object.isFunction(h)) return h(m); return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); }, operators: { '=': "[@#{1}='#{3}']", '!=': "[@#{1}!='#{3}']", '^=': "[starts-with(@#{1}, '#{3}')]", '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", '*=': "[contains(@#{1}, '#{3}')]", '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" }, pseudos: { 'first-child': '[not(preceding-sibling::*)]', 'last-child': '[not(following-sibling::*)]', 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]", 'checked': "[@checked]", 'disabled': "[@disabled]", 'enabled': "[not(@disabled)]", 'not': function(m) { var e = m[6], p = Selector.patterns, x = Selector.xpath, le, v; var exclusion = []; while (e && le != e && (/\S/).test(e)) { le = e; for (var i in p) { if (m = e.match(p[i])) { v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m); exclusion.push("(" + v.substring(1, v.length - 1) + ")"); e = e.replace(m[0], ''); break; } } } return "[not(" + exclusion.join(" and ") + ")]"; }, 'nth-child': function(m) { return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m); }, 'nth-last-child': function(m) { return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m); }, 'nth-of-type': function(m) { return Selector.xpath.pseudos.nth("position() ", m); }, 'nth-last-of-type': function(m) { return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m); }, 'first-of-type': function(m) { m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m); }, 'last-of-type': function(m) { m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m); }, 'only-of-type': function(m) { var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m); }, nth: function(fragment, m) { var mm, formula = m[6], predicate; if (formula == 'even') formula = '2n+0'; if (formula == 'odd') formula = '2n+1'; if (mm = formula.match(/^(\d+)$/)) // digit only return '[' + fragment + "= " + mm[1] + ']'; if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b if (mm[1] == "-") mm[1] = -1; var a = mm[1] ? Number(mm[1]) : 1; var b = mm[2] ? Number(mm[2]) : 0; predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " + "((#{fragment} - #{b}) div #{a} >= 0)]"; return new Template(predicate).evaluate({ fragment: fragment, a: a, b: b }); } } } }, criteria: { tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', className: 'n = h.className(n, r, "#{1}", c); c = false;', id: 'n = h.id(n, r, "#{1}", c); c = false;', attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;', attr: function(m) { m[3] = (m[5] || m[6]); return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m); }, pseudo: function(m) { if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); }, descendant: 'c = "descendant";', child: 'c = "child";', adjacent: 'c = "adjacent";', laterSibling: 'c = "laterSibling";' }, patterns: { // combinators must be listed first // (and descendant needs to be last combinator) laterSibling: /^\s*~\s*/, child: /^\s*>\s*/, adjacent: /^\s*\+\s*/, descendant: /^\s/, // selectors follow tagName: /^\s*(\*|[\w\-]+)(\b|$)?/, id: /^#([\w\-\*]+)(\b|$)/, className: /^\.([\w\-\*]+)(\b|$)/, pseudo: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/, attrPresence: /^\[([\w]+)\]/, attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ }, // for Selector.match and Element#match assertions: { tagName: function(element, matches) { return matches[1].toUpperCase() == element.tagName.toUpperCase(); }, className: function(element, matches) { return Element.hasClassName(element, matches[1]); }, id: function(element, matches) { return element.id === matches[1]; }, attrPresence: function(element, matches) { return Element.hasAttribute(element, matches[1]); }, attr: function(element, matches) { var nodeValue = Element.readAttribute(element, matches[1]); return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]); } }, handlers: { // UTILITY FUNCTIONS // joins two collections concat: function(a, b) { for (var i = 0, node; node = b[i]; i++) a.push(node); return a; }, // marks an array of nodes for counting mark: function(nodes) { var _true = Prototype.emptyFunction; for (var i = 0, node; node = nodes[i]; i++) node._countedByPrototype = _true; return nodes; }, unmark: function(nodes) { for (var i = 0, node; node = nodes[i]; i++) node._countedByPrototype = undefined; return nodes; }, // mark each child node with its position (for nth calls) // "ofType" flag indicates whether we're indexing for nth-of-type // rather than nth-child index: function(parentNode, reverse, ofType) { parentNode._countedByPrototype = Prototype.emptyFunction; if (reverse) { for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { var node = nodes[i]; if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; } } else { for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; } }, // filters out duplicates and extends all nodes unique: function(nodes) { if (nodes.length == 0) return nodes; var results = [], n; for (var i = 0, l = nodes.length; i < l; i++) if (!(n = nodes[i])._countedByPrototype) { n._countedByPrototype = Prototype.emptyFunction; results.push(Element.extend(n)); } return Selector.handlers.unmark(results); }, // COMBINATOR FUNCTIONS descendant: function(nodes) { var h = Selector.handlers; for (var i = 0, results = [], node; node = nodes[i]; i++) h.concat(results, node.getElementsByTagName('*')); return results; }, child: function(nodes) { var h = Selector.handlers; for (var i = 0, results = [], node; node = nodes[i]; i++) { for (var j = 0, child; child = node.childNodes[j]; j++) if (child.nodeType == 1 && child.tagName != '!') results.push(child); } return results; }, adjacent: function(nodes) { for (var i = 0, results = [], node; node = nodes[i]; i++) { var next = this.nextElementSibling(node); if (next) results.push(next); } return results; }, laterSibling: function(nodes) { var h = Selector.handlers; for (var i = 0, results = [], node; node = nodes[i]; i++) h.concat(results, Element.nextSiblings(node)); return results; }, nextElementSibling: function(node) { while (node = node.nextSibling) if (node.nodeType == 1) return node; return null; }, previousElementSibling: function(node) { while (node = node.previousSibling) if (node.nodeType == 1) return node; return null; }, // TOKEN FUNCTIONS tagName: function(nodes, root, tagName, combinator) { var uTagName = tagName.toUpperCase(); var results = [], h = Selector.handlers; if (nodes) { if (combinator) { // fastlane for ordinary descendant combinators if (combinator == "descendant") { for (var i = 0, node; node = nodes[i]; i++) h.concat(results, node.getElementsByTagName(tagName)); return results; } else nodes = this[combinator](nodes); if (tagName == "*") return nodes; } for (var i = 0, node; node = nodes[i]; i++) if (node.tagName.toUpperCase() === uTagName) results.push(node); return results; } else return root.getElementsByTagName(tagName); }, id: function(nodes, root, id, combinator) { var targetNode = $(id), h = Selector.handlers; if (!targetNode) return []; if (!nodes && root == document) return [targetNode]; if (nodes) { if (combinator) { if (combinator == 'child') { for (var i = 0, node; node = nodes[i]; i++) if (targetNode.parentNode == node) return [targetNode]; } else if (combinator == 'descendant') { for (var i = 0, node; node = nodes[i]; i++) if (Element.descendantOf(targetNode, node)) return [targetNode]; } else if (combinator == 'adjacent') { for (var i = 0, node; node = nodes[i]; i++) if (Selector.handlers.previousElementSibling(targetNode) == node) return [targetNode]; } else nodes = h[combinator](nodes); } for (var i = 0, node; node = nodes[i]; i++) if (node == targetNode) return [targetNode]; return []; } return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; }, className: function(nodes, root, className, combinator) { if (nodes && combinator) nodes = this[combinator](nodes); return Selector.handlers.byClassName(nodes, root, className); }, byClassName: function(nodes, root, className) { if (!nodes) nodes = Selector.handlers.descendant([root]); var needle = ' ' + className + ' '; for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { nodeClassName = node.className; if (nodeClassName.length == 0) continue; if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) results.push(node); } return results; }, attrPresence: function(nodes, root, attr, combinator) { if (!nodes) nodes = root.getElementsByTagName("*"); if (nodes && combinator) nodes = this[combinator](nodes); var results = []; for (var i = 0, node; node = nodes[i]; i++) if (Element.hasAttribute(node, attr)) results.push(node); return results; }, attr: function(nodes, root, attr, value, operator, combinator) { if (!nodes) nodes = root.getElementsByTagName("*"); if (nodes && combinator) nodes = this[combinator](nodes); var handler = Selector.operators[operator], results = []; for (var i = 0, node; node = nodes[i]; i++) { var nodeValue = Element.readAttribute(node, attr); if (nodeValue === null) continue; if (handler(nodeValue, value)) results.push(node); } return results; }, pseudo: function(nodes, name, value, root, combinator) { if (nodes && combinator) nodes = this[combinator](nodes); if (!nodes) nodes = root.getElementsByTagName("*"); return Selector.pseudos[name](nodes, value, root); } }, pseudos: { 'first-child': function(nodes, value, root) { for (var i = 0, results = [], node; node = nodes[i]; i++) { if (Selector.handlers.previousElementSibling(node)) continue; results.push(node); } return results; }, 'last-child': function(nodes, value, root) { for (var i = 0, results = [], node; node = nodes[i]; i++) { if (Selector.handlers.nextElementSibling(node)) continue; results.push(node); } return results; }, 'only-child': function(nodes, value, root) { var h = Selector.handlers; for (var i = 0, results = [], node; node = nodes[i]; i++) if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) results.push(node); return results; }, 'nth-child': function(nodes, formula, root) { return Selector.pseudos.nth(nodes, formula, root); }, 'nth-last-child': function(nodes, formula, root) { return Selector.pseudos.nth(nodes, formula, root, true); }, 'nth-of-type': function(nodes, formula, root) { return Selector.pseudos.nth(nodes, formula, root, false, true); }, 'nth-last-of-type': function(nodes, formula, root) { return Selector.pseudos.nth(nodes, formula, root, true, true); }, 'first-of-type': function(nodes, formula, root) { return Selector.pseudos.nth(nodes, "1", root, false, true); }, 'last-of-type': function(nodes, formula, root) { return Selector.pseudos.nth(nodes, "1", root, true, true); }, 'only-of-type': function(nodes, formula, root) { var p = Selector.pseudos; return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); }, // handles the an+b logic getIndices: function(a, b, total) { if (a == 0) return b > 0 ? [b] : []; return $R(1, total).inject([], function(memo, i) { if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); return memo; }); }, // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type nth: function(nodes, formula, root, reverse, ofType) { if (nodes.length == 0) return []; if (formula == 'even') formula = '2n+0'; if (formula == 'odd') formula = '2n+1'; var h = Selector.handlers, results = [], indexed = [], m; h.mark(nodes); for (var i = 0, node; node = nodes[i]; i++) { if (!node.parentNode._countedByPrototype) { h.index(node.parentNode, reverse, ofType); indexed.push(node.parentNode); } } if (formula.match(/^\d+$/)) { // just a number formula = Number(formula); for (var i = 0, node; node = nodes[i]; i++) if (node.nodeIndex == formula) results.push(node); } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b if (m[1] == "-") m[1] = -1; var a = m[1] ? Number(m[1]) : 1; var b = m[2] ? Number(m[2]) : 0; var indices = Selector.pseudos.getIndices(a, b, nodes.length); for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { for (var j = 0; j < l; j++) if (node.nodeIndex == indices[j]) results.push(node); } } h.unmark(nodes); h.unmark(indexed); return results; }, 'empty': function(nodes, value, root) { for (var i = 0, results = [], node; node = nodes[i]; i++) { // IE treats comments as element nodes if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue; results.push(node); } return results; }, 'not': function(nodes, selector, root) { var h = Selector.handlers, selectorType, m; var exclusions = new Selector(selector).findElements(root); h.mark(exclusions); for (var i = 0, results = [], node; node = nodes[i]; i++) if (!node._countedByPrototype) results.push(node); h.unmark(exclusions); return results; }, 'enabled': function(nodes, value, root) { for (var i = 0, results = [], node; node = nodes[i]; i++) if (!node.disabled) results.push(node); return results; }, 'disabled': function(nodes, value, root) { for (var i = 0, results = [], node; node = nodes[i]; i++) if (node.disabled) results.push(node); return results; }, 'checked': function(nodes, value, root) { for (var i = 0, results = [], node; node = nodes[i]; i++) if (node.checked) results.push(node); return results; } }, operators: { '=': function(nv, v) { return nv == v; }, '!=': function(nv, v) { return nv != v; }, '^=': function(nv, v) { return nv.startsWith(v); }, '$=': function(nv, v) { return nv.endsWith(v); }, '*=': function(nv, v) { return nv.include(v); }, '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); } }, split: function(expression) { var expressions = []; expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { expressions.push(m[1].strip()); }); return expressions; }, matchElements: function(elements, expression) { var matches = $$(expression), h = Selector.handlers; h.mark(matches); for (var i = 0, results = [], element; element = elements[i]; i++) if (element._countedByPrototype) results.push(element); h.unmark(matches); return results; }, findElement: function(elements, expression, index) { if (Object.isNumber(expression)) { index = expression; expression = false; } return Selector.matchElements(elements, expression || '*')[index || 0]; }, findChildElements: function(element, expressions) { expressions = Selector.split(expressions.join(',')); var results = [], h = Selector.handlers; for (var i = 0, l = expressions.length, selector; i < l; i++) { selector = new Selector(expressions[i].strip()); h.concat(results, selector.findElements(element)); } return (l > 1) ? h.unique(results) : results; } }); if (Prototype.Browser.IE) { Object.extend(Selector.handlers, { // IE returns comment nodes on getElementsByTagName("*"). // Filter them out. concat: function(a, b) { for (var i = 0, node; node = b[i]; i++) if (node.tagName !== "!") a.push(node); return a; }, // IE improperly serializes _countedByPrototype in (inner|outer)HTML. unmark: function(nodes) { for (var i = 0, node; node = nodes[i]; i++) node.removeAttribute('_countedByPrototype'); return nodes; } }); } function $$() { return Selector.findChildElements(document, $A(arguments)); } var Form = { reset: function(form) { $(form).reset(); return form; }, serializeElements: function(elements, options) { if (typeof options != 'object') options = { hash: !!options }; else if (Object.isUndefined(options.hash)) options.hash = true; var key, value, submitted = false, submit = options.submit; var data = elements.inject({ }, function(result, element) { if (!element.disabled && element.name) { key = element.name; value = $(element).getValue(); if (value != null && (element.type != 'submit' || (!submitted && submit !== false && (!submit || key == submit) && (submitted = true)))) { if (key in result) { // a key is already present; construct an array of values if (!Object.isArray(result[key])) result[key] = [result[key]]; result[key].push(value); } else result[key] = value; } } return result; }); return options.hash ? data : Object.toQueryString(data); } }; Form.Methods = { serialize: function(form, options) { return Form.serializeElements(Form.getElements(form), options); }, getElements: function(form) { return $A($(form).getElementsByTagName('*')).inject([], function(elements, child) { if (Form.Element.Serializers[child.tagName.toLowerCase()]) elements.push(Element.extend(child)); return elements; } ); }, getInputs: function(form, typeName, name) { form = $(form); var inputs = form.getElementsByTagName('input'); if (!typeName && !name) return $A(inputs).map(Element.extend); for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { var input = inputs[i]; if ((typeName && input.type != typeName) || (name && input.name != name)) continue; matchingInputs.push(Element.extend(input)); } return matchingInputs; }, disable: function(form) { form = $(form); Form.getElements(form).invoke('disable'); return form; }, enable: function(form) { form = $(form); Form.getElements(form).invoke('enable'); return form; }, findFirstElement: function(form) { var elements = $(form).getElements().findAll(function(element) { return 'hidden' != element.type && !element.disabled; }); var firstByIndex = elements.findAll(function(element) { return element.hasAttribute('tabIndex') && element.tabIndex >= 0; }).sortBy(function(element) { return element.tabIndex }).first(); return firstByIndex ? firstByIndex : elements.find(function(element) { return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); }); }, focusFirstElement: function(form) { form = $(form); form.findFirstElement().activate(); return form; }, request: function(form, options) { form = $(form), options = Object.clone(options || { }); var params = options.parameters, action = form.readAttribute('action') || ''; if (action.blank()) action = window.location.href; options.parameters = form.serialize(true); if (params) { if (Object.isString(params)) params = params.toQueryParams(); Object.extend(options.parameters, params); } if (form.hasAttribute('method') && !options.method) options.method = form.method; return new Ajax.Request(action, options); } }; /*--------------------------------------------------------------------------*/ Form.Element = { focus: function(element) { $(element).focus(); return element; }, select: function(element) { $(element).select(); return element; } }; Form.Element.Methods = { serialize: function(element) { element = $(element); if (!element.disabled && element.name) { var value = element.getValue(); if (value != undefined) { var pair = { }; pair[element.name] = value; return Object.toQueryString(pair); } } return ''; }, getValue: function(element) { element = $(element); var method = element.tagName.toLowerCase(); return Form.Element.Serializers[method](element); }, setValue: function(element, value) { element = $(element); var method = element.tagName.toLowerCase(); Form.Element.Serializers[method](element, value); return element; }, clear: function(element) { $(element).value = ''; return element; }, present: function(element) { return $(element).value != ''; }, activate: function(element) { element = $(element); try { element.focus(); if (element.select && (element.tagName.toLowerCase() != 'input' || !['button', 'reset', 'submit'].include(element.type))) element.select(); } catch (e) { } return element; }, disable: function(element) { element = $(element); element.blur(); element.disabled = true; return element; }, enable: function(element) { element = $(element); element.disabled = false; return element; } }; /*--------------------------------------------------------------------------*/ var Field = Form.Element; var $F = Form.Element.Methods.getValue; /*--------------------------------------------------------------------------*/ Form.Element.Serializers = { input: function(element, value) { switch (element.type.toLowerCase()) { case 'checkbox': case 'radio': return Form.Element.Serializers.inputSelector(element, value); default: return Form.Element.Serializers.textarea(element, value); } }, inputSelector: function(element, value) { if (Object.isUndefined(value)) return element.checked ? element.value : null; else element.checked = !!value; }, textarea: function(element, value) { if (Object.isUndefined(value)) return element.value; else element.value = value; }, select: function(element, index) { if (Object.isUndefined(index)) return this[element.type == 'select-one' ? 'selectOne' : 'selectMany'](element); else { var opt, value, single = !Object.isArray(index); for (var i = 0, length = element.length; i < length; i++) { opt = element.options[i]; value = this.optionValue(opt); if (single) { if (value == index) { opt.selected = true; return; } } else opt.selected = index.include(value); } } }, selectOne: function(element) { var index = element.selectedIndex; return index >= 0 ? this.optionValue(element.options[index]) : null; }, selectMany: function(element) { var values, length = element.length; if (!length) return null; for (var i = 0, values = []; i < length; i++) { var opt = element.options[i]; if (opt.selected) values.push(this.optionValue(opt)); } return values; }, optionValue: function(opt) { // extend element because hasAttribute may not be native return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; } }; /*--------------------------------------------------------------------------*/ Abstract.TimedObserver = Class.create(PeriodicalExecuter, { initialize: function($super, element, frequency, callback) { $super(callback, frequency); this.element = $(element); this.lastValue = this.getValue(); }, execute: function() { var value = this.getValue(); if (Object.isString(this.lastValue) && Object.isString(value) ? this.lastValue != value : String(this.lastValue) != String(value)) { this.callback(this.element, value); this.lastValue = value; } } }); Form.Element.Observer = Class.create(Abstract.TimedObserver, { getValue: function() { return Form.Element.getValue(this.element); } }); Form.Observer = Class.create(Abstract.TimedObserver, { getValue: function() { return Form.serialize(this.element); } }); /*--------------------------------------------------------------------------*/ Abstract.EventObserver = Class.create({ initialize: function(element, callback) { this.element = $(element); this.callback = callback; this.lastValue = this.getValue(); if (this.element.tagName.toLowerCase() == 'form') this.registerFormCallbacks(); else this.registerCallback(this.element); }, onElementEvent: function() { var value = this.getValue(); if (this.lastValue != value) { this.callback(this.element, value); this.lastValue = value; } }, registerFormCallbacks: function() { Form.getElements(this.element).each(this.registerCallback, this); }, registerCallback: function(element) { if (element.type) { switch (element.type.toLowerCase()) { case 'checkbox': case 'radio': Event.observe(element, 'click', this.onElementEvent.bind(this)); break; default: Event.observe(element, 'change', this.onElementEvent.bind(this)); break; } } } }); Form.Element.EventObserver = Class.create(Abstract.EventObserver, { getValue: function() { return Form.Element.getValue(this.element); } }); Form.EventObserver = Class.create(Abstract.EventObserver, { getValue: function() { return Form.serialize(this.element); } }); if (!window.Event) var Event = { }; Object.extend(Event, { KEY_BACKSPACE: 8, KEY_TAB: 9, KEY_RETURN: 13, KEY_ESC: 27, KEY_LEFT: 37, KEY_UP: 38, KEY_RIGHT: 39, KEY_DOWN: 40, KEY_DELETE: 46, KEY_HOME: 36, KEY_END: 35, KEY_PAGEUP: 33, KEY_PAGEDOWN: 34, KEY_INSERT: 45, cache: { }, relatedTarget: function(event) { var element; switch(event.type) { case 'mouseover': element = event.fromElement; break; case 'mouseout': element = event.toElement; break; default: return null; } return Element.extend(element); } }); Event.Methods = (function() { var isButton; if (Prototype.Browser.IE) { var buttonMap = { 0: 1, 1: 4, 2: 2 }; isButton = function(event, code) { return event.button == buttonMap[code]; }; } else if (Prototype.Browser.WebKit) { isButton = function(event, code) { switch (code) { case 0: return event.which == 1 && !event.metaKey; case 1: return event.which == 1 && event.metaKey; default: return false; } }; } else { isButton = function(event, code) { return event.which ? (event.which === code + 1) : (event.button === code); }; } return { isLeftClick: function(event) { return isButton(event, 0) }, isMiddleClick: function(event) { return isButton(event, 1) }, isRightClick: function(event) { return isButton(event, 2) }, element: function(event) { var node = Event.extend(event).target; return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node); }, findElement: function(event, expression) { var element = Event.element(event); if (!expression) return element; var elements = [element].concat(element.ancestors()); return Selector.findElement(elements, expression, 0); }, pointer: function(event) { return { x: event.pageX || (event.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft)), y: event.pageY || (event.clientY + (document.documentElement.scrollTop || document.body.scrollTop)) }; }, pointerX: function(event) { return Event.pointer(event).x }, pointerY: function(event) { return Event.pointer(event).y }, stop: function(event) { Event.extend(event); event.preventDefault(); event.stopPropagation(); event.stopped = true; } }; })(); Event.extend = (function() { var methods = Object.keys(Event.Methods).inject({ }, function(m, name) { m[name] = Event.Methods[name].methodize(); return m; }); if (Prototype.Browser.IE) { Object.extend(methods, { stopPropagation: function() { this.cancelBubble = true }, preventDefault: function() { this.returnValue = false }, inspect: function() { return "[object Event]" } }); return function(event) { if (!event) return false; if (event._extendedByPrototype) return event; event._extendedByPrototype = Prototype.emptyFunction; var pointer = Event.pointer(event); Object.extend(event, { target: event.srcElement, relatedTarget: Event.relatedTarget(event), pageX: pointer.x, pageY: pointer.y }); return Object.extend(event, methods); }; } else { Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__; Object.extend(Event.prototype, methods); return Prototype.K; } })(); Object.extend(Event, (function() { var cache = Event.cache; function getEventID(element) { if (element._prototypeEventID) return element._prototypeEventID[0]; arguments.callee.id = arguments.callee.id || 1; return element._prototypeEventID = [++arguments.callee.id]; } function getDOMEventName(eventName) { if (eventName && eventName.include(':')) return "dataavailable"; return eventName; } function getCacheForID(id) { return cache[id] = cache[id] || { }; } function getWrappersForEventName(id, eventName) { var c = getCacheForID(id); return c[eventName] = c[eventName] || []; } function createWrapper(element, eventName, handler) { var id = getEventID(element); var c = getWrappersForEventName(id, eventName); if (c.pluck("handler").include(handler)) return false; var wrapper = function(event) { if (!Event || !Event.extend || (event.eventName && event.eventName != eventName)) return false; Event.extend(event); handler.call(element, event); }; wrapper.handler = handler; c.push(wrapper); return wrapper; } function findWrapper(id, eventName, handler) { var c = getWrappersForEventName(id, eventName); return c.find(function(wrapper) { return wrapper.handler == handler }); } function destroyWrapper(id, eventName, handler) { var c = getCacheForID(id); if (!c[eventName]) return false; c[eventName] = c[eventName].without(findWrapper(id, eventName, handler)); } function destroyCache() { for (var id in cache) for (var eventName in cache[id]) cache[id][eventName] = null; } if (window.attachEvent) { window.attachEvent("onunload", destroyCache); } return { observe: function(element, eventName, handler) { element = $(element); var name = getDOMEventName(eventName); var wrapper = createWrapper(element, eventName, handler); if (!wrapper) return element; if (element.addEventListener) { element.addEventListener(name, wrapper, false); } else { element.attachEvent("on" + name, wrapper); } return element; }, stopObserving: function(element, eventName, handler) { element = $(element); var id = getEventID(element), name = getDOMEventName(eventName); if (!handler && eventName) { getWrappersForEventName(id, eventName).each(function(wrapper) { element.stopObserving(eventName, wrapper.handler); }); return element; } else if (!eventName) { Object.keys(getCacheForID(id)).each(function(eventName) { element.stopObserving(eventName); }); return element; } var wrapper = findWrapper(id, eventName, handler); if (!wrapper) return element; if (element.removeEventListener) { element.removeEventListener(name, wrapper, false); } else { element.detachEvent("on" + name, wrapper); } destroyWrapper(id, eventName, handler); return element; }, fire: function(element, eventName, memo) { element = $(element); if (element == document && document.createEvent && !element.dispatchEvent) element = document.documentElement; var event; if (document.createEvent) { event = document.createEvent("HTMLEvents"); event.initEvent("dataavailable", true, true); } else { event = document.createEventObject(); event.eventType = "ondataavailable"; } event.eventName = eventName; event.memo = memo || { }; if (document.createEvent) { element.dispatchEvent(event); } else { element.fireEvent(event.eventType, event); } return Event.extend(event); } }; })()); Object.extend(Event, Event.Methods); Element.addMethods({ fire: Event.fire, observe: Event.observe, stopObserving: Event.stopObserving }); Object.extend(document, { fire: Element.Methods.fire.methodize(), observe: Element.Methods.observe.methodize(), stopObserving: Element.Methods.stopObserving.methodize(), loaded: false }); (function() { /* Support for the DOMContentLoaded event is based on work by Dan Webb, Matthias Miller, Dean Edwards and John Resig. */ var timer; function fireContentLoadedEvent() { if (document.loaded) return; if (timer) window.clearInterval(timer); document.fire("dom:loaded"); document.loaded = true; } if (document.addEventListener) { if (Prototype.Browser.WebKit) { timer = window.setInterval(function() { if (/loaded|complete/.test(document.readyState)) fireContentLoadedEvent(); }, 0); Event.observe(window, "load", fireContentLoadedEvent); } else { document.addEventListener("DOMContentLoaded", fireContentLoadedEvent, false); } } else { document.write("