diff --git a/css/application.css b/css/application.css index c03266668f..7b1e03381f 100644 --- a/css/application.css +++ b/css/application.css @@ -6,7 +6,7 @@ Author: Richard Clark - http://richclarkdesign.com Twitter: @rich_clark */ html, body, div, span, object, iframe, -h1, h2, h3, div.wiki-wrapper div#wiki_panel input[type="button"], h4, h5, h6, p, blockquote, pre, +h1, h2, h3, div#wiki_panel input[type="button"], h4, h5, h6, p, blockquote, pre, abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp, small, strong, sub, sup, var, @@ -129,20 +129,20 @@ input, select { font-weight: 800; font-style: italic; } -.clearfix:after, .topbar:after, nav.sequence-nav:after, div.book-wrapper section.book nav:after, div.wiki-wrapper section.wiki-body header:after, body.askbot .secondary-nav nav:after, html body div.header-wrapper header:after, html body div.header-wrapper header hgroup:after, html body div.header-wrapper header nav ul:after, html body section.main-content:after, html footer:after, div.leanModal_box#enroll ol:after, div.course-wrapper section.course-content .problem-set:after, div.course-wrapper section.course-content section.problems-wrapper:after, div.course-wrapper section.course-content div#seq_content:after, div.course-wrapper section.course-content ol.vert-mod > li:after, section.course-content div.video-wrapper section.video-controls:after, section.course-content div.video-wrapper section.video-controls div#slider:after, div.book-wrapper section.book nav ul:after, div.info-wrapper section.updates ol li:after, div.info-wrapper section.handouts ol li:after, div.profile-wrapper section.course-info ol > li:after, div.wiki-wrapper div#wiki_panel div#wiki_create_form:after { +.clearfix:after, .topbar:after, nav.sequence-nav:after, div.book-wrapper section.book nav:after, div.wiki-wrapper section.wiki-body header:after, html body section.main-content:after, div.header-wrapper header:after, div.header-wrapper header hgroup:after, div.header-wrapper header nav ul:after, footer:after, div.leanModal_box#enroll ol:after, div.course-wrapper section.course-content .problem-set:after, div.course-wrapper section.course-content section.problems-wrapper:after, div.course-wrapper section.course-content div#seq_content:after, div.course-wrapper section.course-content ol.vert-mod > li:after, section.course-content div.video-wrapper section.video-controls:after, section.course-content div.video-wrapper section.video-controls div#slider:after, div.book-wrapper section.book nav ul:after, div.info-wrapper section.updates ol li:after, div.info-wrapper section.handouts ol li:after, div.profile-wrapper section.course-info ol > li:after, div#wiki_panel div#wiki_create_form:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } -.wrapper, html body div.header-wrapper header, html body section.main-content, html footer, section.activation, body.askbot .secondary-nav nav { +.wrapper, html body section.main-content, div.header-wrapper header, footer { margin: 0 auto; max-width: 1400px; min-width: 810px; width: 100%; text-align: left; } - .wrapper div.table-wrapper, html body div.header-wrapper header div.table-wrapper, html body section.main-content div.table-wrapper, html footer div.table-wrapper, section.activation div.table-wrapper, body.askbot .secondary-nav nav div.table-wrapper, .wrapper div.course-wrapper, html body div.header-wrapper header div.course-wrapper, html body section.main-content div.course-wrapper, html footer div.course-wrapper, section.activation div.course-wrapper, body.askbot .secondary-nav nav div.course-wrapper, .wrapper div.book-wrapper, html body div.header-wrapper header div.book-wrapper, html body section.main-content div.book-wrapper, html footer div.book-wrapper, section.activation div.book-wrapper, body.askbot .secondary-nav nav div.book-wrapper, .wrapper div.info-wrapper, html body div.header-wrapper header div.info-wrapper, html body section.main-content div.info-wrapper, html footer div.info-wrapper, section.activation div.info-wrapper, body.askbot .secondary-nav nav div.info-wrapper, .wrapper div.profile-wrapper, html body div.header-wrapper header div.profile-wrapper, html body section.main-content div.profile-wrapper, html footer div.profile-wrapper, section.activation div.profile-wrapper, body.askbot .secondary-nav nav div.profile-wrapper, .wrapper body.askbot section.main-content div.discussion-wrapper, body.askbot section.main-content .wrapper div.discussion-wrapper, html body.askbot div.header-wrapper header section.main-content div.discussion-wrapper, html body.askbot section.main-content div.header-wrapper header div.discussion-wrapper, html body.askbot section.main-content div.discussion-wrapper, html footer body.askbot section.main-content div.discussion-wrapper, body.askbot section.main-content html footer div.discussion-wrapper, section.activation body.askbot section.main-content div.discussion-wrapper, body.askbot section.main-content section.activation div.discussion-wrapper, body.askbot .secondary-nav nav section.main-content div.discussion-wrapper, body.askbot section.main-content .secondary-nav nav div.discussion-wrapper { + .wrapper div.table-wrapper, html body section.main-content div.table-wrapper, div.header-wrapper header div.table-wrapper, footer div.table-wrapper, .wrapper div.course-wrapper, html body section.main-content div.course-wrapper, div.header-wrapper header div.course-wrapper, footer div.course-wrapper, .wrapper div.book-wrapper, html body section.main-content div.book-wrapper, div.header-wrapper header div.book-wrapper, footer div.book-wrapper, .wrapper div.info-wrapper, html body section.main-content div.info-wrapper, div.header-wrapper header div.info-wrapper, footer div.info-wrapper, .wrapper div.profile-wrapper, html body section.main-content div.profile-wrapper, div.header-wrapper header div.profile-wrapper, footer div.profile-wrapper, .wrapper body.askbot section.main-content div.discussion-wrapper, body.askbot section.main-content .wrapper div.discussion-wrapper, html body.askbot section.main-content div.discussion-wrapper, div.header-wrapper header body.askbot section.main-content div.discussion-wrapper, body.askbot section.main-content div.header-wrapper header div.discussion-wrapper, footer body.askbot section.main-content div.discussion-wrapper, body.askbot section.main-content footer div.discussion-wrapper { display: table; width: 100%; } @@ -207,7 +207,7 @@ h1.top-header, div.info-wrapper section.updates > h1, div.profile-wrapper sectio vertical-align: top; width: 76.518%; } -.sidebar, div.course-wrapper div#accordion, div.book-wrapper ul#booknav, div.info-wrapper section.handouts, div.profile-wrapper section.user-info, div.wiki-wrapper div#wiki_panel, body.askbot section.main-content div.discussion-wrapper aside { +.sidebar, div#accordion, div.book-wrapper ul#booknav, div.info-wrapper section.handouts, div.profile-wrapper section.user-info, div#wiki_panel, body.askbot section.main-content div.discussion-wrapper aside { -webkit-box-shadow: inset 0 0 0 1px #f6f6f6; -moz-box-shadow: inset 0 0 0 1px #f6f6f6; -ms-box-shadow: inset 0 0 0 1px #f6f6f6; @@ -231,7 +231,7 @@ h1.top-header, div.info-wrapper section.updates > h1, div.profile-wrapper sectio vertical-align: top; width: 23.482%; position: relative; } - .sidebar h3, div.course-wrapper div#accordion h3, div.book-wrapper ul#booknav h3, div.info-wrapper section.handouts h3, div.profile-wrapper section.user-info h3, div.wiki-wrapper div#wiki_panel h3, body.askbot section.main-content div.discussion-wrapper aside h3, .sidebar div.wiki-wrapper div#wiki_panel input[type="button"], div.wiki-wrapper div#wiki_panel .sidebar input[type="button"], div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel input[type="button"], div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion input[type="button"], div.book-wrapper ul#booknav div.wiki-wrapper div#wiki_panel input[type="button"], div.wiki-wrapper div#wiki_panel div.book-wrapper ul#booknav input[type="button"], div.info-wrapper section.handouts div.wiki-wrapper div#wiki_panel input[type="button"], div.wiki-wrapper div#wiki_panel div.info-wrapper section.handouts input[type="button"], div.profile-wrapper section.user-info div.wiki-wrapper div#wiki_panel input[type="button"], div.wiki-wrapper div#wiki_panel div.profile-wrapper section.user-info input[type="button"], div.wiki-wrapper div#wiki_panel input[type="button"], body.askbot section.main-content div.discussion-wrapper aside div.wiki-wrapper div#wiki_panel input[type="button"], div.wiki-wrapper div#wiki_panel body.askbot section.main-content div.discussion-wrapper aside input[type="button"] { + .sidebar h3, div#accordion h3, div.book-wrapper ul#booknav h3, div.info-wrapper section.handouts h3, div.profile-wrapper section.user-info h3, div#wiki_panel h3, body.askbot section.main-content div.discussion-wrapper aside h3, .sidebar div#wiki_panel input[type="button"], div#wiki_panel .sidebar input[type="button"], div#accordion div#wiki_panel input[type="button"], div#wiki_panel div#accordion input[type="button"], div.book-wrapper ul#booknav div#wiki_panel input[type="button"], div#wiki_panel div.book-wrapper ul#booknav input[type="button"], div.info-wrapper section.handouts div#wiki_panel input[type="button"], div#wiki_panel div.info-wrapper section.handouts input[type="button"], div.profile-wrapper section.user-info div#wiki_panel input[type="button"], div#wiki_panel div.profile-wrapper section.user-info input[type="button"], div#wiki_panel input[type="button"], body.askbot section.main-content div.discussion-wrapper aside div#wiki_panel input[type="button"], div#wiki_panel body.askbot section.main-content div.discussion-wrapper aside input[type="button"] { -webkit-box-shadow: 0 1px 0 #eeeeee; -moz-box-shadow: 0 1px 0 #eeeeee; -ms-box-shadow: 0 1px 0 #eeeeee; @@ -244,7 +244,7 @@ h1.top-header, div.info-wrapper section.updates > h1, div.profile-wrapper sectio font-weight: normal; margin: 0; overflow: hidden; } - .sidebar h3 a, div.course-wrapper div#accordion h3 a, div.book-wrapper ul#booknav h3 a, div.info-wrapper section.handouts h3 a, div.profile-wrapper section.user-info h3 a, div.wiki-wrapper div#wiki_panel h3 a, body.askbot section.main-content div.discussion-wrapper aside h3 a, .sidebar div.wiki-wrapper div#wiki_panel input[type="button"] a, div.wiki-wrapper div#wiki_panel .sidebar input[type="button"] a, div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel input[type="button"] a, div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion input[type="button"] a, div.book-wrapper ul#booknav div.wiki-wrapper div#wiki_panel input[type="button"] a, div.wiki-wrapper div#wiki_panel div.book-wrapper ul#booknav input[type="button"] a, div.info-wrapper section.handouts div.wiki-wrapper div#wiki_panel input[type="button"] a, div.wiki-wrapper div#wiki_panel div.info-wrapper section.handouts input[type="button"] a, div.profile-wrapper section.user-info div.wiki-wrapper div#wiki_panel input[type="button"] a, div.wiki-wrapper div#wiki_panel div.profile-wrapper section.user-info input[type="button"] a, div.wiki-wrapper div#wiki_panel input[type="button"] a, body.askbot section.main-content div.discussion-wrapper aside div.wiki-wrapper div#wiki_panel input[type="button"] a, div.wiki-wrapper div#wiki_panel body.askbot section.main-content div.discussion-wrapper aside input[type="button"] a { + .sidebar h3 a, div#accordion h3 a, div.book-wrapper ul#booknav h3 a, div.info-wrapper section.handouts h3 a, div.profile-wrapper section.user-info h3 a, div#wiki_panel h3 a, body.askbot section.main-content div.discussion-wrapper aside h3 a, .sidebar div#wiki_panel input[type="button"] a, div#wiki_panel .sidebar input[type="button"] a, div#accordion div#wiki_panel input[type="button"] a, div#wiki_panel div#accordion input[type="button"] a, div.book-wrapper ul#booknav div#wiki_panel input[type="button"] a, div#wiki_panel div.book-wrapper ul#booknav input[type="button"] a, div.info-wrapper section.handouts div#wiki_panel input[type="button"] a, div#wiki_panel div.info-wrapper section.handouts input[type="button"] a, div.profile-wrapper section.user-info div#wiki_panel input[type="button"] a, div#wiki_panel div.profile-wrapper section.user-info input[type="button"] a, div#wiki_panel input[type="button"] a, body.askbot section.main-content div.discussion-wrapper aside div#wiki_panel input[type="button"] a, div#wiki_panel body.askbot section.main-content div.discussion-wrapper aside input[type="button"] a { -webkit-transition-property: all; -moz-transition-property: all; -ms-transition-property: all; @@ -270,16 +270,16 @@ h1.top-header, div.info-wrapper section.updates > h1, div.profile-wrapper sectio font-size: 14px; padding: 7px 7px 7px 30px; text-decoration: none; } - .sidebar h3 a:hover, div.course-wrapper div#accordion h3 a:hover, div.book-wrapper ul#booknav h3 a:hover, div.info-wrapper section.handouts h3 a:hover, div.profile-wrapper section.user-info h3 a:hover, div.wiki-wrapper div#wiki_panel h3 a:hover, body.askbot section.main-content div.discussion-wrapper aside h3 a:hover, .sidebar div.wiki-wrapper div#wiki_panel input[type="button"] a:hover, div.wiki-wrapper div#wiki_panel .sidebar input[type="button"] a:hover, div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel input[type="button"] a:hover, div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion input[type="button"] a:hover, div.book-wrapper ul#booknav div.wiki-wrapper div#wiki_panel input[type="button"] a:hover, div.wiki-wrapper div#wiki_panel div.book-wrapper ul#booknav input[type="button"] a:hover, div.info-wrapper section.handouts div.wiki-wrapper div#wiki_panel input[type="button"] a:hover, div.wiki-wrapper div#wiki_panel div.info-wrapper section.handouts input[type="button"] a:hover, div.profile-wrapper section.user-info div.wiki-wrapper div#wiki_panel input[type="button"] a:hover, div.wiki-wrapper div#wiki_panel div.profile-wrapper section.user-info input[type="button"] a:hover, div.wiki-wrapper div#wiki_panel input[type="button"] a:hover, body.askbot section.main-content div.discussion-wrapper aside div.wiki-wrapper div#wiki_panel input[type="button"] a:hover, div.wiki-wrapper div#wiki_panel body.askbot section.main-content div.discussion-wrapper aside input[type="button"] a:hover { + .sidebar h3 a:hover, div#accordion h3 a:hover, div.book-wrapper ul#booknav h3 a:hover, div.info-wrapper section.handouts h3 a:hover, div.profile-wrapper section.user-info h3 a:hover, div#wiki_panel h3 a:hover, body.askbot section.main-content div.discussion-wrapper aside h3 a:hover, .sidebar div#wiki_panel input[type="button"] a:hover, div#wiki_panel .sidebar input[type="button"] a:hover, div#accordion div#wiki_panel input[type="button"] a:hover, div#wiki_panel div#accordion input[type="button"] a:hover, div.book-wrapper ul#booknav div#wiki_panel input[type="button"] a:hover, div#wiki_panel div.book-wrapper ul#booknav input[type="button"] a:hover, div.info-wrapper section.handouts div#wiki_panel input[type="button"] a:hover, div#wiki_panel div.info-wrapper section.handouts input[type="button"] a:hover, div.profile-wrapper section.user-info div#wiki_panel input[type="button"] a:hover, div#wiki_panel div.profile-wrapper section.user-info input[type="button"] a:hover, div#wiki_panel input[type="button"] a:hover, body.askbot section.main-content div.discussion-wrapper aside div#wiki_panel input[type="button"] a:hover, div#wiki_panel body.askbot section.main-content div.discussion-wrapper aside input[type="button"] a:hover { -webkit-box-shadow: 0 1px 0 white; -moz-box-shadow: 0 1px 0 white; -ms-box-shadow: 0 1px 0 white; -o-box-shadow: 0 1px 0 white; box-shadow: 0 1px 0 white; background: #efefef; } - .sidebar h3 span.ui-icon, div.course-wrapper div#accordion h3 span.ui-icon, div.book-wrapper ul#booknav h3 span.ui-icon, div.info-wrapper section.handouts h3 span.ui-icon, div.profile-wrapper section.user-info h3 span.ui-icon, div.wiki-wrapper div#wiki_panel h3 span.ui-icon, body.askbot section.main-content div.discussion-wrapper aside h3 span.ui-icon, .sidebar div.wiki-wrapper div#wiki_panel input[type="button"] span.ui-icon, div.wiki-wrapper div#wiki_panel .sidebar input[type="button"] span.ui-icon, div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel input[type="button"] span.ui-icon, div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion input[type="button"] span.ui-icon, div.book-wrapper ul#booknav div.wiki-wrapper div#wiki_panel input[type="button"] span.ui-icon, div.wiki-wrapper div#wiki_panel div.book-wrapper ul#booknav input[type="button"] span.ui-icon, div.info-wrapper section.handouts div.wiki-wrapper div#wiki_panel input[type="button"] span.ui-icon, div.wiki-wrapper div#wiki_panel div.info-wrapper section.handouts input[type="button"] span.ui-icon, div.profile-wrapper section.user-info div.wiki-wrapper div#wiki_panel input[type="button"] span.ui-icon, div.wiki-wrapper div#wiki_panel div.profile-wrapper section.user-info input[type="button"] span.ui-icon, div.wiki-wrapper div#wiki_panel input[type="button"] span.ui-icon, body.askbot section.main-content div.discussion-wrapper aside div.wiki-wrapper div#wiki_panel input[type="button"] span.ui-icon, div.wiki-wrapper div#wiki_panel body.askbot section.main-content div.discussion-wrapper aside input[type="button"] span.ui-icon { + .sidebar h3 span.ui-icon, div#accordion h3 span.ui-icon, div.book-wrapper ul#booknav h3 span.ui-icon, div.info-wrapper section.handouts h3 span.ui-icon, div.profile-wrapper section.user-info h3 span.ui-icon, div#wiki_panel h3 span.ui-icon, body.askbot section.main-content div.discussion-wrapper aside h3 span.ui-icon, .sidebar div#wiki_panel input[type="button"] span.ui-icon, div#wiki_panel .sidebar input[type="button"] span.ui-icon, div#accordion div#wiki_panel input[type="button"] span.ui-icon, div#wiki_panel div#accordion input[type="button"] span.ui-icon, div.book-wrapper ul#booknav div#wiki_panel input[type="button"] span.ui-icon, div#wiki_panel div.book-wrapper ul#booknav input[type="button"] span.ui-icon, div.info-wrapper section.handouts div#wiki_panel input[type="button"] span.ui-icon, div#wiki_panel div.info-wrapper section.handouts input[type="button"] span.ui-icon, div.profile-wrapper section.user-info div#wiki_panel input[type="button"] span.ui-icon, div#wiki_panel div.profile-wrapper section.user-info input[type="button"] span.ui-icon, div#wiki_panel input[type="button"] span.ui-icon, body.askbot section.main-content div.discussion-wrapper aside div#wiki_panel input[type="button"] span.ui-icon, div#wiki_panel body.askbot section.main-content div.discussion-wrapper aside input[type="button"] span.ui-icon { background-image: url(images/ui-icons_454545_256x240.png); } - .sidebar h3.active, div.course-wrapper div#accordion h3.active, div.book-wrapper ul#booknav h3.active, div.info-wrapper section.handouts h3.active, div.profile-wrapper section.user-info h3.active, div.wiki-wrapper div#wiki_panel h3.active, body.askbot section.main-content div.discussion-wrapper aside h3.active, .sidebar div.course-wrapper div#accordion h3.ui-accordion-header.ui-state-active, div.course-wrapper div#accordion .sidebar h3.ui-accordion-header.ui-state-active, div.course-wrapper div#accordion h3.ui-accordion-header.ui-state-active, div.book-wrapper ul#booknav div.course-wrapper div#accordion h3.ui-accordion-header.ui-state-active, div.course-wrapper div#accordion div.book-wrapper ul#booknav h3.ui-accordion-header.ui-state-active, div.info-wrapper section.handouts div.course-wrapper div#accordion h3.ui-accordion-header.ui-state-active, div.course-wrapper div#accordion div.info-wrapper section.handouts h3.ui-accordion-header.ui-state-active, div.profile-wrapper section.user-info div.course-wrapper div#accordion h3.ui-accordion-header.ui-state-active, div.course-wrapper div#accordion div.profile-wrapper section.user-info h3.ui-accordion-header.ui-state-active, div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion h3.ui-accordion-header.ui-state-active, div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel h3.ui-accordion-header.ui-state-active, body.askbot section.main-content div.discussion-wrapper aside div.course-wrapper div#accordion h3.ui-accordion-header.ui-state-active, div.course-wrapper div#accordion body.askbot section.main-content div.discussion-wrapper aside h3.ui-accordion-header.ui-state-active, .sidebar div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel input.ui-accordion-header.ui-state-active[type="button"], div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel .sidebar input.ui-accordion-header.ui-state-active[type="button"], div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel input.ui-accordion-header.ui-state-active[type="button"], div.book-wrapper ul#booknav div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel input.ui-accordion-header.ui-state-active[type="button"], div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel div.book-wrapper ul#booknav input.ui-accordion-header.ui-state-active[type="button"], div.info-wrapper section.handouts div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel input.ui-accordion-header.ui-state-active[type="button"], div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel div.info-wrapper section.handouts input.ui-accordion-header.ui-state-active[type="button"], div.profile-wrapper section.user-info div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel input.ui-accordion-header.ui-state-active[type="button"], div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel div.profile-wrapper section.user-info input.ui-accordion-header.ui-state-active[type="button"], div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel input.ui-accordion-header.ui-state-active[type="button"], body.askbot section.main-content div.discussion-wrapper aside div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel input.ui-accordion-header.ui-state-active[type="button"], div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel body.askbot section.main-content div.discussion-wrapper aside input.ui-accordion-header.ui-state-active[type="button"], .sidebar div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion input.ui-accordion-header.ui-state-active[type="button"], div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion .sidebar input.ui-accordion-header.ui-state-active[type="button"], div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion input.ui-accordion-header.ui-state-active[type="button"], div.book-wrapper ul#booknav div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion input.ui-accordion-header.ui-state-active[type="button"], div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion div.book-wrapper ul#booknav input.ui-accordion-header.ui-state-active[type="button"], div.info-wrapper section.handouts div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion input.ui-accordion-header.ui-state-active[type="button"], div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion div.info-wrapper section.handouts input.ui-accordion-header.ui-state-active[type="button"], div.profile-wrapper section.user-info div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion input.ui-accordion-header.ui-state-active[type="button"], div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion div.profile-wrapper section.user-info input.ui-accordion-header.ui-state-active[type="button"], div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion input.ui-accordion-header.ui-state-active[type="button"], body.askbot section.main-content div.discussion-wrapper aside div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion input.ui-accordion-header.ui-state-active[type="button"], div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion body.askbot section.main-content div.discussion-wrapper aside input.ui-accordion-header.ui-state-active[type="button"], .sidebar div.wiki-wrapper div#wiki_panel input.active[type="button"], div.wiki-wrapper div#wiki_panel .sidebar input.active[type="button"], div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel input.active[type="button"], div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion input.active[type="button"], div.book-wrapper ul#booknav div.wiki-wrapper div#wiki_panel input.active[type="button"], div.wiki-wrapper div#wiki_panel div.book-wrapper ul#booknav input.active[type="button"], div.info-wrapper section.handouts div.wiki-wrapper div#wiki_panel input.active[type="button"], div.wiki-wrapper div#wiki_panel div.info-wrapper section.handouts input.active[type="button"], div.profile-wrapper section.user-info div.wiki-wrapper div#wiki_panel input.active[type="button"], div.wiki-wrapper div#wiki_panel div.profile-wrapper section.user-info input.active[type="button"], div.wiki-wrapper div#wiki_panel input.active[type="button"], body.askbot section.main-content div.discussion-wrapper aside div.wiki-wrapper div#wiki_panel input.active[type="button"], div.wiki-wrapper div#wiki_panel body.askbot section.main-content div.discussion-wrapper aside input.active[type="button"] { + .sidebar h3.active, div#accordion h3.active, div.book-wrapper ul#booknav h3.active, div.info-wrapper section.handouts h3.active, div.profile-wrapper section.user-info h3.active, div#wiki_panel h3.active, body.askbot section.main-content div.discussion-wrapper aside h3.active, .sidebar div#accordion h3.ui-accordion-header.ui-state-active, div#accordion .sidebar h3.ui-accordion-header.ui-state-active, div#accordion h3.ui-accordion-header.ui-state-active, div.book-wrapper ul#booknav div#accordion h3.ui-accordion-header.ui-state-active, div#accordion div.book-wrapper ul#booknav h3.ui-accordion-header.ui-state-active, div.info-wrapper section.handouts div#accordion h3.ui-accordion-header.ui-state-active, div#accordion div.info-wrapper section.handouts h3.ui-accordion-header.ui-state-active, div.profile-wrapper section.user-info div#accordion h3.ui-accordion-header.ui-state-active, div#accordion div.profile-wrapper section.user-info h3.ui-accordion-header.ui-state-active, div#wiki_panel div#accordion h3.ui-accordion-header.ui-state-active, div#accordion div#wiki_panel h3.ui-accordion-header.ui-state-active, body.askbot section.main-content div.discussion-wrapper aside div#accordion h3.ui-accordion-header.ui-state-active, div#accordion body.askbot section.main-content div.discussion-wrapper aside h3.ui-accordion-header.ui-state-active, .sidebar div#accordion div#wiki_panel input.ui-accordion-header.ui-state-active[type="button"], div#accordion div#wiki_panel .sidebar input.ui-accordion-header.ui-state-active[type="button"], div#accordion div#wiki_panel input.ui-accordion-header.ui-state-active[type="button"], div.book-wrapper ul#booknav div#accordion div#wiki_panel input.ui-accordion-header.ui-state-active[type="button"], div#accordion div#wiki_panel div.book-wrapper ul#booknav input.ui-accordion-header.ui-state-active[type="button"], div.info-wrapper section.handouts div#accordion div#wiki_panel input.ui-accordion-header.ui-state-active[type="button"], div#accordion div#wiki_panel div.info-wrapper section.handouts input.ui-accordion-header.ui-state-active[type="button"], div.profile-wrapper section.user-info div#accordion div#wiki_panel input.ui-accordion-header.ui-state-active[type="button"], div#accordion div#wiki_panel div.profile-wrapper section.user-info input.ui-accordion-header.ui-state-active[type="button"], div#accordion div#wiki_panel input.ui-accordion-header.ui-state-active[type="button"], body.askbot section.main-content div.discussion-wrapper aside div#accordion div#wiki_panel input.ui-accordion-header.ui-state-active[type="button"], div#accordion div#wiki_panel body.askbot section.main-content div.discussion-wrapper aside input.ui-accordion-header.ui-state-active[type="button"], .sidebar div#wiki_panel div#accordion input.ui-accordion-header.ui-state-active[type="button"], div#wiki_panel div#accordion .sidebar input.ui-accordion-header.ui-state-active[type="button"], div#wiki_panel div#accordion input.ui-accordion-header.ui-state-active[type="button"], div.book-wrapper ul#booknav div#wiki_panel div#accordion input.ui-accordion-header.ui-state-active[type="button"], div#wiki_panel div#accordion div.book-wrapper ul#booknav input.ui-accordion-header.ui-state-active[type="button"], div.info-wrapper section.handouts div#wiki_panel div#accordion input.ui-accordion-header.ui-state-active[type="button"], div#wiki_panel div#accordion div.info-wrapper section.handouts input.ui-accordion-header.ui-state-active[type="button"], div.profile-wrapper section.user-info div#wiki_panel div#accordion input.ui-accordion-header.ui-state-active[type="button"], div#wiki_panel div#accordion div.profile-wrapper section.user-info input.ui-accordion-header.ui-state-active[type="button"], div#wiki_panel div#accordion input.ui-accordion-header.ui-state-active[type="button"], body.askbot section.main-content div.discussion-wrapper aside div#wiki_panel div#accordion input.ui-accordion-header.ui-state-active[type="button"], div#wiki_panel div#accordion body.askbot section.main-content div.discussion-wrapper aside input.ui-accordion-header.ui-state-active[type="button"], .sidebar div#wiki_panel input.active[type="button"], div#wiki_panel .sidebar input.active[type="button"], div#accordion div#wiki_panel input.active[type="button"], div#wiki_panel div#accordion input.active[type="button"], div.book-wrapper ul#booknav div#wiki_panel input.active[type="button"], div#wiki_panel div.book-wrapper ul#booknav input.active[type="button"], div.info-wrapper section.handouts div#wiki_panel input.active[type="button"], div#wiki_panel div.info-wrapper section.handouts input.active[type="button"], div.profile-wrapper section.user-info div#wiki_panel input.active[type="button"], div#wiki_panel div.profile-wrapper section.user-info input.active[type="button"], div#wiki_panel input.active[type="button"], body.askbot section.main-content div.discussion-wrapper aside div#wiki_panel input.active[type="button"], div#wiki_panel body.askbot section.main-content div.discussion-wrapper aside input.active[type="button"] { -webkit-box-shadow: none; -moz-box-shadow: none; -ms-box-shadow: none; @@ -290,10 +290,10 @@ h1.top-header, div.info-wrapper section.updates > h1, div.profile-wrapper sectio border-bottom: 1px solid #bbb; color: #000; font-weight: bold; } - .sidebar h3.active a, div.course-wrapper div#accordion h3.active a, div.book-wrapper ul#booknav h3.active a, div.info-wrapper section.handouts h3.active a, div.profile-wrapper section.user-info h3.active a, div.wiki-wrapper div#wiki_panel h3.active a, body.askbot section.main-content div.discussion-wrapper aside h3.active a, .sidebar div.course-wrapper div#accordion h3.ui-accordion-header.ui-state-active a, div.course-wrapper div#accordion .sidebar h3.ui-accordion-header.ui-state-active a, div.course-wrapper div#accordion h3.ui-accordion-header.ui-state-active a, div.book-wrapper ul#booknav div.course-wrapper div#accordion h3.ui-accordion-header.ui-state-active a, div.course-wrapper div#accordion div.book-wrapper ul#booknav h3.ui-accordion-header.ui-state-active a, div.info-wrapper section.handouts div.course-wrapper div#accordion h3.ui-accordion-header.ui-state-active a, div.course-wrapper div#accordion div.info-wrapper section.handouts h3.ui-accordion-header.ui-state-active a, div.profile-wrapper section.user-info div.course-wrapper div#accordion h3.ui-accordion-header.ui-state-active a, div.course-wrapper div#accordion div.profile-wrapper section.user-info h3.ui-accordion-header.ui-state-active a, div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion h3.ui-accordion-header.ui-state-active a, div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel h3.ui-accordion-header.ui-state-active a, body.askbot section.main-content div.discussion-wrapper aside div.course-wrapper div#accordion h3.ui-accordion-header.ui-state-active a, div.course-wrapper div#accordion body.askbot section.main-content div.discussion-wrapper aside h3.ui-accordion-header.ui-state-active a, .sidebar div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel input.ui-accordion-header.ui-state-active[type="button"] a, div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel .sidebar input.ui-accordion-header.ui-state-active[type="button"] a, div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel input.ui-accordion-header.ui-state-active[type="button"] a, div.book-wrapper ul#booknav div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel input.ui-accordion-header.ui-state-active[type="button"] a, div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel div.book-wrapper ul#booknav input.ui-accordion-header.ui-state-active[type="button"] a, div.info-wrapper section.handouts div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel input.ui-accordion-header.ui-state-active[type="button"] a, div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel div.info-wrapper section.handouts input.ui-accordion-header.ui-state-active[type="button"] a, div.profile-wrapper section.user-info div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel input.ui-accordion-header.ui-state-active[type="button"] a, div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel div.profile-wrapper section.user-info input.ui-accordion-header.ui-state-active[type="button"] a, div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel input.ui-accordion-header.ui-state-active[type="button"] a, body.askbot section.main-content div.discussion-wrapper aside div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel input.ui-accordion-header.ui-state-active[type="button"] a, div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel body.askbot section.main-content div.discussion-wrapper aside input.ui-accordion-header.ui-state-active[type="button"] a, .sidebar div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion input.ui-accordion-header.ui-state-active[type="button"] a, div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion .sidebar input.ui-accordion-header.ui-state-active[type="button"] a, div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion input.ui-accordion-header.ui-state-active[type="button"] a, div.book-wrapper ul#booknav div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion input.ui-accordion-header.ui-state-active[type="button"] a, div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion div.book-wrapper ul#booknav input.ui-accordion-header.ui-state-active[type="button"] a, div.info-wrapper section.handouts div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion input.ui-accordion-header.ui-state-active[type="button"] a, div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion div.info-wrapper section.handouts input.ui-accordion-header.ui-state-active[type="button"] a, div.profile-wrapper section.user-info div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion input.ui-accordion-header.ui-state-active[type="button"] a, div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion div.profile-wrapper section.user-info input.ui-accordion-header.ui-state-active[type="button"] a, div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion input.ui-accordion-header.ui-state-active[type="button"] a, body.askbot section.main-content div.discussion-wrapper aside div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion input.ui-accordion-header.ui-state-active[type="button"] a, div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion body.askbot section.main-content div.discussion-wrapper aside input.ui-accordion-header.ui-state-active[type="button"] a, .sidebar div.wiki-wrapper div#wiki_panel input.active[type="button"] a, div.wiki-wrapper div#wiki_panel .sidebar input.active[type="button"] a, div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel input.active[type="button"] a, div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion input.active[type="button"] a, div.book-wrapper ul#booknav div.wiki-wrapper div#wiki_panel input.active[type="button"] a, div.wiki-wrapper div#wiki_panel div.book-wrapper ul#booknav input.active[type="button"] a, div.info-wrapper section.handouts div.wiki-wrapper div#wiki_panel input.active[type="button"] a, div.wiki-wrapper div#wiki_panel div.info-wrapper section.handouts input.active[type="button"] a, div.profile-wrapper section.user-info div.wiki-wrapper div#wiki_panel input.active[type="button"] a, div.wiki-wrapper div#wiki_panel div.profile-wrapper section.user-info input.active[type="button"] a, div.wiki-wrapper div#wiki_panel input.active[type="button"] a, body.askbot section.main-content div.discussion-wrapper aside div.wiki-wrapper div#wiki_panel input.active[type="button"] a, div.wiki-wrapper div#wiki_panel body.askbot section.main-content div.discussion-wrapper aside input.active[type="button"] a { + .sidebar h3.active a, div#accordion h3.active a, div.book-wrapper ul#booknav h3.active a, div.info-wrapper section.handouts h3.active a, div.profile-wrapper section.user-info h3.active a, div#wiki_panel h3.active a, body.askbot section.main-content div.discussion-wrapper aside h3.active a, .sidebar div#accordion h3.ui-accordion-header.ui-state-active a, div#accordion .sidebar h3.ui-accordion-header.ui-state-active a, div#accordion h3.ui-accordion-header.ui-state-active a, div.book-wrapper ul#booknav div#accordion h3.ui-accordion-header.ui-state-active a, div#accordion div.book-wrapper ul#booknav h3.ui-accordion-header.ui-state-active a, div.info-wrapper section.handouts div#accordion h3.ui-accordion-header.ui-state-active a, div#accordion div.info-wrapper section.handouts h3.ui-accordion-header.ui-state-active a, div.profile-wrapper section.user-info div#accordion h3.ui-accordion-header.ui-state-active a, div#accordion div.profile-wrapper section.user-info h3.ui-accordion-header.ui-state-active a, div#wiki_panel div#accordion h3.ui-accordion-header.ui-state-active a, div#accordion div#wiki_panel h3.ui-accordion-header.ui-state-active a, body.askbot section.main-content div.discussion-wrapper aside div#accordion h3.ui-accordion-header.ui-state-active a, div#accordion body.askbot section.main-content div.discussion-wrapper aside h3.ui-accordion-header.ui-state-active a, .sidebar div#accordion div#wiki_panel input.ui-accordion-header.ui-state-active[type="button"] a, div#accordion div#wiki_panel .sidebar input.ui-accordion-header.ui-state-active[type="button"] a, div#accordion div#wiki_panel input.ui-accordion-header.ui-state-active[type="button"] a, div.book-wrapper ul#booknav div#accordion div#wiki_panel input.ui-accordion-header.ui-state-active[type="button"] a, div#accordion div#wiki_panel div.book-wrapper ul#booknav input.ui-accordion-header.ui-state-active[type="button"] a, div.info-wrapper section.handouts div#accordion div#wiki_panel input.ui-accordion-header.ui-state-active[type="button"] a, div#accordion div#wiki_panel div.info-wrapper section.handouts input.ui-accordion-header.ui-state-active[type="button"] a, div.profile-wrapper section.user-info div#accordion div#wiki_panel input.ui-accordion-header.ui-state-active[type="button"] a, div#accordion div#wiki_panel div.profile-wrapper section.user-info input.ui-accordion-header.ui-state-active[type="button"] a, div#accordion div#wiki_panel input.ui-accordion-header.ui-state-active[type="button"] a, body.askbot section.main-content div.discussion-wrapper aside div#accordion div#wiki_panel input.ui-accordion-header.ui-state-active[type="button"] a, div#accordion div#wiki_panel body.askbot section.main-content div.discussion-wrapper aside input.ui-accordion-header.ui-state-active[type="button"] a, .sidebar div#wiki_panel div#accordion input.ui-accordion-header.ui-state-active[type="button"] a, div#wiki_panel div#accordion .sidebar input.ui-accordion-header.ui-state-active[type="button"] a, div#wiki_panel div#accordion input.ui-accordion-header.ui-state-active[type="button"] a, div.book-wrapper ul#booknav div#wiki_panel div#accordion input.ui-accordion-header.ui-state-active[type="button"] a, div#wiki_panel div#accordion div.book-wrapper ul#booknav input.ui-accordion-header.ui-state-active[type="button"] a, div.info-wrapper section.handouts div#wiki_panel div#accordion input.ui-accordion-header.ui-state-active[type="button"] a, div#wiki_panel div#accordion div.info-wrapper section.handouts input.ui-accordion-header.ui-state-active[type="button"] a, div.profile-wrapper section.user-info div#wiki_panel div#accordion input.ui-accordion-header.ui-state-active[type="button"] a, div#wiki_panel div#accordion div.profile-wrapper section.user-info input.ui-accordion-header.ui-state-active[type="button"] a, div#wiki_panel div#accordion input.ui-accordion-header.ui-state-active[type="button"] a, body.askbot section.main-content div.discussion-wrapper aside div#wiki_panel div#accordion input.ui-accordion-header.ui-state-active[type="button"] a, div#wiki_panel div#accordion body.askbot section.main-content div.discussion-wrapper aside input.ui-accordion-header.ui-state-active[type="button"] a, .sidebar div#wiki_panel input.active[type="button"] a, div#wiki_panel .sidebar input.active[type="button"] a, div#accordion div#wiki_panel input.active[type="button"] a, div#wiki_panel div#accordion input.active[type="button"] a, div.book-wrapper ul#booknav div#wiki_panel input.active[type="button"] a, div#wiki_panel div.book-wrapper ul#booknav input.active[type="button"] a, div.info-wrapper section.handouts div#wiki_panel input.active[type="button"] a, div#wiki_panel div.info-wrapper section.handouts input.active[type="button"] a, div.profile-wrapper section.user-info div#wiki_panel input.active[type="button"] a, div#wiki_panel div.profile-wrapper section.user-info input.active[type="button"] a, div#wiki_panel input.active[type="button"] a, body.askbot section.main-content div.discussion-wrapper aside div#wiki_panel input.active[type="button"] a, div#wiki_panel body.askbot section.main-content div.discussion-wrapper aside input.active[type="button"] a { color: #000; } -.topbar, nav.sequence-nav, div.book-wrapper section.book nav, div.wiki-wrapper section.wiki-body header, body.askbot .secondary-nav nav { +.topbar, nav.sequence-nav, div.book-wrapper section.book nav, div.wiki-wrapper section.wiki-body header { background: #F6EFD4; border-bottom: 1px solid #eddfaa; margin: -22.652px -22.652px 22.652px; @@ -304,12 +304,12 @@ h1.top-header, div.info-wrapper section.updates > h1, div.profile-wrapper sectio -ms-box-shadow: inset 0 1px 0 white, inset 1px 0 0 white; -o-box-shadow: inset 0 1px 0 white, inset 1px 0 0 white; box-shadow: inset 0 1px 0 white, inset 1px 0 0 white; } - .topbar a, nav.sequence-nav a, div.book-wrapper section.book nav a, div.wiki-wrapper section.wiki-body header a, body.askbot .secondary-nav nav a { + .topbar a, nav.sequence-nav a, div.book-wrapper section.book nav a, div.wiki-wrapper section.wiki-body header a { color: #292309; } - .topbar a:hover, nav.sequence-nav a:hover, div.book-wrapper section.book nav a:hover, div.wiki-wrapper section.wiki-body header a:hover, body.askbot .secondary-nav nav a:hover { + .topbar a:hover, nav.sequence-nav a:hover, div.book-wrapper section.book nav a:hover, div.wiki-wrapper section.wiki-body header a:hover { color: #7e691a; text-decoration: none; } - .topbar a.block-link, nav.sequence-nav a.block-link, div.book-wrapper section.book nav a.block-link, div.wiki-wrapper section.wiki-body header a.block-link, body.askbot .secondary-nav nav a.block-link, .topbar nav.sequence-nav ol a, nav.sequence-nav ol .topbar a, nav.sequence-nav ol a, div.book-wrapper section.book nav.sequence-nav ol a, div.wiki-wrapper section.wiki-body header nav.sequence-nav ol a, nav.sequence-nav ol div.wiki-wrapper section.wiki-body header a, body.askbot .secondary-nav nav.sequence-nav ol a, .topbar div.book-wrapper section.book nav a, div.book-wrapper section.book nav .topbar a, div.book-wrapper section.book nav.sequence-nav a, div.book-wrapper section.book nav a, div.wiki-wrapper section.wiki-body header div.book-wrapper section.book nav a, div.book-wrapper section.book nav div.wiki-wrapper section.wiki-body header a, body.askbot .secondary-nav div.book-wrapper section.book nav a, div.book-wrapper section.book body.askbot .secondary-nav nav a, .topbar div.wiki-wrapper section.wiki-body header a, div.wiki-wrapper section.wiki-body header .topbar a, nav.sequence-nav div.wiki-wrapper section.wiki-body header a, div.wiki-wrapper section.wiki-body header nav.sequence-nav a, div.book-wrapper section.book nav div.wiki-wrapper section.wiki-body header a, div.wiki-wrapper section.wiki-body header div.book-wrapper section.book nav a, div.wiki-wrapper section.wiki-body header a, body.askbot .secondary-nav nav div.wiki-wrapper section.wiki-body header a, div.wiki-wrapper section.wiki-body header body.askbot .secondary-nav nav a { + .topbar a.block-link, nav.sequence-nav a.block-link, div.book-wrapper section.book nav a.block-link, div.wiki-wrapper section.wiki-body header a.block-link, .topbar nav.sequence-nav ol a, nav.sequence-nav ol .topbar a, nav.sequence-nav ol a, div.book-wrapper section.book nav.sequence-nav ol a, div.wiki-wrapper section.wiki-body header nav.sequence-nav ol a, nav.sequence-nav ol div.wiki-wrapper section.wiki-body header a, .topbar div.book-wrapper section.book nav a, div.book-wrapper section.book nav .topbar a, div.book-wrapper section.book nav.sequence-nav a, div.book-wrapper section.book nav a, div.wiki-wrapper section.wiki-body header div.book-wrapper section.book nav a, div.book-wrapper section.book nav div.wiki-wrapper section.wiki-body header a, .topbar div.wiki-wrapper section.wiki-body header a, div.wiki-wrapper section.wiki-body header .topbar a, nav.sequence-nav div.wiki-wrapper section.wiki-body header a, div.wiki-wrapper section.wiki-body header nav.sequence-nav a, div.book-wrapper section.book nav div.wiki-wrapper section.wiki-body header a, div.wiki-wrapper section.wiki-body header div.book-wrapper section.book nav a, div.wiki-wrapper section.wiki-body header a { -webkit-box-shadow: inset 1px 0 0 #faf7e9; -moz-box-shadow: inset 1px 0 0 #faf7e9; -ms-box-shadow: inset 1px 0 0 #faf7e9; @@ -320,13 +320,13 @@ h1.top-header, div.info-wrapper section.updates > h1, div.profile-wrapper sectio padding: 16.989px; text-transform: uppercase; display: block; } - .topbar a.block-link:hover, nav.sequence-nav a.block-link:hover, div.book-wrapper section.book nav a.block-link:hover, div.wiki-wrapper section.wiki-body header a.block-link:hover, body.askbot .secondary-nav nav a.block-link:hover, .topbar nav.sequence-nav ol a:hover, nav.sequence-nav ol .topbar a:hover, nav.sequence-nav ol a:hover, div.book-wrapper section.book nav.sequence-nav ol a:hover, div.wiki-wrapper section.wiki-body header nav.sequence-nav ol a:hover, nav.sequence-nav ol div.wiki-wrapper section.wiki-body header a:hover, body.askbot .secondary-nav nav.sequence-nav ol a:hover, .topbar div.book-wrapper section.book nav a:hover, div.book-wrapper section.book nav .topbar a:hover, div.book-wrapper section.book nav.sequence-nav a:hover, div.book-wrapper section.book nav a:hover, div.wiki-wrapper section.wiki-body header div.book-wrapper section.book nav a:hover, div.book-wrapper section.book nav div.wiki-wrapper section.wiki-body header a:hover, body.askbot .secondary-nav div.book-wrapper section.book nav a:hover, div.book-wrapper section.book body.askbot .secondary-nav nav a:hover, .topbar div.wiki-wrapper section.wiki-body header a:hover, div.wiki-wrapper section.wiki-body header .topbar a:hover, nav.sequence-nav div.wiki-wrapper section.wiki-body header a:hover, div.wiki-wrapper section.wiki-body header nav.sequence-nav a:hover, div.book-wrapper section.book nav div.wiki-wrapper section.wiki-body header a:hover, div.wiki-wrapper section.wiki-body header div.book-wrapper section.book nav a:hover, div.wiki-wrapper section.wiki-body header a:hover, body.askbot .secondary-nav nav div.wiki-wrapper section.wiki-body header a:hover, div.wiki-wrapper section.wiki-body header body.askbot .secondary-nav nav a:hover { + .topbar a.block-link:hover, nav.sequence-nav a.block-link:hover, div.book-wrapper section.book nav a.block-link:hover, div.wiki-wrapper section.wiki-body header a.block-link:hover, .topbar nav.sequence-nav ol a:hover, nav.sequence-nav ol .topbar a:hover, nav.sequence-nav ol a:hover, div.book-wrapper section.book nav.sequence-nav ol a:hover, div.wiki-wrapper section.wiki-body header nav.sequence-nav ol a:hover, nav.sequence-nav ol div.wiki-wrapper section.wiki-body header a:hover, .topbar div.book-wrapper section.book nav a:hover, div.book-wrapper section.book nav .topbar a:hover, div.book-wrapper section.book nav.sequence-nav a:hover, div.book-wrapper section.book nav a:hover, div.wiki-wrapper section.wiki-body header div.book-wrapper section.book nav a:hover, div.book-wrapper section.book nav div.wiki-wrapper section.wiki-body header a:hover, .topbar div.wiki-wrapper section.wiki-body header a:hover, div.wiki-wrapper section.wiki-body header .topbar a:hover, nav.sequence-nav div.wiki-wrapper section.wiki-body header a:hover, div.wiki-wrapper section.wiki-body header nav.sequence-nav a:hover, div.book-wrapper section.book nav div.wiki-wrapper section.wiki-body header a:hover, div.wiki-wrapper section.wiki-body header div.book-wrapper section.book nav a:hover, div.wiki-wrapper section.wiki-body header a:hover { background: none; } :focus { outline-color: #ccc; } -h1 a, h2 a, h3 a, div.wiki-wrapper div#wiki_panel input[type="button"] a, h4 a, h5 a, h6 a { +h1 a, h2 a, h3 a, div#wiki_panel input[type="button"] a, h4 a, h5 a, h6 a { color: #000; } h1 { @@ -346,6 +346,10 @@ p { em { font-style: italic; } +img { + max-width: 100%; + height: auto; } + input[type="email"], input[type="number"], input[type="password"], input[type="search"], input[type="tel"], input[type="text"], input[type="url"], input[type="color"], input[type="date"], input[type="datetime"], input[type="datetime-local"], input[type="month"], input[type="time"], input[type="week"], textarea { -webkit-box-shadow: 0 -1px 0 white; -moz-box-shadow: 0 -1px 0 white; @@ -384,95 +388,6 @@ html { text-align: center; margin: 0; background: #f4f4f4; } - html body div.header-wrapper { - -webkit-box-shadow: inset 0 -1px 2px #732626; - -moz-box-shadow: inset 0 -1px 2px #732626; - -ms-box-shadow: inset 0 -1px 2px #732626; - -o-box-shadow: inset 0 -1px 2px #732626; - box-shadow: inset 0 -1px 2px #732626; - background: #993333; - border-bottom: 1px solid #fff; } - html body div.header-wrapper header { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - -ms-box-sizing: border-box; - -o-box-sizing: border-box; - box-sizing: border-box; - padding: 0 22.652px; } - html body div.header-wrapper header hgroup { - float: left; } - html body div.header-wrapper header hgroup h1 { - border-right: 1px solid #862d2d; - color: #391313; - font-size: 20px; - font-weight: 800; - margin: 0 22.652px 0 0; - padding: 17px 22.652px 14px 0; - text-shadow: 0 1px 0 #bf4040; - line-height: 22.652px; - display: -moz-inline-box; - -moz-box-orient: vertical; - display: inline-block; - vertical-align: baseline; - zoom: 1; - *display: inline; - *vertical-align: auto; } - html body div.header-wrapper header hgroup h2 { - display: -moz-inline-box; - -moz-box-orient: vertical; - display: inline-block; - vertical-align: baseline; - zoom: 1; - *display: inline; - *vertical-align: auto; - margin: 0 22.652px 0 0; - padding: 19px 22.652px 9px 0; - line-height: 22.652px; - border-right: 1px solid #862d2d; - -webkit-font-smoothing: antialiased; } - html body div.header-wrapper header hgroup h2 a { - color: #fff; - text-decoration: none; } - html body div.header-wrapper header hgroup h2 a:hover { - color: rgba(255, 255, 255, 0.7); } - @media screen and (max-width: 920px) { - html body div.header-wrapper header hgroup { - border-bottom: 1px solid #862d2d; - display: block; - float: none; } - html body div.header-wrapper header hgroup h1 { - float: right; - border: 0; - margin-right: 0; - padding-right: 0; } - html body div.header-wrapper header hgroup h2 { - float: left; - border: 0; - margin-right: 0; - padding-right: 0; } } - html body div.header-wrapper header nav { - float: left; - display: block; - margin: 0; - padding: 0; - text-shadow: 0 -1px 0 #732626; - -webkit-font-smoothing: antialiased; } - html body div.header-wrapper header nav ul { - display: inline-block; - padding: 19px 0 9px; - margin: 0; } - html body div.header-wrapper header nav ul li { - margin-right: 22.652px; - display: inline-block; - margin-bottom: 0; - line-height: 22.652px; } - html body div.header-wrapper header nav ul li a { - color: #fff; - text-decoration: none; } - html body div.header-wrapper header nav ul li a:hover { - color: rgba(255, 255, 255, 0.7); - background-color: none; - text-decoration: none; } html body section.main-content { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; @@ -496,37 +411,125 @@ html { box-shadow: 0 0 4px #dfdfdf; border: 1px solid #bbb; margin-top: 11.326px; } } - html body img { - max-width: 100%; - height: auto; } - html footer { + +div.header-wrapper { + -webkit-box-shadow: inset 0 -1px 2px #732626; + -moz-box-shadow: inset 0 -1px 2px #732626; + -ms-box-shadow: inset 0 -1px 2px #732626; + -o-box-shadow: inset 0 -1px 2px #732626; + box-shadow: inset 0 -1px 2px #732626; + background: #993333; + border-bottom: 1px solid #fff; } + div.header-wrapper header { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; -ms-box-sizing: border-box; -o-box-sizing: border-box; box-sizing: border-box; - color: #777; - margin-top: 22.652px; padding: 0 22.652px; } - html footer p { + div.header-wrapper header hgroup { float: left; } - html footer p a { - color: #444; } - html footer p a:link, html footer p a:visited { - color: #444; } - html footer p a:hover, html footer p a:focus { - color: #000; } - html footer ul { - float: right; } - html footer ul li { + div.header-wrapper header hgroup h1 { + border-right: 1px solid #862d2d; + color: #391313; + font-size: 20px; + font-weight: 800; + margin: 0 22.652px 0 0; + padding: 17px 22.652px 14px 0; + text-shadow: 0 1px 0 #bf4040; + line-height: 22.652px; + display: -moz-inline-box; + -moz-box-orient: vertical; display: inline-block; - margin-right: 20px; } - html footer ul li a { + vertical-align: baseline; + zoom: 1; + *display: inline; + *vertical-align: auto; } + div.header-wrapper header hgroup h2 { + display: -moz-inline-box; + -moz-box-orient: vertical; + display: inline-block; + vertical-align: baseline; + zoom: 1; + *display: inline; + *vertical-align: auto; + margin: 0 22.652px 0 0; + padding: 19px 22.652px 9px 0; + line-height: 22.652px; + border-right: 1px solid #862d2d; + -webkit-font-smoothing: antialiased; } + div.header-wrapper header hgroup h2 a { + color: #fff; + text-decoration: none; } + div.header-wrapper header hgroup h2 a:hover { + color: rgba(255, 255, 255, 0.7); } + @media screen and (max-width: 920px) { + div.header-wrapper header hgroup { + border-bottom: 1px solid #862d2d; + display: block; + float: none; } + div.header-wrapper header hgroup h1 { + float: right; + border: 0; + margin-right: 0; + padding-right: 0; } + div.header-wrapper header hgroup h2 { + float: left; + border: 0; + margin-right: 0; + padding-right: 0; } } + div.header-wrapper header nav { + float: left; + display: block; + margin: 0; + padding: 0; + text-shadow: 0 -1px 0 #732626; + -webkit-font-smoothing: antialiased; } + div.header-wrapper header nav ul { + display: inline-block; + padding: 19px 0 9px; + margin: 0; } + div.header-wrapper header nav ul li { + margin-right: 22.652px; + display: inline-block; + margin-bottom: 0; + line-height: 22.652px; } + div.header-wrapper header nav ul li a { + color: #fff; + text-decoration: none; } + div.header-wrapper header nav ul li a:hover { + color: rgba(255, 255, 255, 0.7); + background-color: none; + text-decoration: none; } + +footer { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + -ms-box-sizing: border-box; + -o-box-sizing: border-box; + box-sizing: border-box; + color: #777; + margin-top: 22.652px; + padding: 0 22.652px; } + footer p { + float: left; } + footer p a { + color: #444; } + footer p a:link, footer p a:visited { + color: #444; } + footer p a:hover, footer p a:focus { + color: #000; } + footer ul { + float: right; } + footer ul li { + display: inline-block; + margin-right: 20px; } + footer ul li a { + color: #444; } + footer ul li a:link, footer ul li a:visited { color: #444; } - html footer ul li a:link, html footer ul li a:visited { - color: #444; } - html footer ul li a:hover, html footer ul li a:focus { - color: #000; } + footer ul li a:hover, footer ul li a:focus { + color: #000; } #lean_overlay { position: fixed; @@ -765,64 +768,1494 @@ div#calculator_div { div#calculator_div dl dd { float: left; } +/* + * jQuery UI CSS Framework 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Theming/API + */ +/* Layout helpers +----------------------------------*/ +.ui-helper-hidden { + display: none; } + +.ui-helper-hidden-accessible { + position: absolute !important; + clip: rect(1px 1px 1px 1px); + clip: rect(1px, 1px, 1px, 1px); } + +.ui-helper-reset { + margin: 0; + padding: 0; + border: 0; + outline: 0; + line-height: 1.3; + text-decoration: none; + font-size: 100%; + list-style: none; } + +.ui-helper-clearfix:after { + content: "."; + display: block; + height: 0; + clear: both; + visibility: hidden; } + +.ui-helper-clearfix { + display: inline-block; } + +/* required comment for clearfix to work in Opera \*/ +* html .ui-helper-clearfix { + height: 1%; } + +.ui-helper-clearfix { + display: block; } + +/* end clearfix */ +.ui-helper-zfix { + width: 100%; + height: 100%; + top: 0; + left: 0; + position: absolute; + opacity: 0; + filter: Alpha(Opacity=0); } + +/* Interaction Cues +----------------------------------*/ +.ui-state-disabled { + cursor: default !important; } + +/* Icons +----------------------------------*/ +/* states and images */ +.ui-icon { + display: block; + text-indent: -99999px; + overflow: hidden; + background-repeat: no-repeat; } + +/* Misc visuals +----------------------------------*/ +/* Overlays */ +.ui-widget-overlay { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; } + +/* + * jQuery UI CSS Framework 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Theming/API + * + * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Helvetica,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=2px&bgColorHeader=7fbcfd&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=50&borderColorHeader=dae5c9&fcHeader=031634&iconColorHeader=031634&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=dae5c9&fcContent=031634&iconColorContent=adcc80&bgColorDefault=7fbcdf&bgTextureDefault=03_highlight_soft.png&bgImgOpacityDefault=100&borderColorDefault=dae5c9&fcDefault=7a994c&iconColorDefault=adcc80&bgColorHover=bddeff&bgTextureHover=03_highlight_soft.png&bgImgOpacityHover=25&borderColorHover=7fbcdf&fcHover=7a994c&iconColorHover=adcc80&bgColorActive=023063&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=dae5c9&fcActive=dae5c9&iconColorActive=454545&bgColorHighlight=ffffff&bgTextureHighlight=01_flat.png&bgImgOpacityHighlight=55&borderColorHighlight=cccccc&fcHighlight=444444&iconColorHighlight=adcc80&bgColorError=ffffff&bgTextureError=01_flat.png&bgImgOpacityError=55&borderColorError=fa720a&fcError=222222&iconColorError=fa720a&bgColorOverlay=eeeeee&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=80&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=60&thicknessShadow=4px&offsetTopShadow=-4px&offsetLeftShadow=-4px&cornerRadiusShadow=0px + */ +/* Component containers +----------------------------------*/ +.ui-widget { + font-family: Helvetica, Arial, sans-serif; + font-size: 1.1em; } + +.ui-widget .ui-widget { + font-size: 1em; } + +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { + font-family: Helvetica, Arial, sans-serif; + font-size: 1em; } + +.ui-widget-content { + border: 1px solid #dae5c9; + background: white url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; + color: #031634; } + +.ui-widget-content a { + color: #031634; } + +.ui-widget-header { + border: 1px solid #dae5c9; + background: #7fbcfd url(images/ui-bg_highlight-soft_50_7fbcfd_1x100.png) 50% 50% repeat-x; + color: #031634; + font-weight: bold; } + +.ui-widget-header a { + color: #031634; } + +/* Interaction states +----------------------------------*/ +.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { + border: 1px solid #dae5c9; + background: #7fbcdf url(images/ui-bg_highlight-soft_100_7fbcdf_1x100.png) 50% 50% repeat-x; + font-weight: bold; + color: #7a994c; } + +.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { + color: #7a994c; + text-decoration: none; } + +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { + border: 1px solid #7fbcdf; + background: #bddeff url(images/ui-bg_highlight-soft_25_bddeff_1x100.png) 50% 50% repeat-x; + font-weight: bold; + color: #7a994c; } + +.ui-state-hover a, .ui-state-hover a:hover { + color: #7a994c; + text-decoration: none; } + +.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { + border: 1px solid #dae5c9; + background: #023063 url(images/ui-bg_glass_65_023063_1x400.png) 50% 50% repeat-x; + font-weight: bold; + color: #dae5c9; } + +.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { + color: #dae5c9; + text-decoration: none; } + +.ui-widget :active { + outline: none; } + +/* Interaction Cues +----------------------------------*/ +.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight { + border: 1px solid #cccccc; + background: white url(images/ui-bg_flat_55_ffffff_40x100.png) 50% 50% repeat-x; + color: #444444; } + +.ui-state-highlight a, .ui-widget-content .ui-state-highlight a, .ui-widget-header .ui-state-highlight a { + color: #444444; } + +.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error { + border: 1px solid #fa720a; + background: white url(images/ui-bg_flat_55_ffffff_40x100.png) 50% 50% repeat-x; + color: #222222; } + +.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { + color: #222222; } + +.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { + color: #222222; } + +.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { + font-weight: bold; } + +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { + opacity: .7; + filter: Alpha(Opacity=70); + font-weight: normal; } + +.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { + opacity: .35; + filter: Alpha(Opacity=35); + background-image: none; } + +/* Icons +----------------------------------*/ +/* states and images */ +.ui-icon { + width: 16px; + height: 16px; + background-image: url(images/ui-icons_adcc80_256x240.png); } + +.ui-widget-content .ui-icon { + background-image: url(images/ui-icons_adcc80_256x240.png); } + +.ui-widget-header .ui-icon { + background-image: url(images/ui-icons_031634_256x240.png); } + +.ui-state-default .ui-icon { + background-image: url(images/ui-icons_adcc80_256x240.png); } + +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon { + background-image: url(images/ui-icons_adcc80_256x240.png); } + +.ui-state-active .ui-icon { + background-image: url(images/ui-icons_454545_256x240.png); } + +.ui-state-highlight .ui-icon { + background-image: url(images/ui-icons_adcc80_256x240.png); } + +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon { + background-image: url(images/ui-icons_fa720a_256x240.png); } + +/* positioning */ +.ui-icon-carat-1-n { + background-position: 0 0; } + +.ui-icon-carat-1-ne { + background-position: -16px 0; } + +.ui-icon-carat-1-e { + background-position: -32px 0; } + +.ui-icon-carat-1-se { + background-position: -48px 0; } + +.ui-icon-carat-1-s { + background-position: -64px 0; } + +.ui-icon-carat-1-sw { + background-position: -80px 0; } + +.ui-icon-carat-1-w { + background-position: -96px 0; } + +.ui-icon-carat-1-nw { + background-position: -112px 0; } + +.ui-icon-carat-2-n-s { + background-position: -128px 0; } + +.ui-icon-carat-2-e-w { + background-position: -144px 0; } + +.ui-icon-triangle-1-n { + background-position: 0 -16px; } + +.ui-icon-triangle-1-ne { + background-position: -16px -16px; } + +.ui-icon-triangle-1-e { + background-position: -32px -16px; } + +.ui-icon-triangle-1-se { + background-position: -48px -16px; } + +.ui-icon-triangle-1-s { + background-position: -64px -16px; } + +.ui-icon-triangle-1-sw { + background-position: -80px -16px; } + +.ui-icon-triangle-1-w { + background-position: -96px -16px; } + +.ui-icon-triangle-1-nw { + background-position: -112px -16px; } + +.ui-icon-triangle-2-n-s { + background-position: -128px -16px; } + +.ui-icon-triangle-2-e-w { + background-position: -144px -16px; } + +.ui-icon-arrow-1-n { + background-position: 0 -32px; } + +.ui-icon-arrow-1-ne { + background-position: -16px -32px; } + +.ui-icon-arrow-1-e { + background-position: -32px -32px; } + +.ui-icon-arrow-1-se { + background-position: -48px -32px; } + +.ui-icon-arrow-1-s { + background-position: -64px -32px; } + +.ui-icon-arrow-1-sw { + background-position: -80px -32px; } + +.ui-icon-arrow-1-w { + background-position: -96px -32px; } + +.ui-icon-arrow-1-nw { + background-position: -112px -32px; } + +.ui-icon-arrow-2-n-s { + background-position: -128px -32px; } + +.ui-icon-arrow-2-ne-sw { + background-position: -144px -32px; } + +.ui-icon-arrow-2-e-w { + background-position: -160px -32px; } + +.ui-icon-arrow-2-se-nw { + background-position: -176px -32px; } + +.ui-icon-arrowstop-1-n { + background-position: -192px -32px; } + +.ui-icon-arrowstop-1-e { + background-position: -208px -32px; } + +.ui-icon-arrowstop-1-s { + background-position: -224px -32px; } + +.ui-icon-arrowstop-1-w { + background-position: -240px -32px; } + +.ui-icon-arrowthick-1-n { + background-position: 0 -48px; } + +.ui-icon-arrowthick-1-ne { + background-position: -16px -48px; } + +.ui-icon-arrowthick-1-e { + background-position: -32px -48px; } + +.ui-icon-arrowthick-1-se { + background-position: -48px -48px; } + +.ui-icon-arrowthick-1-s { + background-position: -64px -48px; } + +.ui-icon-arrowthick-1-sw { + background-position: -80px -48px; } + +.ui-icon-arrowthick-1-w { + background-position: -96px -48px; } + +.ui-icon-arrowthick-1-nw { + background-position: -112px -48px; } + +.ui-icon-arrowthick-2-n-s { + background-position: -128px -48px; } + +.ui-icon-arrowthick-2-ne-sw { + background-position: -144px -48px; } + +.ui-icon-arrowthick-2-e-w { + background-position: -160px -48px; } + +.ui-icon-arrowthick-2-se-nw { + background-position: -176px -48px; } + +.ui-icon-arrowthickstop-1-n { + background-position: -192px -48px; } + +.ui-icon-arrowthickstop-1-e { + background-position: -208px -48px; } + +.ui-icon-arrowthickstop-1-s { + background-position: -224px -48px; } + +.ui-icon-arrowthickstop-1-w { + background-position: -240px -48px; } + +.ui-icon-arrowreturnthick-1-w { + background-position: 0 -64px; } + +.ui-icon-arrowreturnthick-1-n { + background-position: -16px -64px; } + +.ui-icon-arrowreturnthick-1-e { + background-position: -32px -64px; } + +.ui-icon-arrowreturnthick-1-s { + background-position: -48px -64px; } + +.ui-icon-arrowreturn-1-w { + background-position: -64px -64px; } + +.ui-icon-arrowreturn-1-n { + background-position: -80px -64px; } + +.ui-icon-arrowreturn-1-e { + background-position: -96px -64px; } + +.ui-icon-arrowreturn-1-s { + background-position: -112px -64px; } + +.ui-icon-arrowrefresh-1-w { + background-position: -128px -64px; } + +.ui-icon-arrowrefresh-1-n { + background-position: -144px -64px; } + +.ui-icon-arrowrefresh-1-e { + background-position: -160px -64px; } + +.ui-icon-arrowrefresh-1-s { + background-position: -176px -64px; } + +.ui-icon-arrow-4 { + background-position: 0 -80px; } + +.ui-icon-arrow-4-diag { + background-position: -16px -80px; } + +.ui-icon-extlink { + background-position: -32px -80px; } + +.ui-icon-newwin { + background-position: -48px -80px; } + +.ui-icon-refresh { + background-position: -64px -80px; } + +.ui-icon-shuffle { + background-position: -80px -80px; } + +.ui-icon-transfer-e-w { + background-position: -96px -80px; } + +.ui-icon-transferthick-e-w { + background-position: -112px -80px; } + +.ui-icon-folder-collapsed { + background-position: 0 -96px; } + +.ui-icon-folder-open { + background-position: -16px -96px; } + +.ui-icon-document { + background-position: -32px -96px; } + +.ui-icon-document-b { + background-position: -48px -96px; } + +.ui-icon-note { + background-position: -64px -96px; } + +.ui-icon-mail-closed { + background-position: -80px -96px; } + +.ui-icon-mail-open { + background-position: -96px -96px; } + +.ui-icon-suitcase { + background-position: -112px -96px; } + +.ui-icon-comment { + background-position: -128px -96px; } + +.ui-icon-person { + background-position: -144px -96px; } + +.ui-icon-print { + background-position: -160px -96px; } + +.ui-icon-trash { + background-position: -176px -96px; } + +.ui-icon-locked { + background-position: -192px -96px; } + +.ui-icon-unlocked { + background-position: -208px -96px; } + +.ui-icon-bookmark { + background-position: -224px -96px; } + +.ui-icon-tag { + background-position: -240px -96px; } + +.ui-icon-home { + background-position: 0 -112px; } + +.ui-icon-flag { + background-position: -16px -112px; } + +.ui-icon-calendar { + background-position: -32px -112px; } + +.ui-icon-cart { + background-position: -48px -112px; } + +.ui-icon-pencil { + background-position: -64px -112px; } + +.ui-icon-clock { + background-position: -80px -112px; } + +.ui-icon-disk { + background-position: -96px -112px; } + +.ui-icon-calculator { + background-position: -112px -112px; } + +.ui-icon-zoomin { + background-position: -128px -112px; } + +.ui-icon-zoomout { + background-position: -144px -112px; } + +.ui-icon-search { + background-position: -160px -112px; } + +.ui-icon-wrench { + background-position: -176px -112px; } + +.ui-icon-gear { + background-position: -192px -112px; } + +.ui-icon-heart { + background-position: -208px -112px; } + +.ui-icon-star { + background-position: -224px -112px; } + +.ui-icon-link { + background-position: -240px -112px; } + +.ui-icon-cancel { + background-position: 0 -128px; } + +.ui-icon-plus { + background-position: -16px -128px; } + +.ui-icon-plusthick { + background-position: -32px -128px; } + +.ui-icon-minus { + background-position: -48px -128px; } + +.ui-icon-minusthick { + background-position: -64px -128px; } + +.ui-icon-close { + background-position: -80px -128px; } + +.ui-icon-closethick { + background-position: -96px -128px; } + +.ui-icon-key { + background-position: -112px -128px; } + +.ui-icon-lightbulb { + background-position: -128px -128px; } + +.ui-icon-scissors { + background-position: -144px -128px; } + +.ui-icon-clipboard { + background-position: -160px -128px; } + +.ui-icon-copy { + background-position: -176px -128px; } + +.ui-icon-contact { + background-position: -192px -128px; } + +.ui-icon-image { + background-position: -208px -128px; } + +.ui-icon-video { + background-position: -224px -128px; } + +.ui-icon-script { + background-position: -240px -128px; } + +.ui-icon-alert { + background-position: 0 -144px; } + +.ui-icon-info { + background-position: -16px -144px; } + +.ui-icon-notice { + background-position: -32px -144px; } + +.ui-icon-help { + background-position: -48px -144px; } + +.ui-icon-check { + background-position: -64px -144px; } + +.ui-icon-bullet { + background-position: -80px -144px; } + +.ui-icon-radio-off { + background-position: -96px -144px; } + +.ui-icon-radio-on { + background-position: -112px -144px; } + +.ui-icon-pin-w { + background-position: -128px -144px; } + +.ui-icon-pin-s { + background-position: -144px -144px; } + +.ui-icon-play { + background-position: 0 -160px; } + +.ui-icon-pause { + background-position: -16px -160px; } + +.ui-icon-seek-next { + background-position: -32px -160px; } + +.ui-icon-seek-prev { + background-position: -48px -160px; } + +.ui-icon-seek-end { + background-position: -64px -160px; } + +.ui-icon-seek-start { + background-position: -80px -160px; } + +/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ +.ui-icon-seek-first { + background-position: -80px -160px; } + +.ui-icon-stop { + background-position: -96px -160px; } + +.ui-icon-eject { + background-position: -112px -160px; } + +.ui-icon-volume-off { + background-position: -128px -160px; } + +.ui-icon-volume-on { + background-position: -144px -160px; } + +.ui-icon-power { + background-position: 0 -176px; } + +.ui-icon-signal-diag { + background-position: -16px -176px; } + +.ui-icon-signal { + background-position: -32px -176px; } + +.ui-icon-battery-0 { + background-position: -48px -176px; } + +.ui-icon-battery-1 { + background-position: -64px -176px; } + +.ui-icon-battery-2 { + background-position: -80px -176px; } + +.ui-icon-battery-3 { + background-position: -96px -176px; } + +.ui-icon-circle-plus { + background-position: 0 -192px; } + +.ui-icon-circle-minus { + background-position: -16px -192px; } + +.ui-icon-circle-close { + background-position: -32px -192px; } + +.ui-icon-circle-triangle-e { + background-position: -48px -192px; } + +.ui-icon-circle-triangle-s { + background-position: -64px -192px; } + +.ui-icon-circle-triangle-w { + background-position: -80px -192px; } + +.ui-icon-circle-triangle-n { + background-position: -96px -192px; } + +.ui-icon-circle-arrow-e { + background-position: -112px -192px; } + +.ui-icon-circle-arrow-s { + background-position: -128px -192px; } + +.ui-icon-circle-arrow-w { + background-position: -144px -192px; } + +.ui-icon-circle-arrow-n { + background-position: -160px -192px; } + +.ui-icon-circle-zoomin { + background-position: -176px -192px; } + +.ui-icon-circle-zoomout { + background-position: -192px -192px; } + +.ui-icon-circle-check { + background-position: -208px -192px; } + +.ui-icon-circlesmall-plus { + background-position: 0 -208px; } + +.ui-icon-circlesmall-minus { + background-position: -16px -208px; } + +.ui-icon-circlesmall-close { + background-position: -32px -208px; } + +.ui-icon-squaresmall-plus { + background-position: -48px -208px; } + +.ui-icon-squaresmall-minus { + background-position: -64px -208px; } + +.ui-icon-squaresmall-close { + background-position: -80px -208px; } + +.ui-icon-grip-dotted-vertical { + background-position: 0 -224px; } + +.ui-icon-grip-dotted-horizontal { + background-position: -16px -224px; } + +.ui-icon-grip-solid-vertical { + background-position: -32px -224px; } + +.ui-icon-grip-solid-horizontal { + background-position: -48px -224px; } + +.ui-icon-gripsmall-diagonal-se { + background-position: -64px -224px; } + +.ui-icon-grip-diagonal-se { + background-position: -80px -224px; } + +/* Misc visuals +----------------------------------*/ +/* Corner radius */ +.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { + -moz-border-radius-topleft: 2px; + -webkit-border-top-left-radius: 2px; + -khtml-border-top-left-radius: 2px; + border-top-left-radius: 2px; } + +.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { + -moz-border-radius-topright: 2px; + -webkit-border-top-right-radius: 2px; + -khtml-border-top-right-radius: 2px; + border-top-right-radius: 2px; } + +.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { + -moz-border-radius-bottomleft: 2px; + -webkit-border-bottom-left-radius: 2px; + -khtml-border-bottom-left-radius: 2px; + border-bottom-left-radius: 2px; } + +.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { + -moz-border-radius-bottomright: 2px; + -webkit-border-bottom-right-radius: 2px; + -khtml-border-bottom-right-radius: 2px; + border-bottom-right-radius: 2px; } + +/* Overlays */ +.ui-widget-overlay { + background: #eeeeee url(images/ui-bg_flat_0_eeeeee_40x100.png) 50% 50% repeat-x; + opacity: .80; + filter: Alpha(Opacity=80); } + +.ui-widget-shadow { + margin: -4px 0 0 -4px; + padding: 4px; + background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; + opacity: .60; + filter: Alpha(Opacity=60); + -moz-border-radius: 0px; + -khtml-border-radius: 0px; + -webkit-border-radius: 0px; + border-radius: 0px; } + + /* +* jQuery UI Resizable 1.8.16 +* +* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) +* Dual licensed under the MIT or GPL Version 2 licenses. +* http://jquery.org/license +* +* http://docs.jquery.com/UI/Resizable#theming +*/ +.ui-resizable { + position: relative; } + +.ui-resizable-handle { + position: absolute; + font-size: 0.1px; + z-index: 99999; + display: block; } + +.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { + display: none; } + +.ui-resizable-n { + cursor: n-resize; + height: 7px; + width: 100%; + top: -5px; + left: 0; } + +.ui-resizable-s { + cursor: s-resize; + height: 7px; + width: 100%; + bottom: -5px; + left: 0; } + +.ui-resizable-e { + cursor: e-resize; + width: 7px; + right: -5px; + top: 0; + height: 100%; } + +.ui-resizable-w { + cursor: w-resize; + width: 7px; + left: -5px; + top: 0; + height: 100%; } + +.ui-resizable-se { + cursor: se-resize; + width: 12px; + height: 12px; + right: 1px; + bottom: 1px; } + +.ui-resizable-sw { + cursor: sw-resize; + width: 9px; + height: 9px; + left: -5px; + bottom: -5px; } + +.ui-resizable-nw { + cursor: nw-resize; + width: 9px; + height: 9px; + left: -5px; + top: -5px; } + +.ui-resizable-ne { + cursor: ne-resize; + width: 9px; + height: 9px; + right: -5px; + top: -5px; } + + /* +* jQuery UI Selectable 1.8.16 +* +* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) +* Dual licensed under the MIT or GPL Version 2 licenses. +* http://jquery.org/license +* +* http://docs.jquery.com/UI/Selectable#theming +*/ +.ui-selectable-helper { + position: absolute; + z-index: 100; + border: 1px dotted black; } + +/* + * jQuery UI Accordion 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Accordion#theming + */ +/* IE/Win - Fix animation bug - #4615 */ +.ui-accordion { + width: 100%; } + +.ui-accordion .ui-accordion-header { + cursor: pointer; + position: relative; + margin-top: 1px; + zoom: 1; } + +.ui-accordion .ui-accordion-li-fix { + display: inline; } + +.ui-accordion .ui-accordion-header-active { + border-bottom: 0 !important; } + +.ui-accordion .ui-accordion-header a { + display: block; + font-size: 1em; + padding: .5em .5em .5em .7em; } + +.ui-accordion-icons .ui-accordion-header a { + padding-left: 2.2em; } + +.ui-accordion .ui-accordion-header .ui-icon { + position: absolute; + left: .5em; + top: 50%; + margin-top: -8px; } + +.ui-accordion .ui-accordion-content { + padding: 1em 2.2em; + border-top: 0; + margin-top: -2px; + position: relative; + top: 1px; + margin-bottom: 2px; + overflow: auto; + display: none; + zoom: 1; } + +.ui-accordion .ui-accordion-content-active { + display: block; } + +/* + * jQuery UI Autocomplete 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Autocomplete#theming + */ +.ui-autocomplete { + position: absolute; + cursor: default; } + +/* workarounds */ +* html .ui-autocomplete { + width: 1px; } + +/* without this, the menu expands to 100% in IE6 */ +/* + * jQuery UI Menu 1.8.16 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Menu#theming + */ +.ui-menu { + list-style: none; + padding: 2px; + margin: 0; + display: block; + float: left; } + +.ui-menu .ui-menu { + margin-top: -3px; } + +.ui-menu .ui-menu-item { + margin: 0; + padding: 0; + zoom: 1; + float: left; + clear: left; + width: 100%; } + +.ui-menu .ui-menu-item a { + text-decoration: none; + display: block; + padding: .2em .4em; + line-height: 1.5; + zoom: 1; } + +.ui-menu .ui-menu-item a.ui-state-hover, +.ui-menu .ui-menu-item a.ui-state-active { + font-weight: normal; + margin: -1px; } + +/* + * jQuery UI Button 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Button#theming + */ +.ui-button { + display: inline-block; + position: relative; + padding: 0; + margin-right: .1em; + text-decoration: none !important; + cursor: pointer; + text-align: center; + zoom: 1; + overflow: visible; } + +/* the overflow property removes extra width in IE */ +.ui-button-icon-only { + width: 2.2em; } + +/* to make room for the icon, a width needs to be set here */ +button.ui-button-icon-only { + width: 2.4em; } + +/* button elements seem to need a little more width */ +.ui-button-icons-only { + width: 3.4em; } + +button.ui-button-icons-only { + width: 3.7em; } + +/*button text element */ +.ui-button .ui-button-text { + display: block; + line-height: 1.4; } + +.ui-button-text-only .ui-button-text { + padding: .4em 1em; } + +.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { + padding: .4em; + text-indent: -9999999px; } + +.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { + padding: .4em 1em .4em 2.1em; } + +.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { + padding: .4em 2.1em .4em 1em; } + +.ui-button-text-icons .ui-button-text { + padding-left: 2.1em; + padding-right: 2.1em; } + +/* no icon support for input elements, provide padding by default */ +input.ui-button { + padding: .4em 1em; } + +/*button icon element(s) */ +.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { + position: absolute; + top: 50%; + margin-top: -8px; } + +.ui-button-icon-only .ui-icon { + left: 50%; + margin-left: -8px; } + +.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { + left: .5em; } + +.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { + right: .5em; } + +.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { + right: .5em; } + +/*button sets*/ +.ui-buttonset { + margin-right: 7px; } + +.ui-buttonset .ui-button { + margin-left: 0; + margin-right: -0.3em; } + +/* workarounds */ +button.ui-button::-moz-focus-inner { + border: 0; + padding: 0; } + +/* reset extra padding in Firefox */ +/* + * jQuery UI Dialog 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Dialog#theming + */ +.ui-dialog { + position: absolute; + padding: .2em; + width: 300px; + overflow: hidden; } + +.ui-dialog .ui-dialog-titlebar { + padding: .4em 1em; + position: relative; } + +.ui-dialog .ui-dialog-title { + float: left; + margin: .1em 16px .1em 0; } + +.ui-dialog .ui-dialog-titlebar-close { + position: absolute; + right: .3em; + top: 50%; + width: 19px; + margin: -10px 0 0 0; + padding: 1px; + height: 18px; } + +.ui-dialog .ui-dialog-titlebar-close span { + display: block; + margin: 1px; } + +.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { + padding: 0; } + +.ui-dialog .ui-dialog-content { + position: relative; + border: 0; + padding: .5em 1em; + background: none; + overflow: auto; + zoom: 1; } + +.ui-dialog .ui-dialog-buttonpane { + text-align: left; + border-width: 1px 0 0 0; + background-image: none; + margin: .5em 0 0 0; + padding: .3em 1em .5em .4em; } + +.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { + float: right; } + +.ui-dialog .ui-dialog-buttonpane button { + margin: .5em .4em .5em 0; + cursor: pointer; } + +.ui-dialog .ui-resizable-se { + width: 14px; + height: 14px; + right: 3px; + bottom: 3px; } + +.ui-draggable .ui-dialog-titlebar { + cursor: move; } + +/* + * jQuery UI Slider 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Slider#theming + */ +.ui-slider { + position: relative; + text-align: left; } + +.ui-slider .ui-slider-handle { + position: absolute; + z-index: 2; + width: 1.2em; + height: 1.2em; + cursor: default; } + +.ui-slider .ui-slider-range { + position: absolute; + z-index: 1; + font-size: .7em; + display: block; + border: 0; + background-position: 0 0; } + +.ui-slider-horizontal { + height: .8em; } + +.ui-slider-horizontal .ui-slider-handle { + top: -0.3em; + margin-left: -0.6em; } + +.ui-slider-horizontal .ui-slider-range { + top: 0; + height: 100%; } + +.ui-slider-horizontal .ui-slider-range-min { + left: 0; } + +.ui-slider-horizontal .ui-slider-range-max { + right: 0; } + +.ui-slider-vertical { + width: .8em; + height: 100px; } + +.ui-slider-vertical .ui-slider-handle { + left: -0.3em; + margin-left: 0; + margin-bottom: -0.6em; } + +.ui-slider-vertical .ui-slider-range { + left: 0; + width: 100%; } + +.ui-slider-vertical .ui-slider-range-min { + bottom: 0; } + +.ui-slider-vertical .ui-slider-range-max { + top: 0; } + + /* +* jQuery UI Tabs 1.8.16 +* +* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) +* Dual licensed under the MIT or GPL Version 2 licenses. +* http://jquery.org/license +* +* http://docs.jquery.com/UI/Tabs#theming +*/ +.ui-tabs { + position: relative; + padding: .2em; + zoom: 1; } + +/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ +.ui-tabs .ui-tabs-nav { + margin: 0; + padding: .2em .2em 0; } + +.ui-tabs .ui-tabs-nav li { + list-style: none; + float: left; + position: relative; + top: 1px; + margin: 0 .2em 1px 0; + border-bottom: 0 !important; + padding: 0; + white-space: nowrap; } + +.ui-tabs .ui-tabs-nav li a { + float: left; + padding: .5em 1em; + text-decoration: none; } + +.ui-tabs .ui-tabs-nav li.ui-tabs-selected { + margin-bottom: 0; + padding-bottom: 1px; } + +.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { + cursor: text; } + +.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { + cursor: pointer; } + +/* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ +.ui-tabs .ui-tabs-panel { + display: block; + border-width: 0; + padding: 1em 1.4em; + background: none; } + +.ui-tabs .ui-tabs-hide { + display: none !important; } + +/* + * jQuery UI Datepicker 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Datepicker#theming + */ +.ui-datepicker { + width: 17em; + padding: .2em .2em 0; + display: none; } + +.ui-datepicker .ui-datepicker-header { + position: relative; + padding: .2em 0; } + +.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { + position: absolute; + top: 2px; + width: 1.8em; + height: 1.8em; } + +.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { + top: 1px; } + +.ui-datepicker .ui-datepicker-prev { + left: 2px; } + +.ui-datepicker .ui-datepicker-next { + right: 2px; } + +.ui-datepicker .ui-datepicker-prev-hover { + left: 1px; } + +.ui-datepicker .ui-datepicker-next-hover { + right: 1px; } + +.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { + display: block; + position: absolute; + left: 50%; + margin-left: -8px; + top: 50%; + margin-top: -8px; } + +.ui-datepicker .ui-datepicker-title { + margin: 0 2.3em; + line-height: 1.8em; + text-align: center; } + +.ui-datepicker .ui-datepicker-title select { + font-size: 1em; + margin: 1px 0; } + +.ui-datepicker select.ui-datepicker-month-year { + width: 100%; } + +.ui-datepicker select.ui-datepicker-month, +.ui-datepicker select.ui-datepicker-year { + width: 49%; } + +.ui-datepicker table { + width: 100%; + font-size: .9em; + border-collapse: collapse; + margin: 0 0 .4em; } + +.ui-datepicker th { + padding: .7em .3em; + text-align: center; + font-weight: bold; + border: 0; } + +.ui-datepicker td { + border: 0; + padding: 1px; } + +.ui-datepicker td span, .ui-datepicker td a { + display: block; + padding: .2em; + text-align: right; + text-decoration: none; } + +.ui-datepicker .ui-datepicker-buttonpane { + background-image: none; + margin: .7em 0 0 0; + padding: 0 .2em; + border-left: 0; + border-right: 0; + border-bottom: 0; } + +.ui-datepicker .ui-datepicker-buttonpane button { + float: right; + margin: .5em .2em .4em; + cursor: pointer; + padding: .2em .6em .3em .6em; + width: auto; + overflow: visible; } + +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { + float: left; } + +/* with multiple calendars */ +.ui-datepicker.ui-datepicker-multi { + width: auto; } + +.ui-datepicker-multi .ui-datepicker-group { + float: left; } + +.ui-datepicker-multi .ui-datepicker-group table { + width: 95%; + margin: 0 auto .4em; } + +.ui-datepicker-multi-2 .ui-datepicker-group { + width: 50%; } + +.ui-datepicker-multi-3 .ui-datepicker-group { + width: 33.3%; } + +.ui-datepicker-multi-4 .ui-datepicker-group { + width: 25%; } + +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { + border-left-width: 0; } + +.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { + border-left-width: 0; } + +.ui-datepicker-multi .ui-datepicker-buttonpane { + clear: left; } + +.ui-datepicker-row-break { + clear: both; + width: 100%; + font-size: 0em; } + +/* RTL support */ +.ui-datepicker-rtl { + direction: rtl; } + +.ui-datepicker-rtl .ui-datepicker-prev { + right: 2px; + left: auto; } + +.ui-datepicker-rtl .ui-datepicker-next { + left: 2px; + right: auto; } + +.ui-datepicker-rtl .ui-datepicker-prev:hover { + right: 1px; + left: auto; } + +.ui-datepicker-rtl .ui-datepicker-next:hover { + left: 1px; + right: auto; } + +.ui-datepicker-rtl .ui-datepicker-buttonpane { + clear: right; } + +.ui-datepicker-rtl .ui-datepicker-buttonpane button { + float: left; } + +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { + float: right; } + +.ui-datepicker-rtl .ui-datepicker-group { + float: right; } + +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { + border-right-width: 0; + border-left-width: 1px; } + +.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { + border-right-width: 0; + border-left-width: 1px; } + +/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */ +.ui-datepicker-cover { + display: none; + /*sorry for IE5*/ + display/**/: block; + /*sorry for IE5*/ + position: absolute; + /*must have*/ + z-index: -1; + /*must have*/ + filter: mask(); + /*must have*/ + top: -4px; + /*must have*/ + left: -4px; + /*must have*/ + width: 200px; + /*must have*/ + height: 200px; + /*must have*/ } + +/* +* jQuery UI Progressbar 1.8.16 +* +* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) +* Dual licensed under the MIT or GPL Version 2 licenses. +* http://jquery.org/license +* +* http://docs.jquery.com/UI/Progressbar#theming +*/ +.ui-progressbar { + height: 2em; + text-align: left; } + +.ui-progressbar .ui-progressbar-value { + margin: -1px; + height: 100%; } + div.course-wrapper ul, div.course-wrapper ol { list-style: none; } -div.course-wrapper div#accordion div#open_close_accordion { - position: absolute; - right: 0px; - width: 20px; - height: 20px; - background: #ccc; - border: 1px solid black; - right: -22px; - top: 5px; } -div.course-wrapper div#accordion h3, div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel input[type="button"], div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion input[type="button"] { - overflow: hidden; - margin: 0; } - div.course-wrapper div#accordion h3:last-child, div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel input[type="button"]:last-child, div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion input[type="button"]:last-child { - -webkit-box-shadow: none; - -moz-box-shadow: none; - -ms-box-shadow: none; - -o-box-shadow: none; - box-shadow: none; } - div.course-wrapper div#accordion h3.ui-accordion-header, div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel input.ui-accordion-header[type="button"], div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion input.ui-accordion-header[type="button"] { - color: #000; } - div.course-wrapper div#accordion h3.ui-accordion-header a, div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel input.ui-accordion-header[type="button"] a, div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion input.ui-accordion-header[type="button"] a { - font-size: 14px; - color: #4d4d4d; } - div.course-wrapper div#accordion h3.ui-accordion-header.ui-state-hover, div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel input.ui-accordion-header.ui-state-hover[type="button"], div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion input.ui-accordion-header.ui-state-hover[type="button"] { - border: none; - border-bottom: 1px solid #d3d3d3; } -div.course-wrapper div#accordion ul.ui-accordion-content { - -webkit-border-radius: 0; - -moz-border-radius: 0; - -ms-border-radius: 0; - -o-border-radius: 0; - border-radius: 0; - -webkit-box-shadow: inset -1px 0 0 #e6e6e6; - -moz-box-shadow: inset -1px 0 0 #e6e6e6; - -ms-box-shadow: inset -1px 0 0 #e6e6e6; - -o-box-shadow: inset -1px 0 0 #e6e6e6; - box-shadow: inset -1px 0 0 #e6e6e6; - background: #d6d6d6; - border: none; - border-bottom: 1px solid #c3c3c3; - font-size: 12px; - margin: 0; - overflow: hidden; } - div.course-wrapper div#accordion ul.ui-accordion-content li.active, div.course-wrapper div#accordion ul.ui-accordion-content nav.sequence-nav ol li.seq_video_active, nav.sequence-nav ol div.course-wrapper div#accordion ul.ui-accordion-content li.seq_video_active, div.course-wrapper div#accordion ul.ui-accordion-content nav.sequence-nav ol li.seq_other_active, nav.sequence-nav ol div.course-wrapper div#accordion ul.ui-accordion-content li.seq_other_active, div.course-wrapper div#accordion ul.ui-accordion-content nav.sequence-nav ol li.seq_vertical_active, nav.sequence-nav ol div.course-wrapper div#accordion ul.ui-accordion-content li.seq_vertical_active, div.course-wrapper div#accordion ul.ui-accordion-content nav.sequence-nav ol li.seq_problem_active, nav.sequence-nav ol div.course-wrapper div#accordion ul.ui-accordion-content li.seq_problem_active { - font-weight: bold; } - div.course-wrapper div#accordion ul.ui-accordion-content li a { - text-decoration: none; - margin-bottom: 11.326px; - display: block; - color: #000; } - div.course-wrapper div#accordion ul.ui-accordion-content li a:hover { - color: #666; } - div.course-wrapper div#accordion ul.ui-accordion-content li a p { - margin-bottom: 0; } - div.course-wrapper div#accordion ul.ui-accordion-content li a p.subtitle { - color: #666; } div.course-wrapper section.course-content p { margin-bottom: 22.652px; } div.course-wrapper section.course-content p:empty { @@ -924,6 +2357,63 @@ div.course-wrapper section.course-content ol.vert-mod > li { margin-bottom: 0; padding-bottom: 0; } +div#accordion div#open_close_accordion { + position: absolute; + right: 0px; + width: 20px; + height: 20px; + background: #ccc; + border: 1px solid black; + right: -22px; + top: 5px; } +div#accordion h3, div#accordion div#wiki_panel input[type="button"], div#wiki_panel div#accordion input[type="button"] { + overflow: hidden; + margin: 0; } + div#accordion h3:last-child, div#accordion div#wiki_panel input[type="button"]:last-child, div#wiki_panel div#accordion input[type="button"]:last-child { + -webkit-box-shadow: none; + -moz-box-shadow: none; + -ms-box-shadow: none; + -o-box-shadow: none; + box-shadow: none; } + div#accordion h3.ui-accordion-header, div#accordion div#wiki_panel input.ui-accordion-header[type="button"], div#wiki_panel div#accordion input.ui-accordion-header[type="button"] { + color: #000; } + div#accordion h3.ui-accordion-header a, div#accordion div#wiki_panel input.ui-accordion-header[type="button"] a, div#wiki_panel div#accordion input.ui-accordion-header[type="button"] a { + font-size: 14px; + color: #4d4d4d; } + div#accordion h3.ui-accordion-header.ui-state-hover, div#accordion div#wiki_panel input.ui-accordion-header.ui-state-hover[type="button"], div#wiki_panel div#accordion input.ui-accordion-header.ui-state-hover[type="button"] { + border: none; + border-bottom: 1px solid #d3d3d3; } +div#accordion ul.ui-accordion-content { + -webkit-border-radius: 0; + -moz-border-radius: 0; + -ms-border-radius: 0; + -o-border-radius: 0; + border-radius: 0; + -webkit-box-shadow: inset -1px 0 0 #e6e6e6; + -moz-box-shadow: inset -1px 0 0 #e6e6e6; + -ms-box-shadow: inset -1px 0 0 #e6e6e6; + -o-box-shadow: inset -1px 0 0 #e6e6e6; + box-shadow: inset -1px 0 0 #e6e6e6; + background: #d6d6d6; + border: none; + border-bottom: 1px solid #c3c3c3; + font-size: 12px; + margin: 0; + overflow: hidden; } + div#accordion ul.ui-accordion-content li.active, div#accordion ul.ui-accordion-content nav.sequence-nav ol li.seq_video_active, nav.sequence-nav ol div#accordion ul.ui-accordion-content li.seq_video_active, div#accordion ul.ui-accordion-content nav.sequence-nav ol li.seq_other_active, nav.sequence-nav ol div#accordion ul.ui-accordion-content li.seq_other_active, div#accordion ul.ui-accordion-content nav.sequence-nav ol li.seq_vertical_active, nav.sequence-nav ol div#accordion ul.ui-accordion-content li.seq_vertical_active, div#accordion ul.ui-accordion-content nav.sequence-nav ol li.seq_problem_active, nav.sequence-nav ol div#accordion ul.ui-accordion-content li.seq_problem_active { + font-weight: bold; } + div#accordion ul.ui-accordion-content li a { + text-decoration: none; + margin-bottom: 11.326px; + display: block; + color: #000; } + div#accordion ul.ui-accordion-content li a:hover { + color: #666; } + div#accordion ul.ui-accordion-content li a p { + margin-bottom: 0; } + div#accordion ul.ui-accordion-content li a p.subtitle { + color: #666; } + section.course-content div.video-wrapper { float: left; width: 65.761%; @@ -1082,7 +2572,7 @@ nav.sequence-nav { border-color: #ddd7be; } nav.sequence-nav ol .visited:hover, nav.sequence-nav ol li.seq_video_visited:hover, nav.sequence-nav ol li.seq_other_visited:hover, nav.sequence-nav ol li.seq_vertical_visited:hover, nav.sequence-nav ol li.seq_problem_visited:hover { background-color: #F6EFD4; } - nav.sequence-nav ol .active, nav.sequence-nav ol div.course-wrapper div#accordion h3.ui-accordion-header.ui-state-active, div.course-wrapper div#accordion nav.sequence-nav ol h3.ui-accordion-header.ui-state-active, nav.sequence-nav ol div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel input.ui-accordion-header.ui-state-active[type="button"], div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel nav.sequence-nav ol input.ui-accordion-header.ui-state-active[type="button"], nav.sequence-nav ol div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion input.ui-accordion-header.ui-state-active[type="button"], div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion nav.sequence-nav ol input.ui-accordion-header.ui-state-active[type="button"], nav.sequence-nav ol li.seq_video_active, nav.sequence-nav ol li.seq_other_active, nav.sequence-nav ol li.seq_vertical_active, nav.sequence-nav ol li.seq_problem_active { + nav.sequence-nav ol .active, nav.sequence-nav ol div#accordion h3.ui-accordion-header.ui-state-active, div#accordion nav.sequence-nav ol h3.ui-accordion-header.ui-state-active, nav.sequence-nav ol div#accordion div#wiki_panel input.ui-accordion-header.ui-state-active[type="button"], div#accordion div#wiki_panel nav.sequence-nav ol input.ui-accordion-header.ui-state-active[type="button"], nav.sequence-nav ol div#wiki_panel div#accordion input.ui-accordion-header.ui-state-active[type="button"], div#wiki_panel div#accordion nav.sequence-nav ol input.ui-accordion-header.ui-state-active[type="button"], nav.sequence-nav ol li.seq_video_active, nav.sequence-nav ol li.seq_other_active, nav.sequence-nav ol li.seq_vertical_active, nav.sequence-nav ol li.seq_problem_active { -webkit-box-shadow: 0 1px 0 white; -moz-box-shadow: 0 1px 0 white; -ms-box-shadow: 0 1px 0 white; @@ -1090,7 +2580,7 @@ nav.sequence-nav { box-shadow: 0 1px 0 white; background-color: #fff; background-repeat: no-repeat; } - nav.sequence-nav ol .active:hover, nav.sequence-nav ol div.course-wrapper div#accordion h3.ui-accordion-header.ui-state-active:hover, div.course-wrapper div#accordion nav.sequence-nav ol h3.ui-accordion-header.ui-state-active:hover, nav.sequence-nav ol div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel input.ui-accordion-header.ui-state-active[type="button"]:hover, div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel nav.sequence-nav ol input.ui-accordion-header.ui-state-active[type="button"]:hover, nav.sequence-nav ol div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion input.ui-accordion-header.ui-state-active[type="button"]:hover, div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion nav.sequence-nav ol input.ui-accordion-header.ui-state-active[type="button"]:hover, nav.sequence-nav ol li.seq_video_active:hover, nav.sequence-nav ol li.seq_other_active:hover, nav.sequence-nav ol li.seq_vertical_active:hover, nav.sequence-nav ol li.seq_problem_active:hover { + nav.sequence-nav ol .active:hover, nav.sequence-nav ol div#accordion h3.ui-accordion-header.ui-state-active:hover, div#accordion nav.sequence-nav ol h3.ui-accordion-header.ui-state-active:hover, nav.sequence-nav ol div#accordion div#wiki_panel input.ui-accordion-header.ui-state-active[type="button"]:hover, div#accordion div#wiki_panel nav.sequence-nav ol input.ui-accordion-header.ui-state-active[type="button"]:hover, nav.sequence-nav ol div#wiki_panel div#accordion input.ui-accordion-header.ui-state-active[type="button"]:hover, div#wiki_panel div#accordion nav.sequence-nav ol input.ui-accordion-header.ui-state-active[type="button"]:hover, nav.sequence-nav ol li.seq_video_active:hover, nav.sequence-nav ol li.seq_other_active:hover, nav.sequence-nav ol li.seq_vertical_active:hover, nav.sequence-nav ol li.seq_problem_active:hover { background-color: #fff; } nav.sequence-nav ol li { -webkit-box-shadow: 1px 0 0 white; @@ -1366,7 +2856,7 @@ div.profile-wrapper { div.profile-wrapper section.course-info ol > li div.scores { float: left; width: 77.174%; } - div.profile-wrapper section.course-info ol > li div.scores h3, div.profile-wrapper section.course-info ol > li div.scores div.wiki-wrapper div#wiki_panel input[type="button"], div.wiki-wrapper div#wiki_panel div.profile-wrapper section.course-info ol > li div.scores input[type="button"] { + div.profile-wrapper section.course-info ol > li div.scores h3, div.profile-wrapper section.course-info ol > li div.scores div#wiki_panel input[type="button"], div#wiki_panel div.profile-wrapper section.course-info ol > li div.scores input[type="button"] { color: #666; } div.profile-wrapper section.course-info ol > li div.scores ul { list-style: none; } @@ -1379,7 +2869,7 @@ section.wiki-body div#wiki_article blockquote, section.wiki-body div#wiki_article body, section.wiki-body div#wiki_article dd, section.wiki-body div#wiki_article div, section.wiki-body div#wiki_article dl, section.wiki-body div#wiki_article dt, section.wiki-body div#wiki_article fieldset, section.wiki-body div#wiki_article form, section.wiki-body div#wiki_article frame, section.wiki-body div#wiki_article frameset, -section.wiki-body div#wiki_article h1, section.wiki-body div#wiki_article h2, section.wiki-body div#wiki_article h3, section.wiki-body div#wiki_article div.wiki-wrapper div#wiki_panel input[type="button"], div.wiki-wrapper div#wiki_panel section.wiki-body div#wiki_article input[type="button"], section.wiki-body div#wiki_article h4, +section.wiki-body div#wiki_article h1, section.wiki-body div#wiki_article h2, section.wiki-body div#wiki_article h3, section.wiki-body div#wiki_article div#wiki_panel input[type="button"], div#wiki_panel section.wiki-body div#wiki_article input[type="button"], section.wiki-body div#wiki_article h4, section.wiki-body div#wiki_article h5, section.wiki-body div#wiki_article h6, section.wiki-body div#wiki_article noframes, section.wiki-body div#wiki_article ol, section.wiki-body div#wiki_article p, section.wiki-body div#wiki_article ul, section.wiki-body div#wiki_article center, section.wiki-body div#wiki_article dir, section.wiki-body div#wiki_article hr, section.wiki-body div#wiki_article menu, section.wiki-body div#wiki_article pre { @@ -1421,7 +2911,7 @@ section.wiki-body div#wiki_article h2 { font-size: 2em; margin: .75em 0; letter-spacing: 0px; } -section.wiki-body div#wiki_article h3, section.wiki-body div#wiki_article div.wiki-wrapper div#wiki_panel input[type="button"], div.wiki-wrapper div#wiki_panel section.wiki-body div#wiki_article input[type="button"] { +section.wiki-body div#wiki_article h3, section.wiki-body div#wiki_article div#wiki_panel input[type="button"], div#wiki_panel section.wiki-body div#wiki_article input[type="button"] { font-size: 1.75em; margin: .83em 0; } section.wiki-body div#wiki_article h4 { @@ -1438,7 +2928,7 @@ section.wiki-body div#wiki_article h5 { section.wiki-body div#wiki_article h6 { font-size: 1em; margin: 1.67em 0; } -section.wiki-body div#wiki_article h1, section.wiki-body div#wiki_article h2, section.wiki-body div#wiki_article h3, section.wiki-body div#wiki_article div.wiki-wrapper div#wiki_panel input[type="button"], div.wiki-wrapper div#wiki_panel section.wiki-body div#wiki_article input[type="button"], section.wiki-body div#wiki_article h4, +section.wiki-body div#wiki_article h1, section.wiki-body div#wiki_article h2, section.wiki-body div#wiki_article h3, section.wiki-body div#wiki_article div#wiki_panel input[type="button"], div#wiki_panel section.wiki-body div#wiki_article input[type="button"], section.wiki-body div#wiki_article h4, section.wiki-body div#wiki_article h5, section.wiki-body div#wiki_article h6, section.wiki-body div#wiki_article b, section.wiki-body div#wiki_article strong { font-weight: bolder; } @@ -1495,6 +2985,75 @@ section.wiki-body div#wiki_article br:before { section.wiki-body div#wiki_article center { text-align: center; } +div#wiki_panel { + overflow: auto; } + div#wiki_panel input[type="button"] { + -webkit-transition-property: all; + -moz-transition-property: all; + -ms-transition-property: all; + -o-transition-property: all; + transition-property: all; + -webkit-transition-duration: 0.15s; + -moz-transition-duration: 0.15s; + -ms-transition-duration: 0.15s; + -o-transition-duration: 0.15s; + transition-duration: 0.15s; + -webkit-transition-timing-function: ease-out; + -moz-transition-timing-function: ease-out; + -ms-transition-timing-function: ease-out; + -o-transition-timing-function: ease-out; + transition-timing-function: ease-out; + -webkit-transition-delay: 0; + -moz-transition-delay: 0; + -ms-transition-delay: 0; + -o-transition-delay: 0; + transition-delay: 0; + color: #4d4d4d; + font-size: 14px; + margin: 0 !important; + padding: 7px 22.652px; + text-align: left; + width: 100%; } + div#wiki_panel input[type="button"]:hover { + -webkit-box-shadow: 0 1px 0 white; + -moz-box-shadow: 0 1px 0 white; + -ms-box-shadow: 0 1px 0 white; + -o-box-shadow: 0 1px 0 white; + box-shadow: 0 1px 0 white; + background: #efefef; } + div#wiki_panel ul li.search { + -webkit-box-shadow: 0 1px 0 #eeeeee; + -moz-box-shadow: 0 1px 0 #eeeeee; + -ms-box-shadow: 0 1px 0 #eeeeee; + -o-box-shadow: 0 1px 0 #eeeeee; + box-shadow: 0 1px 0 #eeeeee; + border-bottom: 1px solid #d3d3d3; + padding: 7px 22.652px; } + div#wiki_panel ul li.search label { + display: none; } + div#wiki_panel ul li.create-article h3 a, div#wiki_panel ul li.create-article input[type="button"] a { + padding: 7px 22.652px; } + div#wiki_panel div#wiki_create_form { + padding: 15px; + background: #d6d6d6; + border-bottom: 1px solid #bbb; } + div#wiki_panel div#wiki_create_form input[type="text"] { + margin-bottom: 6px; + display: block; + width: 100%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + -ms-box-sizing: border-box; + -o-box-sizing: border-box; + box-sizing: border-box; } + div#wiki_panel div#wiki_create_form ul { + list-style: none; } + div#wiki_panel div#wiki_create_form ul li { + float: left; } + div#wiki_panel div#wiki_create_form ul li#cancel { + float: right; + margin-top: 10px; } + form#wiki_revision { float: left; width: 65.761%; @@ -1549,74 +3108,6 @@ form#wiki_revision { div.wiki-wrapper { display: table; width: 100%; } - div.wiki-wrapper div#wiki_panel { - overflow: auto; } - div.wiki-wrapper div#wiki_panel input[type="button"] { - -webkit-transition-property: all; - -moz-transition-property: all; - -ms-transition-property: all; - -o-transition-property: all; - transition-property: all; - -webkit-transition-duration: 0.15s; - -moz-transition-duration: 0.15s; - -ms-transition-duration: 0.15s; - -o-transition-duration: 0.15s; - transition-duration: 0.15s; - -webkit-transition-timing-function: ease-out; - -moz-transition-timing-function: ease-out; - -ms-transition-timing-function: ease-out; - -o-transition-timing-function: ease-out; - transition-timing-function: ease-out; - -webkit-transition-delay: 0; - -moz-transition-delay: 0; - -ms-transition-delay: 0; - -o-transition-delay: 0; - transition-delay: 0; - color: #4d4d4d; - font-size: 14px; - margin: 0 !important; - padding: 7px 22.652px; - text-align: left; - width: 100%; } - div.wiki-wrapper div#wiki_panel input[type="button"]:hover { - -webkit-box-shadow: 0 1px 0 white; - -moz-box-shadow: 0 1px 0 white; - -ms-box-shadow: 0 1px 0 white; - -o-box-shadow: 0 1px 0 white; - box-shadow: 0 1px 0 white; - background: #efefef; } - div.wiki-wrapper div#wiki_panel ul li.search { - -webkit-box-shadow: 0 1px 0 #eeeeee; - -moz-box-shadow: 0 1px 0 #eeeeee; - -ms-box-shadow: 0 1px 0 #eeeeee; - -o-box-shadow: 0 1px 0 #eeeeee; - box-shadow: 0 1px 0 #eeeeee; - border-bottom: 1px solid #d3d3d3; - padding: 7px 22.652px; } - div.wiki-wrapper div#wiki_panel ul li.search label { - display: none; } - div.wiki-wrapper div#wiki_panel ul li.create-article h3 a, div.wiki-wrapper div#wiki_panel ul li.create-article input[type="button"] a { - padding: 7px 22.652px; } - div.wiki-wrapper div#wiki_panel div#wiki_create_form { - padding: 15px; - background: #d6d6d6; - border-bottom: 1px solid #bbb; } - div.wiki-wrapper div#wiki_panel div#wiki_create_form input[type="text"] { - margin-bottom: 6px; - display: block; - width: 100%; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - -ms-box-sizing: border-box; - -o-box-sizing: border-box; - box-sizing: border-box; } - div.wiki-wrapper div#wiki_panel div#wiki_create_form ul { - list-style: none; } - div.wiki-wrapper div#wiki_panel div#wiki_create_form ul li { - float: left; } - div.wiki-wrapper div#wiki_panel div#wiki_create_form ul li#cancel { - float: right; - margin-top: 10px; } div.wiki-wrapper section.wiki-body header:empty { display: none !important; } div.wiki-wrapper section.wiki-body header p { @@ -1684,24 +3175,6 @@ div.wiki-wrapper { div.wiki-wrapper section.wiki-body #wiki_history_table tr.dark { background-color: #dddddd; } -section.activation { - -webkit-box-shadow: 0 1px 0 white; - -moz-box-shadow: 0 1px 0 white; - -ms-box-shadow: 0 1px 0 white; - -o-box-shadow: 0 1px 0 white; - box-shadow: 0 1px 0 white; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - -ms-box-sizing: border-box; - -o-box-sizing: border-box; - box-sizing: border-box; - background: #fff; - border-top: 0; - border: 1px solid #ccc; - max-width: 600px; - padding: 22.652px; - margin-top: 22.652px; } - section.help.main-content { padding: 22.652px; } section.help.main-content h1 { @@ -1740,7 +3213,7 @@ section.help.main-content { color: #763333; text-decoration: underline; } -.badge-context-toggle.active, div.course-wrapper div#accordion h3.badge-context-toggle.ui-accordion-header.ui-state-active, div.course-wrapper div#accordion div.wiki-wrapper div#wiki_panel input.badge-context-toggle.ui-accordion-header.ui-state-active[type="button"], div.wiki-wrapper div#wiki_panel div.course-wrapper div#accordion input.badge-context-toggle.ui-accordion-header.ui-state-active[type="button"], nav.sequence-nav ol li.badge-context-toggle.seq_video_active, nav.sequence-nav ol li.badge-context-toggle.seq_other_active, nav.sequence-nav ol li.badge-context-toggle.seq_vertical_active, nav.sequence-nav ol li.badge-context-toggle.seq_problem_active { +.badge-context-toggle.active, div#accordion h3.badge-context-toggle.ui-accordion-header.ui-state-active, div#accordion div#wiki_panel input.badge-context-toggle.ui-accordion-header.ui-state-active[type="button"], div#wiki_panel div#accordion input.badge-context-toggle.ui-accordion-header.ui-state-active[type="button"], nav.sequence-nav ol li.badge-context-toggle.seq_video_active, nav.sequence-nav ol li.badge-context-toggle.seq_other_active, nav.sequence-nav ol li.badge-context-toggle.seq_vertical_active, nav.sequence-nav ol li.badge-context-toggle.seq_problem_active { cursor: pointer; text-decoration: underline; } @@ -1998,7 +3471,7 @@ body.anon #searchBar { /*padding-right: 10px;*/ /*margin-bottom: 10px;*/ /*font-family: 'Yanone Kaffeesatz',sans-serif;*/ } - .box h3, .box div.wiki-wrapper div#wiki_panel input[type="button"], div.wiki-wrapper div#wiki_panel .box input[type="button"] { + .box h3, .box div#wiki_panel input[type="button"], div#wiki_panel .box input[type="button"] { /*color: #4a757f;*/ /*font-size: 18px;*/ text-align: left; @@ -2106,18 +3579,6 @@ body.anon #searchBar { #markdownHelp a { font-size: 16px; } -#listSearchTags { - float: left; - margin-top: 3px; - color: #707070; - font-size: 16px; - font-family: 'Yanone Kaffeesatz',sans-serif; } - -ul#searchTags { - margin-left: 10px; - float: right; - padding-top: 2px; } - .pager { margin-top: 10px; margin-bottom: 16px; } @@ -2568,7 +4029,7 @@ a:hover.medal { .user-details { font-size: 13px; } - .user-details h3, .user-details div.wiki-wrapper div#wiki_panel input[type="button"], div.wiki-wrapper div#wiki_panel .user-details input[type="button"] { + .user-details h3, .user-details div#wiki_panel input[type="button"], div#wiki_panel .user-details input[type="button"] { font-size: 16px; } .user-about { @@ -2628,7 +4089,7 @@ a:hover.medal { .karma-summary { padding: 5px; font-size: 13px; } - .karma-summary h3, .karma-summary div.wiki-wrapper div#wiki_panel input[type="button"], div.wiki-wrapper div#wiki_panel .karma-summary input[type="button"] { + .karma-summary h3, .karma-summary div#wiki_panel input[type="button"], div#wiki_panel .karma-summary input[type="button"] { text-align: center; font-weight: bold; padding: 5px; } @@ -2691,7 +4152,7 @@ a:hover.medal { font-size: 13px; line-height: 1.3; color: #525252; } - .revision h3, .revision div.wiki-wrapper div#wiki_panel input[type="button"], div.wiki-wrapper div#wiki_panel .revision input[type="button"] { + .revision h3, .revision div#wiki_panel input[type="button"], div#wiki_panel .revision input[type="button"] { font-family: 'Yanone Kaffeesatz',sans-serif; font-size: 21px; padding-left: 0px; } @@ -2762,7 +4223,7 @@ ins { -moz-border-radius: 4px; -webkit-border-radius: 4px; -khtml-border-radius: 4px; } - .vote-notification h3, .vote-notification div.wiki-wrapper div#wiki_panel input[type="button"], div.wiki-wrapper div#wiki_panel .vote-notification input[type="button"] { + .vote-notification h3, .vote-notification div#wiki_panel input[type="button"], div#wiki_panel .vote-notification input[type="button"] { background: url(../images/notification.png) repeat-x top; padding: 10px 10px 10px 10px; font-size: 13px; @@ -2874,7 +4335,7 @@ label.retag-error { .user-stats-table .narrow { width: 660px; } -.narrow .summary h3, .narrow .summary div.wiki-wrapper div#wiki_panel input[type="button"], div.wiki-wrapper div#wiki_panel .narrow .summary input[type="button"] { +.narrow .summary h3, .narrow .summary div#wiki_panel input[type="button"], div#wiki_panel .narrow .summary input[type="button"] { padding: 0px; margin: 0px; } @@ -3202,7 +4663,7 @@ p.signup_p { margin-left: 0; } .user-profile-page img.gravatar { margin: 2px 0 3px 0; } -.user-profile-page h3, .user-profile-page div.wiki-wrapper div#wiki_panel input[type="button"], div.wiki-wrapper div#wiki_panel .user-profile-page input[type="button"] { +.user-profile-page h3, .user-profile-page div#wiki_panel input[type="button"], div#wiki_panel .user-profile-page input[type="button"] { padding: 0; margin-top: -3px; } @@ -3294,53 +4755,12 @@ pre.prettyprint { border: 1px solid #ccc; text-decoration: none; } -body.askbot .secondary-nav { - margin: 0; } - body.askbot .secondary-nav nav { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - -ms-box-sizing: border-box; - -o-box-sizing: border-box; - box-sizing: border-box; - border: 1px solid #eddfaa; - border-top: 0; - margin: 0 auto; - padding: 22.652px; } - body.askbot .secondary-nav nav div { - float: left; } - body.askbot .secondary-nav nav div.question-filter { - font-size: 16px; - margin-top: 4px; - width: 31.984%; } - body.askbot .secondary-nav nav div.question-filter ul { - -webkit-border-radius: 35px; - -moz-border-radius: 35px; - -ms-border-radius: 35px; - -o-border-radius: 35px; - border-radius: 35px; - background: #e4d080; - display: inline; - margin: 0 0 0 10px; - padding: 5.663px 20px; } - body.askbot .secondary-nav nav div.question-filter ul li { - display: inline-block; - list-style: none; - margin-right: 10px; } - body.askbot .secondary-nav nav div.question-filter ul li:last-child { - margin-right: 0; } - body.askbot .secondary-nav nav div.question-filter ul li a { - text-transform: capitalize; - text-shadow: none; - font-size: 14px; } - body.askbot .secondary-nav nav div.question-filter ul li a.on { - font-weight: bold; } - body.askbot .secondary-nav nav div.search-box { - margin-left: 2%; - text-align: right; - width: 65.992%; } - body.askbot .secondary-nav nav div.search-box input[type="text"] { - margin-right: 6px; - width: 22.699%; } +.action-link a, div.question-list-header section.question-list-meta div.question-sort nav a, div.question-list-header section.question-list-meta div.answer-controls div.answer-sort nav a, div.answer-controls div.question-list-header section.question-list-meta div.answer-sort nav a { + color: #a88d23; } + .action-link a:hover, div.question-list-header section.question-list-meta div.question-sort nav a:hover, div.question-list-header section.question-list-meta div.answer-controls div.answer-sort nav a:hover, div.answer-controls div.question-list-header section.question-list-meta div.answer-sort nav a:hover { + text-decoration: none; + color: #544611; } + body.askbot section.main-content div.discussion-wrapper div.discussion-content { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; @@ -3348,9 +4768,9 @@ body.askbot section.main-content div.discussion-wrapper div.discussion-content { -o-box-sizing: border-box; box-sizing: border-box; display: table-cell; - padding: 2.024%; + padding: 22.652px; vertical-align: top; - width: 74.494%; } + width: 76.518%; } body.askbot section.main-content div.discussion-wrapper div.discussion-content p.tabula-rasa { -webkit-border-radius: 5px; -moz-border-radius: 5px; @@ -3384,11 +4804,11 @@ body.askbot section.main-content div.discussion-wrapper aside { border-radius: 0 4px 4px 0; border-left: 1px solid #d3d3d3; border-right: 1px solid #f6f6f6; - padding: 2.024%; + padding: 22.652px; width: 23.482%; } body.askbot section.main-content div.discussion-wrapper aside h2 { font-size: 16px; } - body.askbot section.main-content div.discussion-wrapper aside h3, body.askbot section.main-content div.discussion-wrapper aside div.wiki-wrapper div#wiki_panel input[type="button"], div.wiki-wrapper div#wiki_panel body.askbot section.main-content div.discussion-wrapper aside input[type="button"] { + body.askbot section.main-content div.discussion-wrapper aside h3, body.askbot section.main-content div.discussion-wrapper aside div#wiki_panel input[type="button"], div#wiki_panel body.askbot section.main-content div.discussion-wrapper aside input[type="button"] { border-bottom: 0; box-shadow: none; } body.askbot section.main-content div.discussion-wrapper aside input[type="text"] { @@ -3396,56 +4816,81 @@ body.askbot section.main-content div.discussion-wrapper aside { body.askbot section.main-content div.discussion-wrapper aside #displayTagFilterControl { margin-top: 10px; } -div.question-controls, div.answer-controls { +div.question-list-header { display: block; - margin-bottom: 30px; + margin-bottom: 15px; overflow: hidden; width: 100%; } - div.question-controls div, div.answer-controls div { - display: inline-block; } - div.question-controls div.question-count, div.answer-controls div.question-count, div.question-controls div.answer-controls div.answer-count, div.answer-controls div.question-controls div.answer-count, div.answer-controls div.answer-count { - margin-right: 2.024%; - width: 42.935%; } - div.question-controls div.question-count h1, div.answer-controls div.question-count h1, div.question-controls div.answer-controls div.answer-count h1, div.answer-controls div.question-controls div.answer-count h1, div.answer-controls div.answer-count h1 { - margin-top: 0; } - div.question-controls div.question-sort, div.answer-controls div.question-sort, div.question-controls div.answer-controls div.answer-sort, div.answer-controls div.question-controls div.answer-sort, div.answer-controls div.answer-sort { - vertical-align: bottom; - width: 54.348%; } - div.question-controls div.question-sort nav, div.answer-controls div.question-sort nav, div.question-controls div.answer-controls div.answer-sort nav, div.answer-controls div.question-controls div.answer-sort nav, div.answer-controls div.answer-sort nav { - -webkit-border-radius: 35px; - -moz-border-radius: 35px; - -ms-border-radius: 35px; - -o-border-radius: 35px; - border-radius: 35px; - background-color: #faf7e9; - height: 30px; + div.question-list-header section.question-list-meta { + display: block; + overflow: hidden; + width: 100%; } + div.question-list-header section.question-list-meta div { + display: inline-block; + float: left; } + div.question-list-header section.question-list-meta span.label { + color: #555; } + div.question-list-header section.question-list-meta div.question-list-title { + margin-right: 2.024%; } + div.question-list-header section.question-list-meta div.question-list-title h1 { + margin-top: 0; } + div.question-list-header section.question-list-meta div.question-sort, div.question-list-header section.question-list-meta div.answer-controls div.answer-sort, div.answer-controls div.question-list-header section.question-list-meta div.answer-sort { float: right; - font-size: 16px; - margin: 3px 0; - padding: 0px 20px 5px; } - div.question-controls div.question-sort nav a, div.answer-controls div.question-sort nav a, div.question-controls div.answer-controls div.answer-sort nav a, div.answer-controls div.question-controls div.answer-sort nav a, div.answer-controls div.answer-sort nav a { - color: #a88d23; } - div.question-controls div.question-sort nav a.on span, div.answer-controls div.question-sort nav a.on span, div.question-controls div.answer-controls div.answer-sort nav a.on span, div.answer-controls div.question-controls div.answer-sort nav a.on span, div.answer-controls div.answer-sort nav a.on span { + margin-left: 2.024%; } + div.question-list-header section.question-list-meta div.question-sort nav, div.question-list-header section.question-list-meta div.answer-controls div.answer-sort nav, div.answer-controls div.question-list-header section.question-list-meta div.answer-sort nav { + float: right; } + div.question-list-header section.question-list-meta div.question-sort nav a.on span, div.question-list-header section.question-list-meta div.answer-controls div.answer-sort nav a.on span, div.answer-controls div.question-list-header section.question-list-meta div.answer-sort nav a.on span { font-weight: bold; } - div.question-controls div.question-sort nav a:before, div.answer-controls div.question-sort nav a:before, div.question-controls div.answer-controls div.answer-sort nav a:before, div.answer-controls div.question-controls div.answer-sort nav a:before, div.answer-controls div.answer-sort nav a:before { + div.question-list-header section.question-list-meta div.question-sort nav a:before, div.question-list-header section.question-list-meta div.answer-controls div.answer-sort nav a:before, div.answer-controls div.question-list-header section.question-list-meta div.answer-sort nav a:before { content: '|'; color: #eddfaa; font-size: 22px; } - div.question-controls div.question-sort nav a:hover, div.answer-controls div.question-sort nav a:hover, div.question-controls div.answer-controls div.answer-sort nav a:hover, div.answer-controls div.question-controls div.answer-sort nav a:hover, div.answer-controls div.answer-sort nav a:hover { - text-decoration: none; - color: #544611; } + div.question-list-header section.question-tags-list { + display: block; + min-height: 26px; + overflow: hidden; + padding-top: 5px; + width: 100%; } + div.question-list-header section.question-tags-list div { + display: inline-block; + float: left; } + div.question-list-header section.question-tags-list div.back { + margin-right: 10px; } + div.question-list-header section.question-tags-list div.back a { + color: #555; } + div.question-list-header section.question-tags-list div.tags-list ul.tags { + display: inline; } + div.question-list-header section.question-tags-list div.tags-list ul.tags li span.delete-icon, div.question-list-header section.question-tags-list div.tags-list ul.tags li div.delete-icon { + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + -ms-border-radius: 0 4px 4px 0; + -o-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; + background: #555; + color: #eee; + cursor: pointer; + float: none; + display: inline; + clear: none; + left: 10px; + padding: 3px 6px; + position: relative; + top: 1px; + opacity: 0.5; } + div.question-list-header section.question-tags-list div.tags-list ul.tags li span.delete-icon:hover, div.question-list-header section.question-tags-list div.tags-list ul.tags li div.delete-icon:hover { + opacity: 1; } -ul.question-list { +ul.question-list, div#question-list { width: 100%; } - ul.question-list li.single-question { + ul.question-list li.single-question, div#question-list li.single-question { border-top: 1px solid #eee; list-style: none; padding: 10px 0; } - ul.question-list li.single-question:hover { + ul.question-list li.single-question:hover, div#question-list li.single-question:hover { background: #fdfcf6; } - ul.question-list li.single-question div { + ul.question-list li.single-question div, div#question-list li.single-question div { display: inline-block; } - ul.question-list li.single-question div.question-body, ul.question-list li.single-question div.answer-block div.answer-container div.answer-content div.answer-body, div.answer-block div.answer-container div.answer-content ul.question-list li.single-question div.answer-body { + ul.question-list li.single-question div.question-body, ul.question-list li.single-question div.answer-block div.answer-container div.answer-content div.answer-body, div.answer-block div.answer-container div.answer-content ul.question-list li.single-question div.answer-body, div#question-list li.single-question div.question-body, div#question-list li.single-question div.answer-block div.answer-container div.answer-content div.answer-body, div.answer-block div.answer-container div.answer-content div#question-list li.single-question div.answer-body { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; -ms-box-sizing: border-box; @@ -3454,25 +4899,25 @@ ul.question-list { margin-right: 2.024%; padding-left: 10px; width: 60.054%; } - ul.question-list li.single-question div.question-body h2, ul.question-list li.single-question div.answer-block div.answer-container div.answer-content div.answer-body h2, div.answer-block div.answer-container div.answer-content ul.question-list li.single-question div.answer-body h2 { + ul.question-list li.single-question div.question-body h2, ul.question-list li.single-question div.answer-block div.answer-container div.answer-content div.answer-body h2, div.answer-block div.answer-container div.answer-content ul.question-list li.single-question div.answer-body h2, div#question-list li.single-question div.question-body h2, div#question-list li.single-question div.answer-block div.answer-container div.answer-content div.answer-body h2, div.answer-block div.answer-container div.answer-content div#question-list li.single-question div.answer-body h2 { font-size: 16px; - font-weight: normal; + font-weight: bold; margin: 0px 0 15px 0; text-transform: none; } - ul.question-list li.single-question div.question-body div.user-info, ul.question-list li.single-question div.answer-block div.answer-container div.answer-content div.answer-body div.user-info, div.answer-block div.answer-container div.answer-content ul.question-list li.single-question div.answer-body div.user-info { + ul.question-list li.single-question div.question-body div.user-info, ul.question-list li.single-question div.answer-block div.answer-container div.answer-content div.answer-body div.user-info, div.answer-block div.answer-container div.answer-content ul.question-list li.single-question div.answer-body div.user-info, div#question-list li.single-question div.question-body div.user-info, div#question-list li.single-question div.answer-block div.answer-container div.answer-content div.answer-body div.user-info, div.answer-block div.answer-container div.answer-content div#question-list li.single-question div.answer-body div.user-info { display: inline-block; vertical-align: top; } - ul.question-list li.single-question div.question-body div.user-info span.relative-time, ul.question-list li.single-question div.answer-block div.answer-container div.answer-content div.answer-body div.user-info span.relative-time, div.answer-block div.answer-container div.answer-content ul.question-list li.single-question div.answer-body div.user-info span.relative-time { + ul.question-list li.single-question div.question-body div.user-info span.relative-time, ul.question-list li.single-question div.answer-block div.answer-container div.answer-content div.answer-body div.user-info span.relative-time, div.answer-block div.answer-container div.answer-content ul.question-list li.single-question div.answer-body div.user-info span.relative-time, div#question-list li.single-question div.question-body div.user-info span.relative-time, div#question-list li.single-question div.answer-block div.answer-container div.answer-content div.answer-body div.user-info span.relative-time, div.answer-block div.answer-container div.answer-content div#question-list li.single-question div.answer-body div.user-info span.relative-time { font-weight: normal; } - ul.question-list li.single-question div.question-body div.user-info a, ul.question-list li.single-question div.answer-block div.answer-container div.answer-content div.answer-body div.user-info a, div.answer-block div.answer-container div.answer-content ul.question-list li.single-question div.answer-body div.user-info a { + ul.question-list li.single-question div.question-body div.user-info a, ul.question-list li.single-question div.answer-block div.answer-container div.answer-content div.answer-body div.user-info a, div.answer-block div.answer-container div.answer-content ul.question-list li.single-question div.answer-body div.user-info a, div#question-list li.single-question div.question-body div.user-info a, div#question-list li.single-question div.answer-block div.answer-container div.answer-content div.answer-body div.user-info a, div.answer-block div.answer-container div.answer-content div#question-list li.single-question div.answer-body div.user-info a { color: #993333; } - ul.question-list li.single-question div.question-body ul.tags, ul.question-list li.single-question div.answer-block div.answer-container div.answer-content div.answer-body ul.tags, div.answer-block div.answer-container div.answer-content ul.question-list li.single-question div.answer-body ul.tags { + ul.question-list li.single-question div.question-body ul.tags, ul.question-list li.single-question div.answer-block div.answer-container div.answer-content div.answer-body ul.tags, div.answer-block div.answer-container div.answer-content ul.question-list li.single-question div.answer-body ul.tags, div#question-list li.single-question div.question-body ul.tags, div#question-list li.single-question div.answer-block div.answer-container div.answer-content div.answer-body ul.tags, div.answer-block div.answer-container div.answer-content div#question-list li.single-question div.answer-body ul.tags { display: inline-block; } - ul.question-list li.single-question div.question-meta { + ul.question-list li.single-question div.question-meta, div#question-list li.single-question div.question-meta { width: 37.228%; } - ul.question-list li.single-question div.question-meta ul { + ul.question-list li.single-question div.question-meta ul, div#question-list li.single-question div.question-meta ul { text-align: right; } - ul.question-list li.single-question div.question-meta ul li { + ul.question-list li.single-question div.question-meta ul li, div#question-list li.single-question div.question-meta ul li { -webkit-border-radius: 3px; -moz-border-radius: 3px; -ms-border-radius: 3px; @@ -3482,13 +4927,13 @@ ul.question-list { height: 60px; margin-right: 10px; width: 60px; } - ul.question-list li.single-question div.question-meta ul li.views { + ul.question-list li.single-question div.question-meta ul li.views, div#question-list li.single-question div.question-meta ul li.views { background: #faf7e9; } - ul.question-list li.single-question div.question-meta ul li.answers { + ul.question-list li.single-question div.question-meta ul li.answers, div#question-list li.single-question div.question-meta ul li.answers { background: #F6EFD4; } - ul.question-list li.single-question div.question-meta ul li.votes { + ul.question-list li.single-question div.question-meta ul li.votes, div#question-list li.single-question div.question-meta ul li.votes { background: #f2e7bf; } - ul.question-list li.single-question div.question-meta ul li span, ul.question-list li.single-question div.question-meta ul li div { + ul.question-list li.single-question div.question-meta ul li span, ul.question-list li.single-question div.question-meta ul li div, div#question-list li.single-question div.question-meta ul li span, div#question-list li.single-question div.question-meta ul li div { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; -ms-box-sizing: border-box; @@ -3497,19 +4942,16 @@ ul.question-list { color: #7e691a; display: block; text-align: center; } - ul.question-list li.single-question div.question-meta ul li span { + ul.question-list li.single-question div.question-meta ul li span, div#question-list li.single-question div.question-meta ul li span { font-size: 16px; font-weight: bold; height: 35px; padding-top: 15px; vertical-align: middle; } - ul.question-list li.single-question div.question-meta ul li div { + ul.question-list li.single-question div.question-meta ul li div, div#question-list li.single-question div.question-meta ul li div { height: 25px; font-size: 12px; } -div.search-tips { - display: block; } - ul.tags { list-style: none; } ul.tags li, ul.tags a { diff --git a/css/marketing.css b/css/marketing.css index 80ffbbc25d..a3a8c48bcc 100644 --- a/css/marketing.css +++ b/css/marketing.css @@ -147,7 +147,8 @@ input, select { .subpage > div, section.copyright > div, section.tos > div, section.privacy-policy > div, section.honor-code > div { padding-left: 0; } } .subpage > div p, section.copyright > div p, section.tos > div p, section.privacy-policy > div p, section.honor-code > div p { - margin-bottom: 25.888px; } + margin-bottom: 25.888px; + line-height: 25.888px; } .subpage > div h1, section.copyright > div h1, section.tos > div h1, section.privacy-policy > div h1, section.honor-code > div h1 { margin-bottom: 12.944px; } .subpage > div h2, section.copyright > div h2, section.tos > div h2, section.privacy-policy > div h2, section.honor-code > div h2 { @@ -157,7 +158,8 @@ input, select { .subpage > div ul, section.copyright > div ul, section.tos > div ul, section.privacy-policy > div ul, section.honor-code > div ul { list-style: disc outside none; } .subpage > div ul li, section.copyright > div ul li, section.tos > div ul li, section.privacy-policy > div ul li, section.honor-code > div ul li { - list-style: disc outside none; } + list-style: disc outside none; + line-height: 25.888px; } .clearfix:after, .subpage:after, section.copyright:after, section.tos:after, section.privacy-policy:after, section.honor-code:after, header.announcement div section:after, section.index-content:after, section.index-content section:after, section.index-content section.about section:after, footer:after, div.leanModal_box#enroll ol:after { content: "."; @@ -269,9 +271,6 @@ header.announcement { -webkit-font-smoothing: antialiased; } header.announcement.home { background: #e3e3e3 url("/static/images/marketing/shot-5-medium.jpg"); } - @media screen and (min-width: 1200px) { - header.announcement.home { - background: #e3e3e3 url("/static/images/marketing/shot-5-large.jpg"); } } header.announcement.home div { padding: 258.88px 25.888px 77.664px; } header.announcement.home div nav h1 { diff --git a/css/print.css b/css/print.css index 12436ba683..3e73338a84 100644 --- a/css/print.css +++ b/css/print.css @@ -1,6 +1,10 @@ -.header-wrapper {display:none;} -#accordion {display:none;} -.ui-accordion {display:none; -visibility:hidden; -width:0%; -} +.header-wrapper { + display: none; } + +#accordion { + display: none; } + +.ui-accordion { + display: none; + visibility: hidden; + width: 0%; } diff --git a/js/cktsim.js b/js/cktsim.js deleted file mode 100755 index 0923c713cc..0000000000 --- a/js/cktsim.js +++ /dev/null @@ -1,1631 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// Circuit simulator -// -////////////////////////////////////////////////////////////////////////////// - -// Copyright (C) 2011 Massachusetts Institute of Technology - - -// create a circuit for simulation using "new cktsim.Circuit()" - -// for modified nodal analysis (MNA) stamps see -// http://www.analog-electronics.eu/analog-electronics/modified-nodal-analysis/modified-nodal-analysis.xhtml - -cktsim = (function() { - - /////////////////////////////////////////////////////////////////////////////// - // - // Circuit - // - ////////////////////////////////////////////////////////////////////////////// - - // types of "nodes" in the linear system - T_VOLTAGE = 0; - T_CURRENT = 1; - - v_newt_lim = 0.3; // Voltage limited Newton great for Mos/diodes - v_abstol = 1e-6; // criterion for absolute convergence (voltage) - i_abstol = 1e-12; // criterion for absolute convergence (current) - min_time_step = 1e-18; // smallest possible time step - max_dc_iters = 200; // max iterations before giving pu - max_tran_iters = 10; // max iterations before giving up - increase_limit = 4; // if we converge in this many iterations, increase time step - time_step_increase_factor = 2.0; // How much can lte let timestep grow. - lte_step_decrease_factor = 8; // How much will lte shrink timestep in one iter. - nr_step_decrease_factor = 4; // How much Newton will shink timeste in one iter. - reltol = 0.0001; // convergence criterion relative to max observed value - lterel = 4; // The ratio between lte error and Newton error. - - function Circuit() { - this.node_map = new Array(); - this.ntypes = []; - this.initial_conditions = []; // ic's for each element - - this.devices = []; // list of devices - this.device_map = new Array(); // map name -> device - this.voltage_sources = []; // list of voltage sources - - this.finalized = false; - this.diddc = false; - this.node_index = -1; - } - - // index of ground node - Circuit.prototype.gnd_node = function() { - return -1; - } - - // allocate a new node index - Circuit.prototype.node = function(name,ntype,ic) { - this.node_index += 1; - if (name) this.node_map[name] = this.node_index; - this.ntypes.push(ntype); - this.initial_conditions.push(ic); - return this.node_index; - } - - // call to finalize the circuit in preparation for simulation - Circuit.prototype.finalize = function() { - if (!this.finalized) { - this.finalized = true; - this.N = this.node_index + 1; // number of nodes - - // give each device a chance to finalize itself - for (var i = this.devices.length - 1; i >= 0; --i) - this.devices[i].finalize(this); - - // set up augmented matrix and various temp vectors - this.matrix = this.make_mat(this.N, this.N+1); - this.Gl = this.make_mat(this.N, this.N); // Matrix for linear conductances - this.G = this.make_mat(this.N, this.N); // Complete conductance matrix - this.C = this.make_mat(this.N, this.N); // Matrix for linear L's and C's - - this.soln_max = new Array(this.N); // max abs value seen for each unknown - this.abstol = new Array(this.N); - this.solution = new Array(this.N); - this.rhs = new Array(this.N); - for (var i = this.N - 1; i >= 0; --i) { - this.soln_max[i] = 0.0; - this.abstol[i] = this.ntypes[i] == T_VOLTAGE ? v_abstol : i_abstol; - this.solution[i] = 0.0; - this.rhs[i] = 0.0; - } - } - } - - // load circuit from JSON netlist (see schematic.js) - Circuit.prototype.load_netlist = function(netlist) { - // set up mapping for all ground connections - for (var i = netlist.length - 1; i >= 0; --i) { - var component = netlist[i]; - var type = component[0]; - if (type == 'g') { - var connections = component[3]; - this.node_map[connections[0]] = this.gnd_node(); - } - } - - // process each component in the JSON netlist (see schematic.js for format) - var found_ground = false; - for (var i = netlist.length - 1; i >= 0; --i) { - var component = netlist[i]; - var type = component[0]; - - // ignore wires, ground connections, scope probes and view info - if (type == 'view' || type == 'w' || type == 'g' || type == 's' || type == 'L') { - continue; - } - - var properties = component[2]; - var name = properties['name']; - if (name==undefined || name=='') - name = '_' + properties['_json_'].toString(); - - // convert node names to circuit indicies - var connections = component[3]; - for (var j = connections.length - 1; j >= 0; --j) { - var node = connections[j]; - var index = this.node_map[node]; - if (index == undefined) index = this.node(node,T_VOLTAGE); - else if (index == this.gnd_node()) found_ground = true; - connections[j] = index; - } - - // process the component - if (type == 'r') // resistor - this.r(connections[0],connections[1],properties['r'],name); - else if (type == 'd') // diode - this.d(connections[0],connections[1],properties['area'],name); - else if (type == 'c') // capacitor - this.c(connections[0],connections[1],properties['c'],name); - else if (type == 'l') // inductor - this.l(connections[0],connections[1],properties['l'],name); - else if (type == 'v') // voltage source - this.v(connections[0],connections[1],properties['value'],name); - else if (type == 'i') // current source - this.i(connections[0],connections[1],properties['value'],name); - else if (type == 'o') // op amp - this.opamp(connections[0],connections[1],connections[2],connections[3],properties['A'],name); - else if (type == 'n') // n fet - this.n(connections[0],connections[1],connections[2],properties['W/L'],name); - else if (type == 'p') // p fet - this.p(connections[0],connections[1],connections[2],properties['W/L'],name); - } - - if (!found_ground) { // No ground on schematic - alert('Please make at least one connection to ground (inverted T symbol)'); - return false; - } - return true; - - } - - // if converges: updates this.solution, this.soln_max, returns iter count - // otherwise: return undefined and set this.problem_node - // Load should compute -f and df/dx (note the sign pattern!) - Circuit.prototype.find_solution = function(load,maxiters) { - var soln = this.solution; - var rhs = this.rhs; - var d_sol,converged; - - // iteratively solve until values convere or iteration limit exceeded - for (var iter = 0; iter < maxiters; iter++) { - // set up equations - load(this,soln,rhs); - - // Compute the Newton delta - d_sol = solve_linear_system(this.matrix,rhs); - - // Update solution and check convergence. - converged = true; - for (var i = this.N - 1; i >= 0; --i) { - // Simple voltage step limiting to encourage Newton convergence - if (this.ntypes[i] == T_VOLTAGE) { - d_sol[i] = (d_sol[i] > v_newt_lim) ? v_newt_lim : d_sol[i]; - d_sol[i] = (d_sol[i] < -v_newt_lim) ? -v_newt_lim : d_sol[i]; - } - soln[i] += d_sol[i]; - if (Math.abs(soln[i]) > this.soln_max[i]) - this.soln_max[i] = Math.abs(soln[i]); - thresh = this.abstol[i] + reltol*this.soln_max[i]; - if (Math.abs(d_sol[i]) > thresh) { - converged = false; - this.problem_node = i; - } - } - //alert(numeric.prettyPrint(this.solution);) - if (converged == true) return iter+1; - } - // too many iterations - return undefined; - } - - // DC analysis - Circuit.prototype.dc = function() { - - // Allocation matrices for linear part, etc. - this.finalize(); - - // Load up the linear part. - for (var i = this.devices.length - 1; i >= 0; --i) { - this.devices[i].load_linear(this) - } - - // Define -f and df/dx for Newton solver - function load_dc(ckt,soln,rhs) { - // rhs is initialized to -Gl * soln - ckt.matv_mult(ckt.Gl, soln, rhs, -1.0); - // G matrix is initialized with linear Gl - ckt.copy_mat(ckt.Gl,ckt.G); - // Now load up the nonlinear parts of rhs and G - for (var i = ckt.devices.length - 1; i >= 0; --i) - ckt.devices[i].load_dc(ckt,soln,rhs); - // G matrix is copied in to the system matrix - ckt.copy_mat(ckt.G,ckt.matrix); - } - - // find the operating point - var iterations = this.find_solution(load_dc,max_dc_iters); - - if (typeof iterations == 'undefined') { - return 'Node '+this.node_map[this.problem_node]+' unconverged'; - } else { - // Note that a dc solution was computed - this.diddc = true; - // create solution dictionary - var result = new Array(); - // capture node voltages - for (var name in this.node_map) { - var index = this.node_map[name]; - result[name] = (index == -1) ? 0 : this.solution[index]; - } - // capture branch currents from voltage sources - for (var i = this.voltage_sources.length - 1; i >= 0; --i) { - var v = this.voltage_sources[i]; - result['I('+v.name+')'] = this.solution[v.branch]; - } - return result; - } - } - - // Transient analysis (needs work!) - Circuit.prototype.tran = function(ntpts, tstart, tstop, probenames, no_dc) { - - // Define -f and df/dx for Newton solver - function load_tran(ckt,soln,rhs) { - // Crnt is initialized to -Gl * soln - ckt.matv_mult(ckt.Gl, soln, ckt.c,-1.0); - // G matrix is initialized with linear Gl - ckt.copy_mat(ckt.Gl,ckt.G); - // Now load up the nonlinear parts of crnt and G - for (var i = ckt.devices.length - 1; i >= 0; --i) - ckt.devices[i].load_tran(ckt,soln,ckt.c,ckt.time); - // Exploit the fact that storage elements are linear - ckt.matv_mult(ckt.C, soln, ckt.q, 1.0); - // -rhs = c - dqdt - for (var i = ckt.N-1; i >= 0; --i) { - var dqdt = ckt.alpha0*ckt.q[i] + ckt.alpha1*ckt.oldq[i] + - ckt.alpha2*ckt.old2q[i]; - //alert(numeric.prettyPrint(dqdt)); - rhs[i] = ckt.beta0[i]*ckt.c[i] + ckt.beta1[i]*ckt.oldc[i] - dqdt; - } - // matrix = beta0*G + alpha0*C. - ckt.mat_scale_add(ckt.G,ckt.C,ckt.beta0,ckt.alpha0,ckt.matrix); - } - - var p = new Array(3); - function interp_coeffs(t, t0, t1, t2) { - // Poly coefficients - var dtt0 = (t - t0); - var dtt1 = (t - t1); - var dtt2 = (t - t2); - var dt0dt1 = (t0 - t1); - var dt0dt2 = (t0 - t2); - var dt1dt2 = (t1 - t2); - p[0] = (dtt1*dtt2)/(dt0dt1 * dt0dt2); - p[1] = (dtt0*dtt2)/(-dt0dt1 * dt1dt2); - p[2] = (dtt0*dtt1)/(dt0dt2 * dt1dt2); - return p; - } - - function pick_step(ckt, step_index) { - var min_shrink_factor = 1.0/lte_step_decrease_factor; - var max_growth_factor = time_step_increase_factor; - var N = ckt.N; - var p = interp_coeffs(ckt.time, ckt.oldt, ckt.old2t, ckt.old3t); - var trapcoeff = 0.5*(ckt.time - ckt.oldt)/(ckt.time - ckt.old3t); - var maxlteratio = 0.0; - for (var i = ckt.N-1; i >= 0; --i) { - if (ckt.ltecheck[i]) { // Check lte on variable - var pred = p[0]*ckt.oldsol[i] + p[1]*ckt.old2sol[i] + p[2]*ckt.old3sol[i]; - var lte = Math.abs((ckt.solution[i] - pred))*trapcoeff; - var lteratio = lte/(lterel*(ckt.abstol[i] + reltol*ckt.soln_max[i])); - maxlteratio = Math.max(maxlteratio, lteratio); - } - } - var new_step; - var lte_step_ratio = 1.0/Math.pow(maxlteratio,1/3); // Cube root because trap - if (lte_step_ratio < 1.0) { // Shrink the timestep to make lte - lte_step_ratio = Math.max(lte_step_ratio,min_shrink_factor); - new_step = (ckt.time - ckt.oldt)*0.75*lte_step_ratio; - new_step = Math.max(new_step, ckt.min_step); - } else { - lte_step_ratio = Math.min(lte_step_ratio, max_growth_factor); - if (lte_step_ratio > 1.2) /* Increase timestep due to lte. */ - new_step = (ckt.time - ckt.oldt) * lte_step_ratio / 1.2; - else - new_step = (ckt.time - ckt.oldt); - new_step = Math.min(new_step, ckt.max_step); - } - return new_step; - } - - // Standard to do a dc analysis before transient - // Otherwise, do the setup also done in dc. - no_dc = true; - if ((this.diddc == false) && (no_dc == false)) this.dc(); - else { - // Allocate matrices and vectors. - this.finalize(); - - // Load up the linear elements once and for all - for (var i = this.devices.length - 1; i >= 0; --i) - this.devices[i].load_linear(this) - } - - // Tired of typing this, and using "with" generates hate mail. - var N = this.N; - - // build array to hold list of results for each variable - // last entry is for timepoints. - var response = new Array(N + 1); - for (var i = N; i >= 0; --i) response[i] = new Array(); - - // Allocate back vectors for up to a second order method - this.old3sol = new Array(this.N); - this.old3q = new Array(this.N); - this.old2sol = new Array(this.N); - this.old2q = new Array(this.N); - this.oldsol = new Array(this.N); - this.oldq = new Array(this.N); - this.q = new Array(this.N); - this.oldc = new Array(this.N); - this.c = new Array(this.N); - this.alpha0 = 1.0; - this.alpha1 = 0.0; - this.alpha2 = 0.0; - this.beta0 = new Array(this.N); - this.beta1 = new Array(this.N); - - // Mark the algebraic rows (useful for trap) - this.ar = this.zero_row(this.C); - - // Non-algebraic variables and probe variables get lte - this.ltecheck = new Array(this.N); - for (var i = N; i >= 0; --i) - this.ltecheck[i] = (this.ar[i] == 0); - - for (var name in this.node_map) { - var index = this.node_map[name]; - for (var i = probenames.length; i >= 0; --i) { - if (name == probenames[i]) { - this.ltecheck[index] = true; - break; - } - } - } - - this.time = tstart; - this.max_step = (tstop - tstart)/ntpts; - this.min_step = this.max_step/1e8; - var new_step = this.max_step/1e6; - this.oldt = this.time - new_step; - - // Initialize old crnts, charges, and solutions. - load_tran(this,this.solution,this.rhs) - for (var i = N-1; i >= 0; --i) { - this.old3sol[i] = this.solution[i]; - this.old2sol[i] = this.solution[i]; - this.oldsol[i] = this.solution[i]; - this.old3q[i] = this.q[i]; - this.old2q[i] = this.q[i]; - this.oldq[i] = this.q[i]; - this.oldc[i] = this.c[i]; - } - - - var beta0,beta1; - // Start with two pseudo-Euler steps, maximum 50000 steps - for(var step_index = -3; step_index < 50000; step_index++) { - // Save the just computed solution, and move back q and c. - for (var i = this.N - 1; i >= 0; --i) { - if (step_index >= 0) - response[i].push(this.solution[i]); - this.oldc[i] = this.c[i]; - this.old3sol[i] = this.old2sol[i]; - this.old2sol[i] = this.oldsol[i]; - this.oldsol[i] = this.solution[i]; - this.old3q[i] = this.oldq[i]; - this.old2q[i] = this.oldq[i]; - this.oldq[i] = this.q[i]; - - } - - if (step_index < 0) { // Take a prestep using BE - this.old3t = this.old2t - (this.oldt-this.old2t) - this.old2t = this.oldt - (tstart-this.oldt) - this.oldt = tstart - (this.time - this.oldt); - this.time = tstart; - beta0 = 1.0; - beta1 = 0.0; - } else { // Take a regular step - // Save the time, and rotate time wheel - response[this.N].push(this.time); - this.old3t = this.old2t; - this.old2t = this.oldt; - this.oldt = this.time; - // Make sure we come smoothly in to the interval end. - if (this.time >= tstop) break; // We're done. - else if(this.time + new_step > tstop) - this.time = tstop; - else if(this.time + 1.5*new_step > tstop) - this.time += (2/3)*(tstop - this.time); - else - this.time += new_step; - // Trapezoidal rule betas - beta0 = 0.5; - beta1 = 0.5; - } - - // For trap rule, turn off current avging for algebraic eqns - for (var i = this.N - 1; i >= 0; --i) { - this.beta0[i] = beta0 + this.ar[i]*beta1; - this.beta1[i] = (1.0 - this.ar[i])*beta1; - } - - // Loop to find NR converging timestep with okay LTE - while (true) { - // Set the timestep coefficients (alpha2 is for bdf2). - this.alpha0 = 1.0/(this.time - this.oldt); - this.alpha1 = -this.alpha0; - this.alpha2 = 0; - - // Use Newton to compute the solution. - var iterations = this.find_solution(load_tran,max_tran_iters); - - // If NR succeeds and stepsize is at min, accept and newstep=maxgrowth*minstep. - // Else if Newton Fails, shrink step by a factor and try again - // Else LTE picks new step, if bigger accept current step and go on. - if ((iterations != undefined) && - (step_index <= 0 || (this.time-this.oldt) < (1+reltol)*this.min_step)) { - if (step_index > 0) new_step = time_step_increase_factor*this.min_step; - break; - } else if (iterations == undefined) { // NR nonconvergence, shrink by factor - //alert('timestep nonconvergence'); - this.time = this.oldt + - (this.time - this.oldt)/nr_step_decrease_factor; - } else { // Check the LTE and shrink step if needed. - new_step = pick_step(this, step_index); - if (new_step < (1.0 - reltol)*(this.time - this.oldt)) { - this.time = this.oldt + new_step; // Try again - } - else - break; // LTE okay, new_step for next step - } - } - } - - // create solution dictionary - var result = new Array(); - for (var name in this.node_map) { - var index = this.node_map[name]; - result[name] = (index == -1) ? 0 : response[index]; - } - // capture branch currents from voltage sources - for (var i = this.voltage_sources.length - 1; i >= 0; --i) { - var v = this.voltage_sources[i]; - result['I('+v.name+')'] = response[v.branch]; - } - - result['_time_'] = response[this.N]; - return result; - } - - // AC analysis: npts/decade for freqs in range [fstart,fstop] - // result['_frequencies_'] = vector of log10(sample freqs) - // result['xxx'] = vector of dB(response for node xxx) - // NOTE: Normalization removed in schematic.js, jkw. - Circuit.prototype.ac = function(npts,fstart,fstop,source_name) { - if (this.diddc == false) this.dc(); - - var N = this.N; - var G = this.G; - var C = this.C; - - // Complex numbers, we're going to need a bigger boat - var matrixac = this.make_mat(2*N, (2*N)+1); - - // Get the source used for ac - if (this.device_map[source_name] === undefined) { - alert('AC analysis refers to unknown source ' + source_name); - return 'AC analysis failed, unknown source'; - } - this.device_map[source_name].load_ac(this,this.rhs); - - // build array to hold list of results for each node - // last entry is for frequency values - var response = new Array(N + 1); - for (var i = N; i >= 0; --i) response[i] = new Array(); - - // multiplicative frequency increase between freq points - var delta_f = Math.exp(Math.LN10/npts); - - var f = fstart; - fstop *= 1.0001; // capture that last time point! - while (f <= fstop) { - var omega = 2 * Math.PI * f; - response[this.N].push(f); - - // Find complex x+jy that sats Gx-omega*Cy=rhs; omega*Cx+Gy=0 - // Note: solac[0:N-1]=x, solac[N:2N-1]=y - for (var i = N-1; i >= 0; --i) { - // First the rhs, replicated for real and imaginary - matrixac[i][2*N] = this.rhs[i]; - matrixac[i+N][2*N] = 0; - - for (var j = N-1; j >= 0; --j) { - matrixac[i][j] = G[i][j]; - matrixac[i+N][j+N] = G[i][j]; - matrixac[i][j+N] = -omega*C[i][j]; - matrixac[i+N][j] = omega*C[i][j]; - } - } - - // Compute the small signal response - var solac = solve_linear_system(matrixac); - - // Save just the magnitude for now - for (var i = this.N - 1; i >= 0; --i) { - var mag = Math.sqrt(solac[i]*solac[i] + solac[i+N]*solac[i+N]); - response[i].push(mag); - } - f *= delta_f; // increment frequency - } - - // create solution dictionary - var result = new Array(); - for (var name in this.node_map) { - var index = this.node_map[name]; - result[name] = (index == -1) ? 0 : response[index]; - } - result['_frequencies_'] = response[this.N]; - return result; - } - - - // Helper for adding devices to a circuit, warns on duplicate device names. - Circuit.prototype.add_device = function(d,name) { - // Add device to list of devices and to device map - this.devices.push(d); - d.name = name; - if (name) { - if (this.device_map[name] === undefined) - this.device_map[name] = d; - else { - alert('Warning: two circuit elements share the same name ' + name); - this.device_map[name] = d; - } - } - return d; - } - - Circuit.prototype.r = function(n1,n2,v,name) { - // try to convert string value into numeric value, barf if we can't - if ((typeof v) == 'string') { - v = parse_number(v,undefined); - if (v === undefined) return undefined; - } - - if (v != 0) { - var d = new Resistor(n1,n2,v); - return this.add_device(d, name); - } else return this.v(n1,n2,0,name); // zero resistance == 0V voltage source - } - - Circuit.prototype.d = function(n1,n2,area,name) { - // try to convert string value into numeric value, barf if we can't - if ((typeof area) == 'string') { - area = parse_number(area,undefined); - if (area === undefined) return undefined; - } - - if (area != 0) { - var d = new Diode(n1,n2,area); - return this.add_device(d, name); - } // zero area diodes discarded. - } - - - Circuit.prototype.c = function(n1,n2,v,name) { - // try to convert string value into numeric value, barf if we can't - if ((typeof v) == 'string') { - v = parse_number(v,undefined); - if (v === undefined) return undefined; - } - var d = new Capacitor(n1,n2,v); - return this.add_device(d, name); - } - - Circuit.prototype.l = function(n1,n2,v,name) { - // try to convert string value into numeric value, barf if we can't - if ((typeof v) == 'string') { - v = parse_number(v,undefined); - if (v === undefined) return undefined; - } - var branch = this.node(undefined,T_CURRENT); - var d = new Inductor(n1,n2,branch,v); - return this.add_device(d, name); - } - - Circuit.prototype.v = function(n1,n2,v,name) { - var branch = this.node(undefined,T_CURRENT); - var d = new VSource(n1,n2,branch,v); - this.voltage_sources.push(d); - return this.add_device(d, name); - } - - Circuit.prototype.i = function(n1,n2,v,name) { - var d = new ISource(n1,n2,v); - return this.add_device(d, name); - } - - Circuit.prototype.opamp = function(np,nn,no,ng,A,name) { - // try to convert string value into numeric value, barf if we can't - if ((typeof A) == 'string') { - ratio = parse_number(A,undefined); - if (A === undefined) return undefined; - } - var branch = this.node(undefined,T_CURRENT); - var d = new Opamp(np,nn,no,ng,branch,A,name); - return this.add_device(d, name); - } - - Circuit.prototype.n = function(d,g,s, ratio, name) { - // try to convert string value into numeric value, barf if we can't - if ((typeof ratio) == 'string') { - ratio = parse_number(ratio,undefined); - if (ratio === undefined) return undefined; - } - var d = new Fet(d,g,s,ratio,name,'n'); - return this.add_device(d, name); - } - - Circuit.prototype.p = function(d,g,s, ratio, name) { - // try to convert string value into numeric value, barf if we can't - if ((typeof ratio) == 'string') { - ratio = parse_number(ratio,undefined); - if (ratio === undefined) return undefined; - } - var d = new Fet(d,g,s,ratio,name,'p'); - return this.add_device(d, name); - } - - /////////////////////////////////////////////////////////////////////////////// - // - // Support for creating and solving a system of linear equations - // - //////////////////////////////////////////////////////////////////////////////// - - // model circuit using a linear system of the form Ax = b where - // A is an nxn matrix of conductances and branch voltages - // b is an n-element vector of sources - // x is an n-element vector of unknowns (node voltages, branch currents) - - // Knowns (A and b) are stored in an augmented matrix M = [A | b] - // Matrix is stored as an array of arrays: M[row][col]. - - // Allocate an NxM matrix - Circuit.prototype.make_mat = function(N,M) { - var mat = new Array(N); - for (var i = N - 1; i >= 0; --i) { - mat[i] = new Array(M); - for (var j = M - 1; j >= 0; --j) { - mat[i][j] = 0.0; - } - } - return mat; - } - - // Form b = scale*Mx - Circuit.prototype.matv_mult = function(M,x,b,scale) { - var n = M.length; - var m = M[0].length; - - if (n != b.length || m != x.length) - throw 'Rows of M mismatched to b or cols mismatch to x.'; - - for (var i = 0; i < n; i++) { - var temp = 0; - for (var j = 0; j < m; j++) temp += M[i][j]*x[j]; - b[i] = scale*temp; // Recall the neg in the name - } - } - - // C = scalea*A + scaleb*B, scalea, scaleb eithers numbers or arrays (row scaling) - Circuit.prototype.mat_scale_add = function(A, B, scalea, scaleb, C) { - var n = A.length; - var m = A[0].length; - - if (n > B.length || m > B[0].length) - throw 'Row or columns of A to large for B'; - if (n > C.length || m > C[0].length) - throw 'Row or columns of A to large for C'; - if ((typeof scalea == 'number') && (typeof scaleb == 'number')) - for (var i = 0; i < n; i++) - for (var j = 0; j < m; j++) - C[i][j] = scalea*A[i][j] + scaleb*B[i][j]; - else if ((typeof scaleb == 'number') && (scalea instanceof Array)) - for (var i = 0; i < n; i++) - for (var j = 0; j < m; j++) - C[i][j] = scalea[i]*A[i][j] + scaleb*B[i][j]; - else if ((typeof scaleb instanceof Array) && (scalea instanceof Array)) - for (var i = 0; i < n; i++) - for (var j = 0; j < m; j++) - C[i][j] = scalea[i]*A[i][j] + scaleb[i]*B[i][j]; - else - throw 'scalea and scaleb must be scalars or Arrays'; - } - - // Returns a vector of ones and zeros, ones denote zero rows in M - Circuit.prototype.zero_row = function(M) { - var N = M.length - var one_if_zero = new Array(N); - for (var i = N-1; i >= 0; i--) - if ((Math.max.apply(Math, M[i]) == 0) - && (Math.min.apply(Math, M[i]) == 0)) - one_if_zero[i] = 1.0; - else one_if_zero[i] = 0.0; - return one_if_zero; - } - - // Copy A -> using the bounds of A - Circuit.prototype.copy_mat = function(src,dest) { - var n = src.length; - var m = src[0].length; - if (n > dest.length || m > dest[0].length) - throw 'Rows or cols > rows or cols of dest'; - - for (var i = 0; i < n; i++) - for (var j = 0; j < m; j++) - dest[i][j] = src[i][j]; - } - - // add val component between two nodes to matrix M - // Index of -1 refers to ground node - Circuit.prototype.add_two_terminal = function(i,j,g,M) { - if (i >= 0) { - M[i][i] += g; - if (j >= 0) { - M[i][j] -= g; - M[j][i] -= g; - M[j][j] += g; - } - } else if (j >= 0) - M[j][j] += g; - } - - // add val component between two nodes to matrix M - // Index of -1 refers to ground node - Circuit.prototype.get_two_terminal = function(i,j,x) { - var xi_minus_xj = 0; - if (i >= 0) xi_minus_xj = x[i]; - if (j >= 0) xi_minus_xj -= x[j]; - return xi_minus_xj - } - - Circuit.prototype.add_conductance_l = function(i,j,g) { - this.add_two_terminal(i,j,g, this.Gl) - } - - Circuit.prototype.add_conductance = function(i,j,g) { - this.add_two_terminal(i,j,g, this.G) - } - - Circuit.prototype.add_capacitance = function(i,j,c) { - this.add_two_terminal(i,j,c,this.C) - } - - // add individual conductance to Gl matrix - Circuit.prototype.add_to_Gl = function(i,j,g) { - if (i >=0 && j >= 0) - this.Gl[i][j] += g; - } - - // add individual conductance to Gl matrix - Circuit.prototype.add_to_G = function(i,j,g) { - if (i >=0 && j >= 0) - this.G[i][j] += g; - } - - // add individual capacitance to C matrix - Circuit.prototype.add_to_C = function(i,j,c) { - if (i >=0 && j >= 0) - this.C[i][j] += c; - } - - // add source info to rhs - Circuit.prototype.add_to_rhs = function(i,v,rhs) { - if (i >= 0) rhs[i] += v; - } - - // solve Ax=b and return vector x given augmented matrix M = [A | b] - // Uses Gaussian elimination with partial pivoting - function solve_linear_system(M,rhs) { - var N = M.length; // augmented matrix M has N rows, N+1 columns - var temp,i,j; - - // Copy the rhs in to the last column of M if one is given. - if (rhs != null) { - for (var row = 0; row < N ; row++) - M[row][N] = rhs[row]; - } - - // gaussian elimination - for (var col = 0; col < N ; col++) { - // find pivot: largest abs(v) in this column of remaining rows - var max_v = Math.abs(M[col][col]); - var max_col = col; - for (i = col + 1; i < N; i++) { - temp = Math.abs(M[i][col]); - if (temp > max_v) { max_v = temp; max_col = i; } - } - - // if no value found, generate a small conductance to gnd - // otherwise swap current row with pivot row - if (max_v == 0) M[col][col] = 1e-10; - else { - temp = M[col]; - M[col] = M[max_col]; - M[max_col] = temp; - } - - // now eliminate this column for all subsequent rows - for (i = col + 1; i < N; i++) { - temp = M[i][col]/M[col][col]; // multiplier we'll use for current row - if (temp != 0) - // subtract current row from row we're working on - // remember to process b too! - for (j = col; j <= N; j++) M[i][j] -= M[col][j]*temp; - } - } - - // matrix is now upper triangular, so solve for elements of x starting - // with the last row - var x = new Array(N); - for (i = N-1; i >= 0; --i) { - temp = M[i][N]; // grab b[i] from augmented matrix as RHS - // subtract LHS term from RHS using known x values - for (j = N-1; j > i; --j) temp -= M[i][j]*x[j]; - // now compute new x value - x[i] = temp/M[i][i]; - } - - // return solution - return x; - } - - // test solution code, expect x = [2,3,-1] - //M = [[2,1,-1,8],[-3,-1,2,-11],[-2,1,2,-3]]; - //x = solve_linear_system(M); - //y = 1; // so we have place to set a breakpoint :) - - /////////////////////////////////////////////////////////////////////////////// - // - // Device base class - // - //////////////////////////////////////////////////////////////////////////////// - - function Device() { - } - - // complete initial set up of device - Device.prototype.finalize = function() { - } - - // Load the linear elements in to Gl and C - Device.prototype.load_linear = function(ckt) { - } - - // load linear system equations for dc analysis - // (inductors shorted and capacitors opened) - Device.prototype.load_dc = function(ckt,soln,rhs) { - } - - // load linear system equations for tran analysis - Device.prototype.load_tran = function(ckt,soln) { - } - - // load linear system equations for ac analysis: - // current sources open, voltage sources shorted - // linear models at operating point for everyone else - Device.prototype.load_ac = function(ckt,rhs) { - } - - // return time of next breakpoint for the device - Device.prototype.breakpoint = function(time) { - return undefined; - } - - /////////////////////////////////////////////////////////////////////////////// - // - // Parse numbers in engineering notation - // - /////////////////////////////////////////////////////////////////////////////// - - // convert first character of argument into an integer - function ord(ch) { - return ch.charCodeAt(0); - } - - // convert string argument to a number, accepting usual notations - // (hex, octal, binary, decimal, floating point) plus engineering - // scale factors (eg, 1k = 1000.0 = 1e3). - // return default if argument couldn't be interpreted as a number - function parse_number(s,default_v) { - var slen = s.length; - var multiplier = 1; - var result = 0; - var index = 0; - - // skip leading whitespace - while (index < slen && s.charAt(index) <= ' ') index += 1; - if (index == slen) return default_v; - - // check for leading sign - if (s.charAt(index) == '-') { - multiplier = -1; - index += 1; - } else if (s.charAt(index) == '+') - index += 1; - var start = index; // remember where digits start - - // if leading digit is 0, check for hex, octal or binary notation - if (index >= slen) return default_v; - else if (s.charAt(index) == '0') { - index += 1; - if (index >= slen) return 0; - if (s.charAt(index) == 'x' || s.charAt(index) == 'X') { // hex - while (true) { - index += 1; - if (index >= slen) break; - if (s.charAt(index) >= '0' && s.charAt(index) <= '9') - result = result*16 + ord(s.charAt(index)) - ord('0'); - else if (s.charAt(index) >= 'A' && s.charAt(index) <= 'F') - result = result*16 + ord(s.charAt(index)) - ord('A') + 10; - else if (s.charAt(index) >= 'a' && s.charAt(index) <= 'f') - result = result*16 + ord(s.charAt(index)) - ord('a') + 10; - else break; - } - return result*multiplier; - } else if (s.charAt(index) == 'b' || s.charAt(index) == 'B') { // binary - while (true) { - index += 1; - if (index >= slen) break; - if (s.charAt(index) >= '0' && s.charAt(index) <= '1') - result = result*2 + ord(s.charAt(index)) - ord('0'); - else break; - } - return result*multiplier; - } else if (s.charAt(index) != '.') { // octal - while (true) { - if (s.charAt(index) >= '0' && s.charAt(index) <= '7') - result = result*8 + ord(s.charAt(index)) - ord('0'); - else break; - index += 1; - if (index >= slen) break; - } - return result*multiplier; - } - } - - // read decimal integer or floating-point number - while (true) { - if (s.charAt(index) >= '0' && s.charAt(index) <= '9') - result = result*10 + ord(s.charAt(index)) - ord('0'); - else break; - index += 1; - if (index >= slen) break; - } - - // fractional part? - if (index < slen && s.charAt(index) == '.') { - while (true) { - index += 1; - if (index >= slen) break; - if (s.charAt(index) >= '0' && s.charAt(index) <= '9') { - result = result*10 + ord(s.charAt(index)) - ord('0'); - multiplier *= 0.1; - } else break; - } - } - - // if we haven't seen any digits yet, don't check - // for exponents or scale factors - if (index == start) return default_v; - - // type of multiplier determines type of result: - // multiplier is a float if we've seen digits past - // a decimal point, otherwise it's an int or long. - // Up to this point result is an int or long. - result *= multiplier; - - // now check for exponent or engineering scale factor. If there - // is one, result will be a float. - if (index < slen) { - var scale = s.charAt(index); - index += 1; - if (scale == 'e' || scale == 'E') { - var exponent = 0; - multiplier = 10.0; - if (index < slen) { - if (s.charAt(index) == '+') index += 1; - else if (s.charAt(index) == '-') { - index += 1; - multiplier = 0.1; - } - } - while (index < slen) { - if (s.charAt(index) >= '0' && s.charAt(index) <= '9') { - exponent = exponent*10 + ord(s.charAt(index)) - ord('0'); - index += 1; - } else break; - } - while (exponent > 0) { - exponent -= 1; - result *= multiplier; - } - } else if (scale == 't' || scale == 'T') result *= 1e12; - else if (scale == 'g' || scale == 'G') result *= 1e9; - else if (scale == 'M') result *= 1e6; - else if (scale == 'k' || scale == 'K') result *= 1e3; - else if (scale == 'm') result *= 1e-3; - else if (scale == 'u' || scale == 'U') result *= 1e-6; - else if (scale == 'n' || scale == 'N') result *= 1e-9; - else if (scale == 'p' || scale == 'P') result *= 1e-12; - else if (scale == 'f' || scale == 'F') result *= 1e-15; - } - // ignore any remaining chars, eg, 1kohms returns 1000 - return result; - } - - Circuit.prototype.parse_number = parse_number; // make it easy to call from outside - - /////////////////////////////////////////////////////////////////////////////// - // - // Sources - // - /////////////////////////////////////////////////////////////////////////////// - - // argument is a string describing the source's value (see comments for details) - // source types: dc,step,square,triangle,sin,pulse,pwl,pwl_repeating - - // returns an object with the following attributes: - // fun -- name of source function - // args -- list of argument values - // value(t) -- compute source value at time t - // inflection_point(t) -- compute time after t when a time point is needed - // dc -- value at time 0 - - function parse_source(v) { - // generic parser: parse v as either or (,...) - var src = new Object(); - src.value = function(t) { return 0; } // overridden below - src.inflection_point = function(t) { return undefined; }; // may be overridden below - - // see if there's a "(" in the description - var index = v.indexOf('('); - var ch; - if (index >= 0) { - src.fun = v.slice(0,index); // function name is before the "(" - src.args = []; // we'll push argument values onto this list - var end = v.indexOf(')',index); - if (end == -1) end = v.length; - - index += 1; // start parsing right after "(" - while (index < end) { - // figure out where next argument value starts - ch = v.charAt(index); - if (ch <= ' ') { index++; continue; } - // and where it ends - var arg_end = v.indexOf(',',index); - if (arg_end == -1) arg_end = end; - // parse and save result in our list of arg values - src.args.push(parse_number(v.slice(index,arg_end),undefined)); - index = arg_end + 1; - } - } else { - src.fun = 'dc'; - src.args = [parse_number(v,0)]; - } - - // post-processing for constant sources - // dc(v) - if (src.fun == 'dc') { - var v = arg_value(src.args,0,0); - src.args = [v]; - src.value = function(t) { return v; } // closure - } - - // post-processing for impulse sources - // impulse(height,width) - else if (src.fun == 'impulse') { - var h = arg_value(src.args,0,1); // default height: 1 - var w = Math.abs(arg_value(src.args,2,1e-9)); // default width: 1ns - src.args = [h,w]; // remember any defaulted values - pwl_source(src,[0,0,w/2,h,w,0],false); - } - - // post-processing for step sources - // step(v_init,v_plateau,t_delay,t_rise) - else if (src.fun == 'step') { - var v1 = arg_value(src.args,0,0); // default init value: 0V - var v2 = arg_value(src.args,1,1); // default plateau value: 1V - var td = Math.max(0,arg_value(src.args,2,0)); // time step starts - var tr = Math.abs(arg_value(src.args,3,1e-9)); // default rise time: 1ns - src.args = [v1,v2,td,tr]; // remember any defaulted values - pwl_source(src,[td,v1,td+tr,v2],false); - } - - // post-processing for square wave - // square(v_init,v_plateau,freq) - else if (src.fun == 'square') { - var v1 = arg_value(src.args,0,0); // default init value: 0V - var v2 = arg_value(src.args,1,1); // default plateau value: 1V - var freq = Math.abs(arg_value(src.args,2,1)); // default frequency: 1Hz - src.args = [v1,v2,freq]; // remember any defaulted values - - var per = freq == 0 ? Infinity : 1/freq; - var t_change = 0.01 * per; // rise and fall time - var t_pw = 0.49 * per; // half the cycle minus rise and fall time - pwl_source(src,[0,v1,t_change,v2,t_change+t_pw, - v2,t_change+t_pw+t_change,v1,per,v1],true); - } - - // post-processing for triangle - // triangle(v_init,v_plateua,t_period) - else if (src.fun == 'triangle') { - var v1 = arg_value(src.args,0,0); // default init value: 0V - var v2 = arg_value(src.args,1,1); // default plateau value: 1V - var freq = Math.abs(arg_value(src.args,2,1)); // default frequency: 1s - src.args = [v1,v2,freq]; // remember any defaulted values - - var per = freq == 0 ? Infinity : 1/freq; - pwl_source(src,[0,v1,per/2,v2,per,v1],true); - } - - // post-processing for pwl and pwlr sources - // pwl[r](t1,v1,t2,v2,...) - else if (src.fun == 'pwl' || src.fun == 'pwl_repeating') { - pwl_source(src,src.args,src.fun == 'pwl_repeating'); - } - - // post-processing for pulsed sources - // pulse(v_init,v_plateau,t_delay,t_rise,t_fall,t_width,t_period) - else if (src.fun == 'pulse') { - var v1 = arg_value(src.args,0,0); // default init value: 0V - var v2 = arg_value(src.args,1,1); // default plateau value: 1V - var td = Math.max(0,arg_value(src.args,2,0)); // time pulse starts - var tr = Math.abs(arg_value(src.args,3,1e-9)); // default rise time: 1ns - var tf = Math.abs(arg_value(src.args,4,1e-9)); // default rise time: 1ns - var pw = Math.abs(arg_value(src.args,5,1e9)); // default pulse width: "infinite" - var per = Math.abs(arg_value(src.args,6,1e9)); // default period: "infinite" - src.args = [v1,v2,td,tr,tf,pw,per]; - - var t1 = td; // time when v1 -> v2 transition starts - var t2 = t1 + tr; // time when v1 -> v2 transition ends - var t3 = t2 + pw; // time when v2 -> v1 transition starts - var t4 = t3 + tf; // time when v2 -> v1 transition ends - - pwl_source(src,[t1,v1, t2,v2, t3,v2, t4,v1, per,v1],true); - } - - // post-processing for sinusoidal sources - // sin(v_offset,v_amplitude,freq_hz,t_delay,phase_offset_degrees) - else if (src.fun == 'sin') { - var voffset = arg_value(src.args,0,0); // default offset voltage: 0V - var va = arg_value(src.args,1,1); // default amplitude: -1V to 1V - var freq = Math.abs(arg_value(src.args,2,1)); // default frequency: 1Hz - var td = Math.max(0,arg_value(src.args,3,0)); // default time delay: 0sec - var phase = arg_value(src.args,4,0); // default phase offset: 0 degrees - src.args = [voffset,va,freq,td,phase]; - - phase /= 360.0; - - // return value of source at time t - src.value = function(t) { // closure - if (t < td) return voffset + va*Math.sin(2*Math.PI*phase); - else return voffset + va*Math.sin(2*Math.PI*(freq*(t - td) + phase)); - } - - // return time of next inflection point after time t - src.inflection_point = function(t) { // closure - if (t < td) return td; - else return undefined; - } - } - - // object has all the necessary info to compute the source value and inflection points - src.dc = src.value(0); // DC value is value at time 0 - return src; - } - - function pwl_source(src,tv_pairs,repeat) { - var nvals = tv_pairs.length; - if (nvals % 2 == 1) npts -= 1; // make sure it's even! - - if (nvals <= 2) { - // handle degenerate case - src.value = function(t) { return nvals == 2 ? tv_pairs[1] : 0; } - src.inflection_point = function(t) { return undefined; } - } else { - src.value = function(t) { // closure - if (repeat) - // make time periodic if values are to be repeated - t = Math.fmod(t,tv_pairs[nvals-2]); - var last_t = tv_pairs[0]; - var last_v = tv_pairs[1]; - if (t > last_t) { - var next_t,next_v; - for (var i = 2; i < nvals; i += 2) { - next_t = tv_pairs[i]; - next_v = tv_pairs[i+1]; - if (next_t > last_t) // defend against bogus tv pairs - if (t < next_t) - return last_v + (next_v - last_v)*(t - last_t)/(next_t - last_t); - last_t = next_t; - last_v = next_v; - } - } - return last_v; - } - src.inflection_point = function(t) { // closure - if (repeat) - // make time periodic if values are to be repeated - t = Math.fmod(t,tv_pairs[nvals-2]); - for (var i = 0; i < nvals; i += 2) { - var next_t = tv_pairs[i]; - if (t < next_t) return next_t; - } - return undefined; - } - } - } - - // helper function: return args[index] if present, else default_v - function arg_value(args,index,default_v) { - if (index < args.length) { - var result = args[index]; - if (result === undefined) result = default_v; - return result; - } else return default_v; - } - - // we need fmod in the Math library! - Math.fmod = function(numerator,denominator) { - var quotient = Math.floor(numerator/denominator); - return numerator - quotient*denominator; - } - - /////////////////////////////////////////////////////////////////////////////// - // - // Sources - // - /////////////////////////////////////////////////////////////////////////////// - - function VSource(npos,nneg,branch,v) { - Device.call(this); - - this.src = parse_source(v); - this.npos = npos; - this.nneg = nneg; - this.branch = branch; - } - VSource.prototype = new Device(); - VSource.prototype.constructor = VSource; - - // load linear part for source evaluation - VSource.prototype.load_linear = function(ckt) { - // MNA stamp for independent voltage source - ckt.add_to_Gl(this.branch,this.npos,1.0); - ckt.add_to_Gl(this.branch,this.nneg,-1.0); - ckt.add_to_Gl(this.npos,this.branch,1.0); - ckt.add_to_Gl(this.nneg,this.branch,-1.0); - } - - // Source voltage added to b. - VSource.prototype.load_dc = function(ckt,soln,rhs) { - ckt.add_to_rhs(this.branch,this.src.dc,rhs); - } - - // Load time-dependent value for voltage source for tran - VSource.prototype.load_tran = function(ckt,soln,rhs,time) { - ckt.add_to_rhs(this.branch,this.src.value(time),rhs); - } - - // return time of next breakpoint for the device - VSource.prototype.breakpoint = function(time) { - return this.src.inflection_point(time); - } - - // small signal model ac value - VSource.prototype.load_ac = function(ckt,rhs) { - ckt.add_to_rhs(this.branch,1.0,rhs); - } - - function ISource(npos,nneg,v) { - Device.call(this); - - this.src = parse_source(v); - this.npos = npos; - this.nneg = nneg; - } - ISource.prototype = new Device(); - ISource.prototype.constructor = ISource; - - // load linear system equations for dc analysis - ISource.prototype.load_dc = function(ckt,soln,rhs) { - var is = this.src.dc; - - // MNA stamp for independent current source - ckt.add_to_rhs(this.npos,-is,rhs); // current flow into npos - ckt.add_to_rhs(this.nneg,is,rhs); // and out of nneg - } - - // load linear system equations for tran analysis (just like DC) - ISource.prototype.load_tran = function(ckt,soln,rhs,time) { - var is = this.src.value(time); - - // MNA stamp for independent current source - ckt.add_to_rhs(this.npos,-is,rhs); // current flow into npos - ckt.add_to_rhs(this.nneg,is,rhs); // and out of nneg - } - - // return time of next breakpoint for the device - ISource.prototype.breakpoint = function(time) { - return this.src.inflection_point(time); - } - - // small signal model: open circuit - ISource.prototype.load_ac = function(ckt) { - // MNA stamp for independent current source - ckt.add_to_rhs(this.npos,-1.0,rhs); // current flow into npos - ckt.add_to_rhs(this.nneg,1.0,rhs); // and out of nneg - } - - /////////////////////////////////////////////////////////////////////////////// - // - // Resistor - // - /////////////////////////////////////////////////////////////////////////////// - - function Resistor(n1,n2,v) { - Device.call(this); - this.n1 = n1; - this.n2 = n2; - this.g = 1.0/v; - } - Resistor.prototype = new Device(); - Resistor.prototype.constructor = Resistor; - - Resistor.prototype.load_linear = function(ckt) { - // MNA stamp for admittance g - ckt.add_conductance_l(this.n1,this.n2,this.g); - } - - Resistor.prototype.load_dc = function(ckt) { - // Nothing to see here, move along. - } - - Resistor.prototype.load_tran = function(ckt,soln) { - } - - Resistor.prototype.load_ac = function(ckt) { - } - - /////////////////////////////////////////////////////////////////////////////// - // - // Diode - // - /////////////////////////////////////////////////////////////////////////////// - - function Diode(n1,n2,v) { - Device.call(this); - this.anode = n1; - this.cathode = n2; - this.area = v; - this.is = 1.0e-14; - this.ais = this.area * this.is; - this.vt = 2.58e-2; // 26 millivolts - } - Diode.prototype = new Device(); - Diode.prototype.constructor = Diode; - - Diode.prototype.load_linear = function(ckt) { - // Diode is not linear, has no linear piece. - } - - Diode.prototype.load_dc = function(ckt,soln,rhs) { - var vd = ckt.get_two_terminal(this.anode, this.cathode, soln); - var temp1 = this.ais * Math.exp(vd / this.vt); - var id = temp1 - this.ais; - var gd = temp1 / this.vt - - // MNA stamp for independent current source - ckt.add_to_rhs(this.anode,-id,rhs); // current flows into anode - ckt.add_to_rhs(this.cathode,id,rhs); // and out of cathode - ckt.add_conductance(this.anode,this.cathode,gd); - } - - Diode.prototype.load_tran = function(ckt,soln,rhs,time) { - this.load_dc(ckt,soln,rhs); - } - - Diode.prototype.load_ac = function(ckt) { - } - - - /////////////////////////////////////////////////////////////////////////////// - // - // Capacitor - // - /////////////////////////////////////////////////////////////////////////////// - - function Capacitor(n1,n2,v) { - Device.call(this); - this.n1 = n1; - this.n2 = n2; - this.value = v; - } - Capacitor.prototype = new Device(); - Capacitor.prototype.constructor = Capacitor; - - Capacitor.prototype.load_linear = function(ckt) { - // MNA stamp for capacitance matrix - ckt.add_capacitance(this.n1,this.n2,this.value); - } - - Capacitor.prototype.load_dc = function(ckt,soln,rhs) { - } - - Capacitor.prototype.load_ac = function(ckt) { - } - - Capacitor.prototype.load_tran = function(ckt) { - } - - /////////////////////////////////////////////////////////////////////////////// - // - // Inductor - // - /////////////////////////////////////////////////////////////////////////////// - - function Inductor(n1,n2,branch,v) { - Device.call(this); - this.n1 = n1; - this.n2 = n2; - this.branch = branch; - this.value = v; - } - Inductor.prototype = new Device(); - Inductor.prototype.constructor = Inductor; - - Inductor.prototype.load_linear = function(ckt) { - // MNA stamp for inductor linear part - // L on diag of C because L di/dt = v(n1) - v(n2) - ckt.add_to_Gl(this.n1,this.branch,1); - ckt.add_to_Gl(this.n2,this.branch,-1); - ckt.add_to_Gl(this.branch,this.n1,-1); - ckt.add_to_Gl(this.branch,this.n2,1); - ckt.add_to_C(this.branch,this.branch,this.value) - } - - Inductor.prototype.load_dc = function(ckt,soln,rhs) { - // Inductor is a short at dc, so is linear. - } - - Inductor.prototype.load_ac = function(ckt) { - } - - Inductor.prototype.load_tran = function(ckt) { - } - - - - /////////////////////////////////////////////////////////////////////////////// - // - // Simple Voltage-Controlled Voltage Source Op Amp model - // - /////////////////////////////////////////////////////////////////////////////// - - function Opamp(np,nn,no,ng,branch,A,name) { - Device.call(this); - this.np = np; - this.nn = nn; - this.no = no; - this.ng = ng; - this.branch = branch; - this.gain = A; - this.name = name; - } - - Opamp.prototype = new Device(); - Opamp.prototype.constructor = Opamp; - - Opamp.prototype.load_linear = function(ckt) { - // MNA stamp for VCVS: 1/A(v(no) - v(ng)) - (v(np)-v(nn))) = 0. - var invA = 1.0/this.gain; - ckt.add_to_Gl(this.no,this.branch,1); - ckt.add_to_Gl(this.ng,this.branch,-1); - ckt.add_to_Gl(this.branch,this.no,invA); - ckt.add_to_Gl(this.branch,this.ng,-invA); - ckt.add_to_Gl(this.branch,this.np,-1); - ckt.add_to_Gl(this.branch,this.nn,1); - } - - Opamp.prototype.load_dc = function(ckt,soln,rhs) { - // Op-amp is linear. - } - - Opamp.prototype.load_ac = function(ckt) { - } - - Opamp.prototype.load_tran = function(ckt) { - } - - - - /////////////////////////////////////////////////////////////////////////////// - // - // Simplified MOS FET with no bulk connection and no body effect. - // - /////////////////////////////////////////////////////////////////////////////// - - - function Fet(d,g,s,ratio,name,type) { - Device.call(this); - this.d = d; - this.g = g; - this.s = s; - this.name = name; - this.ratio = ratio; - if (type != 'n' && type != 'p') - { throw 'fet type is not n or p'; - } - this.type_sign = (type == 'n') ? 1 : -1; - this.vt = 0.5; - this.kp = 20e-6; - this.beta = this.kp * this.ratio; - this.lambda = 0.05; - } - Fet.prototype = new Device(); - Fet.prototype.constructor = Fet; - - Fet.prototype.load_linear = function(ckt) { - // FET's are nonlinear, just like javascript progammers - } - - Fet.prototype.load_dc = function(ckt,soln,rhs) { - var vds = this.type_sign * ckt.get_two_terminal(this.d, this.s, soln); - if (vds < 0) { // Drain and source have swapped roles - var temp = this.d; - this.d = this.s; - this.s = temp; - vds = this.type_sign * ckt.get_two_terminal(this.d, this.s, soln); - } - var vgs = this.type_sign * ckt.get_two_terminal(this.g, this.s, soln); - var vgst = vgs - this.vt; - with (this) { - var gmgs,ids,gds; - if (vgst > 0.0 ) { // vgst < 0, transistor off, no subthreshold here. - if (vgst < vds) { /* Saturation. */ - gmgs = beta * (1 + (lambda * vds)) * vgst; - ids = type_sign * 0.5 * gmgs * vgst; - gds = 0.5 * beta * vgst * vgst * lambda; - } else { /* Linear region */ - gmgs = beta * (1 + lambda * vds); - ids = type_sign * gmgs * vds * (vgst - 0.50 * vds); - gds = gmgs * (vgst - vds) + beta * lambda * vds * (vgst - 0.5 * vds); - gmgs *= vds; - } - ckt.add_to_rhs(d,-ids,rhs); // current flows into the drain - ckt.add_to_rhs(s, ids,rhs); // and out the source - ckt.add_conductance(d,s,gds); - ckt.add_to_G(s,s, gmgs); - ckt.add_to_G(d,s,-gmgs); - ckt.add_to_G(d,g, gmgs); - ckt.add_to_G(s,g,-gmgs); - } - } - } - - Fet.prototype.load_tran = function(ckt,soln,rhs) { - this.load_dc(ckt,soln,rhs); - } - - Fet.prototype.load_ac = function(ckt) { - } - - - /////////////////////////////////////////////////////////////////////////////// - // - // Module definition - // - /////////////////////////////////////////////////////////////////////////////// - var module = { - 'Circuit': Circuit, - 'parse_number': parse_number, - 'parse_source': parse_source, - } - return module; - }()); diff --git a/js/cktsim.js b/js/cktsim.js new file mode 120000 index 0000000000..ccca600650 --- /dev/null +++ b/js/cktsim.js @@ -0,0 +1 @@ +../../data/js/cktsim.js \ No newline at end of file diff --git a/js/schematic.js b/js/schematic.js deleted file mode 100644 index a9613baef0..0000000000 --- a/js/schematic.js +++ /dev/null @@ -1,3535 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// -// Simple schematic capture -// -//////////////////////////////////////////////////////////////////////////////// - -// Copyright (C) 2011 Massachusetts Institute of Technology - -// add schematics to a document with -// -// -// -// other attributes you can add to the input tag: -// width -- width in pixels of diagram -// height -- height in pixels of diagram -// parts -- comma-separated list of parts for parts bin (see parts_map), -// parts="" disables editing of diagram - -// JSON schematic representation: -// sch := [part, part, ...] -// part := [type, coords, properties, connections] -// type := string (see parts_map) -// coords := [number, ...] // (x,y,rot) or (x1,y1,x2,y2) -// properties := {name: value, ...} -// connections := [node, ...] // one per connection point in canoncial order -// node := string -// need a netlist? just use the part's type, properites and connections - -// TO DO: -// - wire labels? -// - zoom/scroll canvas -// - rotate multiple objects around their center of mass -// - rubber band wires when moving components - -// set up each schematic entry widget -function update_schematics() { - // set up each schematic on the page - var schematics = document.getElementsByClassName('schematic'); - for (var i = schematics.length - 1; i >= 0; i--) - if (schematics[i].getAttribute("loaded") != "true") { - new schematic.Schematic(schematics[i]); - schematics[i].setAttribute("loaded","true"); - } -} - -// add ourselves to the tasks that get performed when window is loaded -function add_schematic_handler(other_onload) { - return function() { - // execute othe onload functions first - if (other_onload) other_onload(); - - update_schematics(); - } -} -window.onload = add_schematic_handler(window.onload); - -// ask each schematic input widget to update its value field for submission -function prepare_schematics() { - var schematics = document.getElementsByClassName('schematic'); - for (var i = schematics.length - 1; i >= 0; i--) - schematics[i].schematic.update_value(); -} - -schematic = (function() { - background_style = 'rgb(220,220,220)'; - element_style = 'rgb(255,255,255)'; - thumb_style = 'rgb(128,128,128)'; - normal_style = 'rgb(0,0,0)'; // color for unselected components - selected_style = 'rgb(64,255,64)'; // highlight color for selected components - grid_style = "rgb(128,128,128)"; - annotation_style = 'rgb(255,64,64)'; // color for diagram annotations - - property_size = 5; // point size for Component property text - annotation_size = 6; // point size for diagram annotations - - // list of all the defined parts - parts_map = { - 'g': [Ground, 'Ground connection'], - 'L': [Label, 'Node label'], - 'v': [VSource, 'Voltage source'], - 'i': [ISource, 'Current source'], - 'r': [Resistor, 'Resistor'], - 'c': [Capacitor, 'Capacitor'], - 'l': [Inductor, 'Inductor'], - 'o': [OpAmp, 'Op Amp'], - 'd': [Diode, 'Diode'], - 'n': [NFet, 'NFet'], - 'p': [PFet, 'PFet'], - 's': [Probe, 'Scope Probe'], - }; - - // global clipboard - if (typeof sch_clipboard == 'undefined') - sch_clipboard = []; - - /////////////////////////////////////////////////////////////////////////////// - // - // Schematic = diagram + parts bin + status area - // - //////////////////////////////////////////////////////////////////////////////// - - // setup a schematic by populating the
with the appropriate children - function Schematic(input) { - // set up diagram viewing parameters - this.grid = 8; - this.scale = 2; - this.origin_x = input.getAttribute("origin_x"); - if (this.origin_x == undefined) this.origin_x = 0; - this.origin_y = input.getAttribute("origin_y"); - if (this.origin_y == undefined) this.origin_y = 0; - - // use user-supplied list of parts if supplied - // else just populate parts bin with all the parts - this.edits_allowed = true; - var parts = input.getAttribute('parts'); - if (parts == undefined || parts == 'None') { - parts = new Array(); - for (var p in parts_map) parts.push(p); - } else if (parts == '') { - this.edits_allowed = false; - parts = []; - } else parts = parts.split(','); - - // now add the parts to the parts bin - this.parts_bin = []; - for (var i = 0; i < parts.length; i++) { - var part = new Part(this); - var pm = parts_map[parts[i]]; - part.set_component(new pm[0](0,0,0),pm[1]); - this.parts_bin.push(part); - } - - // use user-supplied list of analyses, otherwise provide them all - // analyses="" means no analyses - var analyses = input.getAttribute('analyses'); - if (analyses == undefined || analyses == 'None') - analyses = ['dc','ac','tran']; - else if (analyses == '') analyses = []; - else analyses = analyses.split(','); - - if (parts.length == 0 && analyses.length == 0) this.diagram_only = true; - else this.diagram_only = false; - - // see what we need to submit. Expecting attribute of the form - // submit_analyses="{'tran':[[node_name,t1,t2,t3],...], - // 'ac':[[node_name,f1,f2,...],...]}" - var submit = input.getAttribute('submit_analyses'); - if (submit && submit.indexOf('{') != -1) - this.submit_analyses = JSON.parse(submit); - else - this.submit_analyses = undefined; - - // toolbar - this.tools = new Array(); - this.toolbar = []; - if (this.edits_allowed) { - this.tools['cut'] = this.add_tool(cut_icon,'Cut: move selected components from diagram to the clipboard',this.cut); - this.tools['copy'] = this.add_tool(copy_icon,'Copy: copy selected components into the clipboard',this.copy); - this.tools['paste'] = this.add_tool(paste_icon,'Paste: copy clipboard into the diagram',this.paste); - this.toolbar.push(null); // spacer - } - - // simulation interface if cktsim.js is loaded - if (typeof cktsim != 'undefined') { - if (analyses.indexOf('dc') != -1) { - this.tools['dc'] = this.add_tool('DC','DC Analysis',this.dc_analysis); - this.enable_tool('dc',true); - } - - if (analyses.indexOf('ac') != -1) { - this.tools['ac'] = this.add_tool('AC','AC Small-Signal Analysis',this.setup_ac_analysis); - this.enable_tool('ac',true); - this.ac_npts = '5'; // default values for AC Analysis - this.ac_fstart = '10'; - this.ac_fstop = '10MEG'; - this.ac_source_name = undefined; - } - - if (analyses.indexOf('tran') != -1) { - this.tools['tran'] = this.add_tool('TRAN','Transient Analysis',this.transient_analysis); - this.enable_tool('tran',true); - this.tran_npts = '100'; // default values for transient analysis - this.tran_tstop = '1'; - } - } - - // set up diagram canvas - this.canvas = document.createElement('canvas'); - this.width = input.getAttribute('width'); - this.width = parseInt(this.width == undefined ? '400' : this.width); - this.canvas.width = this.width; - this.height = input.getAttribute('height'); - this.height = parseInt(this.height == undefined ? '300' : this.height); - this.canvas.height = this.height; - - // repaint simply draws this buffer and then adds selected elements on top - this.bg_image = document.createElement('canvas'); - this.bg_image.width = this.width; - this.bg_image.height = this.height; - - if (!this.diagram_only) { - this.canvas.tabIndex = 1; // so we get keystrokes - this.canvas.style.borderStyle = 'solid'; - this.canvas.style.borderWidth = '1px'; - this.canvas.style.borderColor = grid_style; - this.canvas.style.outline = 'none'; - } - - this.canvas.schematic = this; - if (this.edits_allowed) { - this.canvas.addEventListener('mousemove',schematic_mouse_move,false); - this.canvas.addEventListener('mouseover',schematic_mouse_enter,false); - this.canvas.addEventListener('mouseout',schematic_mouse_leave,false); - this.canvas.addEventListener('mousedown',schematic_mouse_down,false); - this.canvas.addEventListener('mouseup',schematic_mouse_up,false); - this.canvas.addEventListener('dblclick',schematic_double_click,false); - this.canvas.addEventListener('keydown',schematic_key_down,false); - this.canvas.addEventListener('keyup',schematic_key_up,false); - } - - // set up message area - if (!this.diagram_only) { - this.status_div = document.createElement('div'); - this.status = document.createTextNode(''); - this.status_div.appendChild(this.status); - this.status_div.style.height = status_height + 'px'; - } else this.status_div = undefined; - - this.connection_points = new Array(); // location string => list of cp's - this.components = []; - - this.dragging = false; - this.drawCursor = false; - this.cursor_x = 0; - this.cursor_y = 0; - this.draw_cursor = undefined; - this.select_rect = undefined; - this.wire = undefined; - - this.operating_point = undefined; // result from DC analysis - this.dc_results = undefined; // saved analysis results for submission - this.ac_results = undefined; // saved analysis results for submission - this.transient_results = undefined; // saved analysis results for submission - - // state of modifier keys - this.ctrlKey = false; - this.shiftKey = false; - this.altKey = false; - this.cmdKey = false; - - // make sure other code can find us! - input.schematic = this; - this.input = input; - - // set up DOM -- use nested tables to do the layout - var table,tr,td; - table = document.createElement('table'); - table.rules = 'none'; - if (!this.diagram_only) { - table.frame = 'box'; - table.style.borderStyle = 'solid'; - table.style.borderWidth = '2px'; - table.style.borderColor = normal_style; - table.style.backgroundColor = background_style; - } - - // add tools to DOM - if (this.toolbar.length > 0) { - tr = document.createElement('tr'); - table.appendChild(tr); - td = document.createElement('td'); - td.style.verticalAlign = 'top'; - td.colSpan = 2; - tr.appendChild(td); - for (var i = 0; i < this.toolbar.length; ++i) { - var tool = this.toolbar[i]; - if (tool != null) td.appendChild(tool); - } - } - - // add canvas and parts bin to DOM - tr = document.createElement('tr'); - table.appendChild(tr); - td = document.createElement('td'); - tr.appendChild(td); - var wrapper = document.createElement('div'); - td.appendChild(wrapper); - wrapper.style.position = 'relative'; // so we can position subwindows - wrapper.appendChild(this.canvas); - td = document.createElement('td'); - td.style.verticalAlign = 'top'; - tr.appendChild(td); - var parts_table = document.createElement('table'); - td.appendChild(parts_table); - parts_table.rules = 'none'; - parts_table.frame = 'void'; - parts_table.cellPadding = '0'; - parts_table.cellSpacing = '0'; - - // fill in parts_table - var parts_per_column = Math.floor(this.height / (part_h + 5)); // mysterious extra padding - for (var i = 0; i < parts_per_column; ++i) { - tr = document.createElement('tr'); - parts_table.appendChild(tr); - for (var j = i; j < this.parts_bin.length; j += parts_per_column) { - td = document.createElement('td'); - tr.appendChild(td); - td.appendChild(this.parts_bin[j].canvas); - } - } - - if (this.status_div != undefined) { - tr = document.createElement('tr'); - table.appendChild(tr); - td = document.createElement('td'); - tr.appendChild(td); - td.colSpan = 2; - td.appendChild(this.status_div); - } - - // add to dom - this.input.parentNode.insertBefore(table,this.input.nextSibling); - - // process initial contents of diagram - this.load_schematic(this.input.getAttribute('value'), - this.input.getAttribute('initial_value')); - } - - part_w = 42; // size of a parts bin compartment - part_h = 42; - status_height = 18; - - Schematic.prototype.add_component = function(new_c) { - this.components.push(new_c); - - // create undoable edit record here - } - - Schematic.prototype.remove_component = function(c) { - var index = this.components.indexOf(c); - if (index != -1) this.components.splice(index,1); - } - - // add connection point to list of connection points at that location - Schematic.prototype.add_connection_point = function(cp) { - var cplist = this.connection_points[cp.location]; - if (cplist) cplist.push(cp); - else { - cplist = [cp]; - this.connection_points[cp.location] = cplist; - } - - // return list of conincident connection points - return cplist; - } - - // remove connection point from the list points at the old location - Schematic.prototype.remove_connection_point = function(cp,old_location) { - // remove cp from list at old location - var cplist = this.connection_points[old_location]; - if (cplist) { - var index = cplist.indexOf(cp); - if (index != -1) { - cplist.splice(index,1); - // if no more connections at this location, remove - // entry from array to keep our search time short - if (cplist.length == 0) - delete this.connection_points[old_location]; - } - } - } - - // connection point has changed location: remove, then add - Schematic.prototype.update_connection_point = function(cp,old_location) { - this.remove_connection_point(cp,old_location); - return this.add_connection_point(cp); - } - - // add a wire to the schematic - Schematic.prototype.add_wire = function(x1,y1,x2,y2) { - var new_wire = new Wire(x1,y1,x2,y2); - new_wire.add(this); - new_wire.move_end(); - return new_wire; - } - - // see if connection points of component c split any wires - Schematic.prototype.check_wires = function(c) { - for (var i = this.components.length - 1; i >=0; --i) { - var cc = this.components[i]; - if (cc != c) { // don't check a component against itself - // only wires will do return non-null from a bisect call - var cp = cc.bisect(c); - if (cp) { - // cc is a wire bisected by connection point cp - - // remove biscted wire - cc.delete(); - - // add two new wires with cp in the middle - this.add_wire(cc.x,cc.y,cp.x,cp.y); - this.add_wire(cc.x+cc.dx,cc.y+cc.dy,cp.x,cp.y); - this.redraw_background(); - break; - } - } - } - } - - Schematic.prototype.unselect_all = function(which) { - this.operating_point = undefined; // remove annotations - - for (var i = this.components.length - 1; i >= 0; --i) - if (i != which) this.components[i].set_select(false); - } - - Schematic.prototype.drag_begin = function() { - // let components know they're about to move - for (var i = this.components.length - 1; i >= 0; --i) { - var component = this.components[i]; - if (component.selected) component.move_begin(); - } - - // remember where drag started - this.drag_x = this.cursor_x; - this.drag_y = this.cursor_y; - this.dragging = true; - } - - Schematic.prototype.drag_end = function() { - // let components know they're done moving - for (var i = this.components.length - 1; i >= 0; --i) { - var component = this.components[i]; - if (component.selected) component.move_end(); - } - this.dragging = false; - } - - Schematic.prototype.cut = function() { - // clear previous contents - sch_clipboard = []; - - // look for selected components, move them to clipboard. - for (var i = this.components.length - 1; i >=0; --i) { - var c = this.components[i]; - if (c.selected) { - c.delete(); - sch_clipboard.push(c); - } - } - - // update diagram view - this.redraw(); - } - - Schematic.prototype.copy = function() { - // clear previous contents - sch_clipboard = []; - - // look for selected components, copy them to clipboard. - for (var i = this.components.length - 1; i >=0; --i) { - var c = this.components[i]; - if (c.selected) - sch_clipboard.push(c.clone(c.x,c.y)); - } - } - - Schematic.prototype.paste = function() { - // compute left,top of bounding box for origins of - // components in the clipboard - var left = undefined; - var top = undefined; - for (var i = sch_clipboard.length - 1; i >= 0; --i) { - var c = sch_clipboard[i]; - left = left ? Math.min(left,c.x) : c.x; - top = top ? Math.min(top,c.y) : c.y; - } - - this.message('cursor '+this.cursor_x+','+this.cursor_y); - - // clear current selections - this.unselect_all(-1); - this.redraw_background(); // so we see any components that got unselected - - // make clones of components on the clipboard, positioning - // them relative to the cursor - for (var i = sch_clipboard.length - 1; i >= 0; --i) { - var c = sch_clipboard[i]; - var new_c = c.clone(this.cursor_x + (c.x - left),this.cursor_y + (c.y - top)); - new_c.set_select(true); - new_c.add(this); - } - - // see what we've wrought - this.redraw(); - } - - /////////////////////////////////////////////////////////////////////////////// - // - // Netlist and Simulation interface - // - //////////////////////////////////////////////////////////////////////////////// - - // load diagram from JSON representation - Schematic.prototype.load_schematic = function(value,initial_value) { - // use default value if no schematic info in value - if (value == undefined || value.indexOf('[') == -1) - value = initial_value; - - if (value && value.indexOf('[') != -1) { - // convert string value into data structure - var json = JSON.parse(value); - - // top level is a list of components - for (var i = json.length - 1; i >= 0; --i) { - var c = json[i]; - if (c[0] == 'view') { - // special hack: view component lets us recreate view - this.origin_x = c[1]; - this.origin_y = c[2]; - this.scale = c[3]; - this.ac_npts = c[4]; - this.ac_fstart = c[5]; - this.ac_fstop = c[6]; - this.ac_source_name = c[7]; - this.tran_npts = c[8]; - this.tran_tstop = c[9]; - } else if (c[0] == 'w') { - // wire - this.add_wire(c[1][0],c[1][1],c[1][2],c[1][3]); - } else if (c[0] == 'dc') { - this.dc_results = c[1]; - } else if (c[0] == 'transient') { - this.transient_results = c[1]; - } else if (c[0] == 'ac') { - this.ac_results = c[1]; - } else { - // ordinary component - // c := [type, coords, properties, connections] - var type = c[0]; - var coords = c[1]; - var properties = c[2]; - - // make the part - var part = new parts_map[type][0](coords[0],coords[1],coords[2]); - - // give it its properties - for (var name in properties) - part.properties[name] = properties[name]; - - // add component to the diagram - part.add(this); - } - } - } - - // see what we've got! - this.redraw_background(); - } - - // label all the nodes in the circuit - Schematic.prototype.label_connection_points = function() { - // start by clearing all the connection point labels - for (var i = this.components.length - 1; i >=0; --i) - this.components[i].clear_labels(); - - // components are in charge of labeling their unlabeled connections. - // labels given to connection points will propagate to coincident connection - // points and across Wires. - - // let special components like GND label their connection(s) - for (var i = this.components.length - 1; i >=0; --i) - this.components[i].add_default_labels(); - - // now have components generate labels for unlabeled connections - this.next_label = 0; - for (var i = this.components.length - 1; i >=0; --i) - this.components[i].label_connections(); - } - - // generate a new label - Schematic.prototype.get_next_label = function() { - // generate next label in sequence - this.next_label += 1; - return this.next_label.toString(); - } - - // propagate label to coincident connection points - Schematic.prototype.propagate_label = function(label,location) { - var cplist = this.connection_points[location]; - for (var i = cplist.length - 1; i >= 0; --i) - cplist[i].propagate_label(label); - } - - // update the value field of our corresponding input field with JSON - // representation of schematic - Schematic.prototype.update_value = function() { - // label connection points - this.label_connection_points(); - - // build JSON data structure, convert to string value for - // input field - this.input.value = JSON.stringify(this.json_with_analyses()); - } - - // produce a JSON representation of the diagram - Schematic.prototype.json = function() { - var json = []; - - // output all the components/wires in the diagram - var n = this.components.length; - for (var i = 0; i < n; i++) - json.push(this.components[i].json(i)); - - // capture the current view parameters - json.push(['view',this.origin_x,this.origin_y,this.scale, - this.ac_npts,this.ac_fstart,this.ac_fstop,this.ac_source_name, - this.tran_npts,this.tran_tstop]); - - return json; - } - - // produce a JSON representation of the diagram - Schematic.prototype.json_with_analyses = function() { - var json = this.json(); - - if (this.dc_results != undefined) json.push(['dc',this.dc_results]); - if (this.ac_results != undefined) json.push(['ac',this.ac_results]); - if (this.transient_results != undefined) json.push(['transient',this.transient_results]); - - return json; - } - - /////////////////////////////////////////////////////////////////////////////// - // - // Simulation interface - // - //////////////////////////////////////////////////////////////////////////////// - - Schematic.prototype.extract_circuit = function() { - // give all the circuit nodes a name, extract netlist - this.label_connection_points(); - var netlist = this.json(); - - // since we've done the heavy lifting, update input field value - // so user can grab diagram if they want - this.input.value = JSON.stringify(netlist); - - // create a circuit from the netlist - var ckt = new cktsim.Circuit(); - if (ckt.load_netlist(netlist)) - return ckt; - else - return null; - } - - Schematic.prototype.dc_analysis = function() { - // remove any previous annotations - this.unselect_all(-1); - this.redraw_background(); - - var ckt = this.extract_circuit(); - if (ckt === null) return; - - // run the analysis - this.operating_point = ckt.dc(); - - // save a copy of the results for submission - this.dc_results = {}; - for (var i in this.operating_point) this.dc_results[i] = this.operating_point[i]; - - // display results on diagram - this.redraw(); - } - - // return a list of [color,node_label] for each probe in the diagram - Schematic.prototype.find_probes = function() { - var result = []; - for (var i = this.components.length - 1; i >= 0; --i) { - var c = this.components[i]; - if (c.type == 's') result.push(c.probe_info()); - } - return result; - } - - // use a dialog to get AC analysis parameters - Schematic.prototype.setup_ac_analysis = function() { - this.unselect_all(-1); - this.redraw_background(); - - var npts_lbl = 'Number of points/decade'; - var fstart_lbl = 'Starting frequency (Hz)'; - var fstop_lbl = 'Ending frequency (Hz)'; - var source_name_lbl = 'Name of V or I source for ac' - - if (this.find_probes().length == 0) { - alert("AC Analysis: there are no scope probes in the diagram!"); - return; - } - - var fields = new Array(); - fields[npts_lbl] = build_input('text',10,this.ac_npts); - fields[fstart_lbl] = build_input('text',10,this.ac_fstart); - fields[fstop_lbl] = build_input('text',10,this.ac_fstop); - fields[source_name_lbl] = build_input('text',10,this.ac_source_name); - - var content = build_table(fields); - content.fields = fields; - content.sch = this; - - this.dialog('AC Analysis',content,function(content) { - var sch = content.sch; - - // retrieve parameters, remember for next time - sch.ac_npts = content.fields[npts_lbl].value; - sch.ac_fstart = content.fields[fstart_lbl].value; - sch.ac_fstop = content.fields[fstop_lbl].value; - sch.ac_source_name = content.fields[source_name_lbl].value; - - sch.ac_analysis(cktsim.parse_number(sch.ac_npts), - cktsim.parse_number(sch.ac_fstart), - cktsim.parse_number(sch.ac_fstop), - sch.ac_source_name); - }); - } - - // perform ac analysis - Schematic.prototype.ac_analysis = function(npts,fstart,fstop,ac_source_name) { - // run the analysis - var ckt = this.extract_circuit(); - if (ckt === null) return; - var results = ckt.ac(npts,fstart,fstop,ac_source_name); - - if (typeof results == 'string') - this.message(results); - else { - if (this.submit_analyses != undefined) { - var submit = this.submit_analyses['ac']; - if (submit != undefined) { - // save a copy of the results for submission - sch.ac_results = {}; - var freqs = results['_frequencies_']; - - // save requested values for each requested node - for (var j = 0; j < submit.length; j++) { - var flist = submit[j]; // [node_name,f1,f2,...] - var node = flist[0]; - var values = results[node]; - var fvlist = []; - // for each requested freq, interpolate response value - for (var k = 1; k < flist.length; k++) { - var f = flist[k]; - var v = interpolate(f,freqs,values); - fvlist.push([f,v == undefined ? 'undefined' : v]); - } - // save results as list of [f,response] paris - this.ac_results[node] = fvlist; - } - } - } - - var x_values = results['_frequencies_']; - - // x axis will be a log scale - for (var i = x_values.length - 1; i >= 0; --i) - x_values[i] = Math.log(x_values[i])/Math.LN10; - - // set up plot values for each node with a probe - var y_values = []; // list of [color, result_array] - var probes = this.find_probes(); - - var probe_maxv = []; - var probe_color = []; - - // Check for probe with near zero transfer function and warn - for (var i = probes.length - 1; i >= 0; --i) { - probe_color[i] = probes[i][0]; - var label = probes[i][1]; - var v = results[label]; - probe_maxv[i] = array_max(v); // magnitudes always > 0 - } - var all_max = array_max(probe_maxv); - for (var i = probes.length - 1; i >= 0; --i) { - if ((probe_maxv[i] / all_max) < 1.0e-10) { - alert('Near zero ac response, remove ' + probe_color[i] + ' probe'); - return; - } - } - - for (var i = probes.length - 1; i >= 0; --i) { - var color = probes[i][0]; - var label = probes[i][1]; - var v = results[label]; - // convert values into dB relative to source amplitude - var v_max = 1; - for (var j = v.length - 1; j >= 0; --j) - // convert each value to dB relative to max - v[j] = 20.0 * Math.log(v[j]/v_max)/Math.LN10; - - y_values.push([color,v]); - } - - // graph the result and display in a window - var graph = this.graph(x_values,y_values,'log(Frequency)','dB'); - this.window('Results of AC Analysis',graph); - } - } - - Schematic.prototype.transient_analysis = function() { - this.unselect_all(-1); - this.redraw_background(); - - var npts_lbl = 'Minimum number of timepoints'; - var tstop_lbl = 'Stop Time (seconds)'; - - if (this.find_probes().length == 0) { - alert("Transient Analysis: there are no probes in the diagram!"); - return; - } - - var fields = new Array(); - fields[npts_lbl] = build_input('text',10,this.tran_npts); - fields[tstop_lbl] = build_input('text',10,this.tran_tstop); - - var content = build_table(fields); - content.fields = fields; - content.sch = this; - - this.dialog('Transient Analysis',content,function(content) { - var sch = content.sch; - var ckt = sch.extract_circuit(); - if (ckt === null) return; - - - // retrieve parameters, remember for next time - sch.tran_npts = content.fields[npts_lbl].value; - sch.tran_tstop = content.fields[tstop_lbl].value; - - // gather a list of nodes that are being probed. These - // will be added to the list of nodes checked during the - // LTE calculations in transient analysis - var probe_list = sch.find_probes(); - var probe_names = new Array(probe_list.length); - for (var i = probe_list.length - 1; i >= 0; --i) - probe_names[i] = probe_list[i][1]; - - // run the analysis - var results = ckt.tran(ckt.parse_number(sch.tran_npts), 0, - ckt.parse_number(sch.tran_tstop), probe_names, false); - - if (typeof results == 'string') - sch.message(results); - else { - if (sch.submit_analyses != undefined) { - var submit = sch.submit_analyses['tran']; - if (submit != undefined) { - // save a copy of the results for submission - sch.transient_results = {}; - var times = results['_time_']; - - // save requested values for each requested node - for (var j = 0; j < submit.length; j++) { - var tlist = submit[j]; // [node_name,t1,t2,...] - var node = tlist[0]; - var values = results[node]; - var tvlist = []; - // for each requested time, interpolate waveform value - for (var k = 1; k < tlist.length; k++) { - var t = tlist[k]; - var v = interpolate(t,times,values); - tvlist.push([t,v == undefined ? 'undefined' : v]); - } - // save results as list of [t,value] pairs - sch.transient_results[node] = tvlist; - } - } - } - - var x_values = results['_time_']; - - // set up plot values for each node with a probe - var y_values = []; // list of [color, result_array] - var probes = sch.find_probes(); - - for (var i = probes.length - 1; i >= 0; --i) { - var color = probes[i][0]; - var label = probes[i][1]; - var v = results[label]; - y_values.push([color,v]); - } - - // graph the result and display in a window - var graph = sch.graph(x_values,y_values,'Time','Voltage'); - sch.window('Results of Transient Analysis',graph); - } - }) - } - - // t is the time at which we want a value - // times is a list of timepoints from the simulation - function interpolate(t,times,values) { - if (values == undefined) return undefined; - - for (var i = 0; i < times.length; i++) - if (t < times[i]) { - // t falls between times[i-1] and times[i] - var t1 = (i == 0) ? times[0] : times[i-1]; - var t2 = times[i]; - - if (t2 == undefined) return undefined; - - var v1 = (i == 0) ? values[0] : values[i-1]; - var v2 = values[i]; - var v = v1; - if (t != t1) v += (t - t1)*(v2 - v1)/(t2 - t1); - return v; - } - } - - // external interface for setting the property value of a named component - Schematic.prototype.set_property = function(component_name,property,value) { - this.unselect_all(-1); - - for (var i = this.components.length - 1; i >= 0; --i) { - var component = this.components[i]; - if (component.properties['name'] == component_name) { - component.properties[property] = value.toString(); - break; - } - } - - // update diagram - this.redraw_background(); - } - - /////////////////////////////////////////////////////////////////////////////// - // - // Drawing support -- deals with scaling and scrolling of diagrama - // - //////////////////////////////////////////////////////////////////////////////// - - // here to redraw background image containing static portions of the schematic. - // Also redraws dynamic portion. - Schematic.prototype.redraw_background = function() { - var c = this.bg_image.getContext('2d'); - - c.lineCap = 'round'; - - // paint background color - c.fillStyle = element_style; - c.fillRect(0,0,this.width,this.height); - - if (!this.diagram_only) { - // grid - c.strokeStyle = grid_style; - var first_x = 0; - var last_x = this.width/this.scale; - var first_y = 0; - var last_y = this.height/this.scale; - for (var i = first_x; i < last_x; i += this.grid) - this.draw_line(c,i,first_y,i,last_y,0.1); - for (var i = first_y; i < last_y; i += this.grid) - this.draw_line(c,first_x,i,last_x,i,0.1); - } - - // unselected components - for (var i = this.components.length - 1; i >= 0; --i) { - var component = this.components[i]; - if (!component.selected) component.draw(c); - } - - this.redraw(); // background changed, redraw on screen - } - - // redraw what user sees = static image + dynamic parts - Schematic.prototype.redraw = function() { - var c = this.canvas.getContext('2d'); - - // put static image in the background - c.drawImage(this.bg_image, 0, 0); - - // selected components - var selections = false; - for (var i = this.components.length - 1; i >= 0; --i) { - var component = this.components[i]; - if (component.selected) { - component.draw(c); - selections = true; - } - } - this.enable_tool('cut',selections); - this.enable_tool('copy',selections); - this.enable_tool('paste',sch_clipboard.length > 0); - - // connection points: draw one at each location - for (var location in this.connection_points) { - var cplist = this.connection_points[location]; - cplist[0].draw(c,cplist.length); - } - - // draw new wire - if (this.wire) { - var r = this.wire; - c.strokeStyle = selected_style; - this.draw_line(c,r[0],r[1],r[2],r[3],1); - } - - // draw selection rectangle - if (this.select_rect) { - var r = this.select_rect; - c.lineWidth = 1; - c.strokeStyle = selected_style; - c.beginPath(); - c.moveTo(r[0],r[1]); - c.lineTo(r[0],r[3]); - c.lineTo(r[2],r[3]); - c.lineTo(r[2],r[1]); - c.lineTo(r[0],r[1]); - c.stroke(); - } - - // display operating point results - if (this.operating_point) { - if (typeof this.operating_point == 'string') - this.message(this.operating_point); - else { - // make a copy of the operating_point info so we can mess with it - var temp = new Array(); - for (var i in this.operating_point) temp[i] = this.operating_point[i]; - - // run through connection points displaying (once) the voltage - // for each electrical node - for (var location in this.connection_points) - (this.connection_points[location])[0].display_voltage(c,temp); - - // let components display branch current info if available - for (var i = this.components.length - 1; i >= 0; --i) - this.components[i].display_current(c,temp) - } - } - - // finally overlay cursor - if (this.drawCursor && this.draw_cursor) { - //var x = this.cursor_x; - //var y = this.cursor_y; - //this.draw_text(c,'('+x+','+y+')',x+this.grid,y-this.grid,10); - this.draw_cursor(c,this.cursor_x,this.cursor_y); - } - } - - // draws a cross cursor - Schematic.prototype.cross_cursor = function(c,x,y) { - this.draw_line(c,x-this.grid,y,x+this.grid,y,1); - this.draw_line(c,x,y-this.grid,x,y+this.grid,1); - } - - Schematic.prototype.moveTo = function(c,x,y) { - c.moveTo((x - this.origin_x) * this.scale,(y - this.origin_y) * this.scale); - } - - Schematic.prototype.lineTo = function(c,x,y) { - c.lineTo((x - this.origin_x) * this.scale,(y - this.origin_y) * this.scale); - } - - Schematic.prototype.draw_line = function(c,x1,y1,x2,y2,width) { - c.lineWidth = width*this.scale; - c.beginPath(); - c.moveTo((x1 - this.origin_x) * this.scale,(y1 - this.origin_y) * this.scale); - c.lineTo((x2 - this.origin_x) * this.scale,(y2 - this.origin_y) * this.scale); - c.stroke(); - } - - Schematic.prototype.draw_arc = function(c,x,y,radius,start_radians,end_radians,anticlockwise,width,filled) { - c.lineWidth = width*this.scale; - c.beginPath(); - c.arc((x - this.origin_x)*this.scale,(y - this.origin_y)*this.scale,radius*this.scale, - start_radians,end_radians,anticlockwise); - if (filled) c.fill(); - else c.stroke(); - } - - Schematic.prototype.draw_text = function(c,text,x,y,size) { - c.font = size*this.scale+'pt sans-serif' - c.fillText(text,(x - this.origin_x) * this.scale,(y - this.origin_y) * this.scale); - } - - // add method to canvas to compute relative coords for event - HTMLCanvasElement.prototype.relMouseCoords = function(event){ - // run up the DOM tree to figure out coords for top,left of canvas - var totalOffsetX = 0; - var totalOffsetY = 0; - var currentElement = this; - do { - totalOffsetX += currentElement.offsetLeft; - totalOffsetY += currentElement.offsetTop; - } - while (currentElement = currentElement.offsetParent); - - // now compute relative position of click within the canvas - this.mouse_x = event.pageX - totalOffsetX; - this.mouse_y = event.pageY - totalOffsetY; - - this.page_x = event.pageX; - this.page_y = event.pageY; - } - - /////////////////////////////////////////////////////////////////////////////// - // - // Event handling - // - //////////////////////////////////////////////////////////////////////////////// - - // process keystrokes, consuming those that are meaningful to us - function schematic_key_down(event) { - if (!event) event = window.event; - var sch = (window.event) ? event.srcElement.schematic : event.target.schematic; - var code = event.keyCode; - - // keep track of modifier key state - if (code == 16) sch.shiftKey = true; - else if (code == 17) sch.ctrlKey = true; - else if (code == 18) sch.altKey = true; - else if (code == 91) sch.cmdKey = true; - - // backspace or delete: delete selected components - else if (code == 8 || code == 46) { - // delete selected components - for (var i = sch.components.length - 1; i >= 0; --i) { - var component = sch.components[i]; - if (component.selected) component.delete(1); - } - } - - // cmd/ctrl x: cut - else if ((sch.ctrlKey || sch.cmdKey) && code == 88) { - sch.cut(); - event.preventDefault(); - return false; - } - - // cmd/ctrl c: copy - else if ((sch.ctrlKey || sch.cmdKey) && code == 67) { - sch.copy(); - event.preventDefault(); - return false; - } - - // cmd/ctrl v: paste - else if ((sch.ctrlKey || sch.cmdKey) && code == 86) { - sch.paste(); - event.preventDefault(); - return false; - } - - // 'r': rotate component - else if (!sch.ctrlKey && !sch.altKey && !sch.cmdKey && code == 82) { - // rotate - for (var i = sch.components.length - 1; i >= 0; --i) { - var component = sch.components[i]; - if (component.selected) component.rotate(1); - } - sch.redraw(); - event.preventDefault(); - return false; - } - - else return true; - - // consume keystroke - sch.redraw(); - event.preventDefault(); - return false; - } - - function schematic_key_up(event) { - if (!event) event = window.event; - var sch = (window.event) ? event.srcElement.schematic : event.target.schematic; - var code = event.keyCode; - - if (code == 16) sch.shiftKey = false; - else if (code == 17) sch.ctrlKey = false; - else if (code == 18) sch.altKey = false; - else if (code == 91) sch.cmdKey = false; - } - - function schematic_mouse_enter(event) { - if (!event) event = window.event; - var sch = (window.event) ? event.srcElement.schematic : event.target.schematic; - - // see if user has selected a new part - if (sch.new_part) { - // revert handler - document.onselectstart = sch.saved_onselectstart; - - // grab incoming part, turn off selection of parts bin - var part = sch.new_part; - sch.new_part = undefined; - part.select(false); - - // unselect everything else in the schematic, add part and select it - sch.unselect_all(-1); - sch.redraw_background(); // so we see any components that got unselected - - // make a clone of the component in the parts bin - part = part.component.clone(sch.cursor_x,sch.cursor_y); - part.add(sch); // add it to schematic - part.set_select(true); - - // and start dragging it - sch.drag_begin(); - } - - sch.drawCursor = true; - sch.redraw(); - sch.canvas.focus(); // capture key strokes - return false; - } - - function schematic_mouse_leave(event) { - if (!event) event = window.event; - var sch = (window.event) ? event.srcElement.schematic : event.target.schematic; - sch.drawCursor = false; - sch.redraw(); - return false; - } - - function schematic_mouse_down(event) { - if (!event) event = window.event; - else event.preventDefault(); - var sch = (window.event) ? event.srcElement.schematic : event.target.schematic; - - // determine where event happened in schematic coordinates - sch.canvas.relMouseCoords(event); - var x = sch.canvas.mouse_x/sch.scale + sch.origin_x; - var y = sch.canvas.mouse_y/sch.scale + sch.origin_y; - sch.cursor_x = Math.round(x/sch.grid) * sch.grid; - sch.cursor_y = Math.round(y/sch.grid) * sch.grid; - - // is mouse over a connection point? If so, start dragging a wire - var cplist = sch.connection_points[sch.cursor_x + ',' + sch.cursor_y]; - if (cplist && !event.shiftKey) { - sch.unselect_all(-1); - sch.wire = [sch.cursor_x,sch.cursor_y,sch.cursor_x,sch.cursor_y]; - } else { - // give all components a shot at processing the selection event - var which = -1; - for (var i = sch.components.length - 1; i >= 0; --i) - if (sch.components[i].select(x,y,event.shiftKey)) { - if (sch.components[i].selected) { - sch.drag_begin(); - which = i; // keep track of component we found - } - break; - } - // did we just click on a previously selected component? - var reselect = which!=-1 && sch.components[which].was_previously_selected; - - if (!event.shiftKey) { - // if shift key isn't pressed and we didn't click on component - // that was already selected, unselect everyone except component - // we just clicked on - if (!reselect) sch.unselect_all(which); - - // if there's nothing to drag, set up a selection rectangle - if (!sch.dragging) sch.select_rect = [sch.canvas.mouse_x,sch.canvas.mouse_y, - sch.canvas.mouse_x,sch.canvas.mouse_y]; - } - } - - sch.redraw_background(); - return false; - } - - function schematic_mouse_move(event) { - if (!event) event = window.event; - var sch = (window.event) ? event.srcElement.schematic : event.target.schematic; - - sch.canvas.relMouseCoords(event); - var x = sch.canvas.mouse_x/sch.scale + sch.origin_x; - var y = sch.canvas.mouse_y/sch.scale + sch.origin_y; - sch.cursor_x = Math.round(x/sch.grid) * sch.grid; - sch.cursor_y = Math.round(y/sch.grid) * sch.grid; - - if (sch.wire) { - // update new wire end point - sch.wire[2] = sch.cursor_x; - sch.wire[3] = sch.cursor_y; - } else if (sch.dragging) { - // see how far we moved - var dx = sch.cursor_x - sch.drag_x; - var dy = sch.cursor_y - sch.drag_y; - if (dx != 0 || dy != 0) { - // update position for next time - sch.drag_x = sch.cursor_x; - sch.drag_y = sch.cursor_y; - - // give all components a shot at processing the event - for (var i = sch.components.length - 1; i >= 0; --i) { - var component = sch.components[i]; - if (component.selected) component.move(dx,dy); - } - } - } else if (sch.select_rect) { - // update moving corner of selection rectangle - sch.select_rect[2] = sch.canvas.mouse_x; - sch.select_rect[3] = sch.canvas.mouse_y; - //sch.message(sch.select_rect.toString()); - } - - // just redraw dynamic components - sch.redraw(); - //sch.message(sch.canvas.page_x + ',' + sch.canvas.page_y + ';' + sch.canvas.mouse_x + ',' + sch.canvas.mouse_y + ';' + sch.cursor_x + ',' + sch.cursor_y); - - return false; - } - - function schematic_mouse_up(event) { - if (!event) event = window.event; - else event.preventDefault(); - var sch = (window.event) ? event.srcElement.schematic : event.target.schematic; - - // drawing a new wire - if (sch.wire) { - var r = sch.wire; - sch.wire = undefined; - - if (r[0]!=r[2] || r[1]!=r[3]) { - // insert wire component - sch.add_wire(r[0],r[1],r[2],r[3]); - sch.redraw_background(); - } else sch.redraw(); - } - - // dragging - if (sch.dragging) sch.drag_end(); - - // selection rectangle - if (sch.select_rect) { - var r = sch.select_rect; - - // if select_rect is a point, we've already dealt with selection - // in mouse_down handler - if (r[0]!=r[2] || r[1]!=r[3]) { - // convert to schematic coordinates - var s = [r[0]/sch.scale + sch.origin_x, r[1]/sch.scale + sch.origin_y, - r[2]/sch.scale + sch.origin_x, r[3]/sch.scale + sch.origin_y]; - canonicalize(s); - - if (!event.shiftKey) sch.unselect_all(); - - // select components that intersect selection rectangle - for (var i = sch.components.length - 1; i >= 0; --i) - sch.components[i].select_rect(s,event.shiftKey); - } - - sch.select_rect = undefined; - sch.redraw_background(); - } - return false; - } - - function schematic_double_click(event) { - if (!event) event = window.event; - else event.preventDefault(); - var sch = (window.event) ? event.srcElement.schematic : event.target.schematic; - - // determine where event happened in schematic coordinates - sch.canvas.relMouseCoords(event); - var x = sch.canvas.mouse_x/sch.scale + sch.origin_x; - var y = sch.canvas.mouse_y/sch.scale + sch.origin_y; - sch.cursor_x = Math.round(x/sch.grid) * sch.grid; - sch.cursor_y = Math.round(y/sch.grid) * sch.grid; - - // see if we double-clicked a component. If so, edit it's properties - for (var i = sch.components.length - 1; i >= 0; --i) - if (sch.components[i].edit_properties(x,y)) - break; - - return false; - } - - /////////////////////////////////////////////////////////////////////////////// - // - // Status message and dialogs - // - //////////////////////////////////////////////////////////////////////////////// - - Schematic.prototype.message = function(message) { - this.status.nodeValue = message; - } - - Schematic.prototype.append_message = function(message) { - this.status.nodeValue += ' / '+message; - } - - // set up a dialog with specified title, content and two buttons at - // the bottom: OK and Cancel. If Cancel is clicked, dialog goes away - // and we're done. If OK is clicked, dialog goes away and the - // callback function is called with the content as an argument (so - // that the values of any fields can be captured). - Schematic.prototype.dialog = function(title,content,callback) { - // create the div for the top level of the dialog, add to DOM - var dialog = document.createElement('div'); - dialog.sch = this; - dialog.content = content; - dialog.callback = callback; - - // div to hold the content - var body = document.createElement('div'); - content.style.marginBotton = '5px'; - body.appendChild(content); - body.style.padding = '5px'; - dialog.appendChild(body); - - // OK button - var ok_button = document.createElement('span'); - ok_button.appendChild(document.createTextNode('OK')); - ok_button.dialog = dialog; // for the handler to use - ok_button.addEventListener('click',dialog_okay,false); - ok_button.style.display = 'inline'; - ok_button.style.border = '1px solid'; - ok_button.style.padding = '5px'; - ok_button.style.margin = '10px'; - - // cancel button - var cancel_button = document.createElement('span'); - cancel_button.appendChild(document.createTextNode('Cancel')); - cancel_button.dialog = dialog; // for the handler to use - cancel_button.addEventListener('click',dialog_cancel,false); - cancel_button.style.display = 'inline'; - cancel_button.style.border = '1px solid'; - cancel_button.style.padding = '5px'; - cancel_button.style.margin = '10px'; - - // div to hold the two buttons - var buttons = document.createElement('div'); - buttons.style.textAlign = 'center'; - buttons.appendChild(ok_button); - buttons.appendChild(cancel_button); - buttons.style.padding = '5px'; - buttons.style.margin = '10px'; - dialog.appendChild(buttons); - - // put into an overlay window - this.window(title,dialog); - } - - // callback when user click "Cancel" in a dialog - function dialog_cancel(event) { - if (!event) event = window.event; - var dialog = (window.event) ? event.srcElement.dialog : event.target.dialog; - - window_close(dialog.win); - } - - // callback when user click "OK" in a dialog - function dialog_okay(event) { - if (!event) event = window.event; - var dialog = (window.event) ? event.srcElement.dialog : event.target.dialog; - - window_close(dialog.win); - - // invoke the callback with the dialog contents as the argument - if (dialog.callback) dialog.callback(dialog.content); - } - - /////////////////////////////////////////////////////////////////////////////// - // - // Draggable, resizeable, closeable window - // - //////////////////////////////////////////////////////////////////////////////// - - // build a 2-column HTML table from an associative array (keys as text in - // column 1, values in column 2). - function build_table(a) { - var tbl = document.createElement('table'); - - // build a row for each element in associative array - for (var i in a) { - var label = document.createTextNode(i + ': '); - var col1 = document.createElement('td'); - col1.appendChild(label); - var col2 = document.createElement('td'); - col2.appendChild(a[i]); - var row = document.createElement('tr'); - row.appendChild(col1); - row.appendChild(col2); - row.style.verticalAlign = 'center'; - tbl.appendChild(row); - } - - return tbl; - } - - // build an input field - function build_input(type,size,value) { - var input = document.createElement('input'); - input.type = type; - input.size = size; - if (value == undefined) input.value = ''; - else input.value = value.toString(); - return input; - } - - // build a select widget using the strings found in the options array - function build_select(options,selected) { - var select = document.createElement('select'); - for (var i = 0; i < options.length; i++) { - var option = document.createElement('option'); - option.text = options[i]; - select.add(option); - if (options[i] == selected) select.selectedIndex = i; - } - return select; - } - - Schematic.prototype.window = function(title,content) { - // create the div for the top level of the window - var win = document.createElement('div'); - win.sch = this; - win.content = content; - win.drag_x = undefined; - win.draw_y = undefined; - - // div to hold the title - var head = document.createElement('div'); - head.style.backgroundColor = 'black'; - head.style.color = 'white'; - head.style.textAlign = 'center'; - head.style.padding = '5px'; - head.appendChild(document.createTextNode(title)); - - var close_button = new Image(); - close_button.src = close_icon; - close_button.style.cssFloat = 'right'; - close_button.addEventListener('click',window_close_button,false); - close_button.win = win; - head.appendChild(close_button); - - win.appendChild(head); - - // capture mouse events in title bar - head.addEventListener('mousedown',window_mouse_down,false); - head.addEventListener('mouseup',window_mouse_up,false); - head.addEventListener('mouseout',window_mouse_up,false); - head.addEventListener('mousemove',window_mouse_move,false); - - // div to hold the content - //var body = document.createElement('div'); - //body.appendChild(content); - win.appendChild(content); - content.win = win; // so content can contact us - - // compute location relative to canvas - win.left = this.canvas.mouse_x; - win.top = this.canvas.mouse_y; - - // add to DOM - win.style.background = 'white'; - win.style.zindex = '1000'; - win.style.position = 'absolute'; - win.style.left = win.left + 'px'; - win.style.top = win.top + 'px'; - win.style.border = '2px solid'; - - this.canvas.parentNode.insertBefore(win,this.canvas); - //this.input.parentNode.insertBefore(win,this.input.nextSibling); - } - - // close the window - function window_close(win) { - // remove the windw from the top-level div of the schematic - win.parentNode.removeChild(win); - } - - function window_close_button(event) { - if (!event) event = window.event; - var src = (window.event) ? event.srcElement : event.target; - window_close(src.win); - } - - // capture mouse events in title bar of window - function window_mouse_down(event) { - if (!event) event = window.event; - var src = (window.event) ? event.srcElement : event.target; - var win = src.parentNode; - - // remember where mouse is so we can compute dx,dy during drag - win.drag_x = event.pageX; - win.drag_y = event.pageY; - - return false; - } - - function window_mouse_up(event) { - if (!event) event = window.event; - var src = (window.event) ? event.srcElement : event.target; - var win = src.parentNode; - - // show's over folks... - win.drag_x = undefined; - win.drag_y = undefined; - return false; - } - - function window_mouse_move(event) { - if (!event) event = window.event; - var win = (window.event) ? event.srcElement.parentNode : event.target.parentNode; - - if (win.drag_x) { - var dx = event.pageX - win.drag_x; - var dy = event.pageY - win.drag_y; - - // move the window - win.left += dx; - win.top += dy; - win.style.left = win.left + 'px'; - win.style.top = win.top + 'px'; - - // update reference point - win.drag_x += dx; - win.drag_y += dy; - - return false; - } - } - - /////////////////////////////////////////////////////////////////////////////// - // - // Toolbar - // - //////////////////////////////////////////////////////////////////////////////// - - Schematic.prototype.add_tool = function(icon,tip,callback) { - var tool; - if (icon.search('data:image') != -1) { - tool = document.createElement('img'); - tool.src = icon; - } else { - tool = document.createElement('span'); - tool.style.font = 'small-caps small sans-serif'; - var label = document.createTextNode(icon); - tool.appendChild(label); - } - - // decorate tool - tool.style.borderWidth = '1px'; - tool.style.borderStyle = 'solid'; - tool.style.borderColor = background_style; - tool.style.padding = '2px'; - - // set up event processing - tool.addEventListener('mouseover',tool_enter,false); - tool.addEventListener('mouseout',tool_leave,false); - tool.addEventListener('click',tool_click,false); - - // add to toolbar - tool.sch = this; - tool.tip = tip; - tool.callback = callback; - this.toolbar.push(tool); - - tool.enabled = false; - tool.style.opacity = 0.2; - - return tool; - } - - Schematic.prototype.enable_tool = function(tname,which) { - var tool = this.tools[tname]; - - if (tool != undefined) { - tool.style.opacity = which ? 1.0 : 0.2; - tool.enabled = which; - - // if disabling tool, remove border and tip - if (!which) { - tool.style.borderColor = background_style; - tool.sch.message(''); - } - } - } - - // highlight tool button by turning on border, changing background - function tool_enter(event) { - if (!event) event = window.event; - var tool = (window.event) ? event.srcElement : event.target; - - if (tool.enabled) { - tool.style.borderColor = normal_style; - tool.sch.message(tool.tip); - tool.opacity = 1.0; - } - } - - // unhighlight tool button by turning off border, reverting to normal background - function tool_leave(event) { - if (!event) event = window.event; - var tool = (window.event) ? event.srcElement : event.target; - - if (tool.enabled) { - tool.style.borderColor = background_style; - tool.sch.message(''); - } - } - - // handle click on a tool - function tool_click(event) { - if (!event) event = window.event; - var tool = (window.event) ? event.srcElement : event.target; - - if (tool.enabled) { - tool.sch.canvas.relMouseCoords(event); // so we can position pop-up window correctly - tool.callback.call(tool.sch); - } - } - - cut_icon = 'data:image/gif;base64,R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgMDAwICAgP8AAAD/AP//AAAA//8A/wD//////yH5BAEAAAcALAAAAAAQABAAAAQu8MhJqz1g5qs7lxv2gRkQfuWomarXEgDRHjJhf3YtyRav0xcfcFgR0nhB5OwTAQA7'; - - copy_icon = 'data:image/gif;base64,R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgMDAwICAgP8AAAD/AP//AAAA//8A/wD//////yH5BAEAAAcALAAAAAAQABAAAAQ+8MhJ6wE4Wwqef9gmdV8HiKZJrCz3ecS7TikWfzExvk+M9a0a4MbTkXCgTMeoHPJgG5+yF31SLazsTMTtViIAOw=='; - - paste_icon = 'data:image/gif;base64,R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgMDAwICAgP8AAAD/AP//AAAA//8A/wD//////yH5BAEAAAcALAAAAAAQABAAAARL8MhJqwUYWJnxWp3GDcgAgCdQIqLKXmVLhhnyHiqpr7rME8AgocVDEB5IJHD0SyofBFzxGIQGAbvB0ZkcTq1CKK6z5YorwnR0w44AADs='; - - close_icon = 'data:image/gif;base64,R0lGODlhEAAQAMQAAGtra/f3/62tre/v9+bm787O1pycnHNzc6WlpcXFxd7e3tbW1nt7e7W1te/v74SEhMXFzmNjY+bm5v///87OzgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAAAAAAALAAAAAAQABAAAAVt4DRMZGmSwRQQBUS9MAwRIyQ5Uq7neEFSDtxOF4T8cobIQaE4RAQ5yjHHiCCSD510QtFGvoCFdppDfBu7bYzy+D7WP5ggAgA8Y3FKwi5IAhIweW1vbBGEWy5rilsFi2tGAwSJixAFBCkpJ5ojIQA7'; - - - /////////////////////////////////////////////////////////////////////////////// - // - // Graphing - // - /////////////////////////////////////////////////////////////////////////////// - - // add dashed lines! - // from http://davidowens.wordpress.com/2010/09/07/html-5-canvas-and-dashed-lines/ - CanvasRenderingContext2D.prototype.dashedLineTo = function(fromX, fromY, toX, toY, pattern) { - // Our growth rate for our line can be one of the following: - // (+,+), (+,-), (-,+), (-,-) - // Because of this, our algorithm needs to understand if the x-coord and - // y-coord should be getting smaller or larger and properly cap the values - // based on (x,y). - var lt = function (a, b) { return a <= b; }; - var gt = function (a, b) { return a >= b; }; - var capmin = function (a, b) { return Math.min(a, b); }; - var capmax = function (a, b) { return Math.max(a, b); }; - - var checkX = { thereYet: gt, cap: capmin }; - var checkY = { thereYet: gt, cap: capmin }; - - if (fromY - toY > 0) { - checkY.thereYet = lt; - checkY.cap = capmax; - } - if (fromX - toX > 0) { - checkX.thereYet = lt; - checkX.cap = capmax; - } - - this.moveTo(fromX, fromY); - var offsetX = fromX; - var offsetY = fromY; - var idx = 0, dash = true; - while (!(checkX.thereYet(offsetX, toX) && checkY.thereYet(offsetY, toY))) { - var ang = Math.atan2(toY - fromY, toX - fromX); - var len = pattern[idx]; - - offsetX = checkX.cap(toX, offsetX + (Math.cos(ang) * len)); - offsetY = checkY.cap(toY, offsetY + (Math.sin(ang) * len)); - - if (dash) this.lineTo(offsetX, offsetY); - else this.moveTo(offsetX, offsetY); - - idx = (idx + 1) % pattern.length; - dash = !dash; - } - }; - - // given a range of values, return a new range [vmin',vmax'] where the limits - // have been chosen "nicely". Taken from matplotlib.ticker.LinearLocator - function view_limits(vmin,vmax) { - // deal with degenerate case... - if (vmin == vmax) { - if (vmin == 0) { vmin = -0.5; vmax = 0.5; } - else { - vmin = vmin > 0 ? 0.9*vmin : 1.1*vmin; - vmax = vmax > 0 ? 1.1*vmax : 0.9*vmax; - } - } - - var log_range = Math.log(vmax - vmin)/Math.LN10; - var exponent = Math.floor(log_range); - //if (log_range - exponent < 0.5) exponent -= 1; - var scale = Math.pow(10,-exponent); - vmin = Math.floor(scale*vmin)/scale; - vmax = Math.ceil(scale*vmax)/scale; - - return [vmin,vmax,1.0/scale]; - } - - function engineering_notation(n,nplaces,trim) { - if (n == 0) return("0"); - if (trim == undefined) trim = true; - - var sign = n < 0 ? -1 : 1; - var log10 = Math.log(sign*n)/Math.LN10; - var exp = Math.floor(log10/3); // powers of 1000 - var mantissa = sign*Math.pow(10,log10 - 3*exp); - - // keep specified number of places following decimal point - var mstring = (mantissa + sign*0.5*Math.pow(10,-nplaces)).toString(); - var mlen = mstring.length; - var endindex = mstring.indexOf('.'); - if (endindex != -1) { - if (nplaces > 0) { - endindex += nplaces + 1; - if (endindex > mlen) endindex = mlen; - if (trim) { - while (mstring.charAt(endindex-1) == '0') endindex -= 1; - if (mstring.charAt(endindex-1) == '.') endindex -= 1; - } - } - if (endindex < mlen) - mstring = mstring.substring(0,endindex); - } - - switch(exp) { - case -5: return mstring+"f"; - case -4: return mstring+"p"; - case -3: return mstring+"n"; - case -2: return mstring+"u"; - case -1: return mstring+"m"; - case 0: return mstring; - case 1: return mstring+"K"; - case 2: return mstring+"M"; - case 3: return mstring+"G"; - } - - // don't have a good suffix, so just print the number - return n.toString(); - } - - var grid_pattern = [1,2]; - var cursor_pattern = [5,5]; - - // x_values is an array of x coordinates for each of the plots - // y_values is an array of [color, value_array], one entry for each plot - Schematic.prototype.graph = function(x_values,y_values,x_legend,y_legend) { - var pwidth = 400; // dimensions of actual plot - var pheight = 300; // dimensions of actual plot - var left_margin = 55; - var top_margin = 25; - var right_margin = 25; - var bottom_margin = 45; - var tick_length = 5; - - var w = pwidth + left_margin + right_margin; - var h = pheight + top_margin + bottom_margin; - - var canvas = document.createElement('canvas'); - canvas.width = w; - canvas.height = h; - - // the graph itself will be drawn here and this image will be copied - // onto canvas, where it can be overlayed with mouse cursors, etc. - var bg_image = document.createElement('canvas'); - bg_image.width = w; - bg_image.height = h; - canvas.bg_image = bg_image; // so we can find it during event handling - - // start by painting an opaque background - var c = bg_image.getContext('2d'); - c.fillStyle = background_style; - c.fillRect(0,0,w,h); - c.fillStyle = element_style; - c.fillRect(left_margin,top_margin,pwidth,pheight); - - // figure out scaling for plots - var x_min = array_min(x_values); - var x_max = array_max(x_values); - var x_limits = view_limits(x_min,x_max); - x_min = x_limits[0]; - x_max = x_limits[1]; - var x_scale = pwidth/(x_max - x_min); - - function plot_x(x) { - return (x - x_min)*x_scale + left_margin; - } - - // draw x grid - c.strokeStyle = grid_style; - c.lineWidth = 1; - c.fillStyle = normal_style; - c.font = '10pt sans-serif'; - c.textAlign = 'center'; - c.textBaseline = 'top'; - var end = top_margin + pheight; - for (var x = x_min; x <= x_max; x += x_limits[2]) { - var temp = plot_x(x) + 0.5; // keep lines crisp! - - // grid line - c.beginPath(); - if (x == x_min) { - c.moveTo(temp,top_margin); - c.lineTo(temp,end); - } else - c.dashedLineTo(temp,top_margin,temp,end,grid_pattern); - c.stroke(); - - // tick mark - c.beginPath(); - c.moveTo(temp,end); - c.lineTo(temp,end + tick_length); - c.stroke(); - c.fillText(engineering_notation(x,2),temp,end + tick_length); - } - - var y_min = Infinity; - var y_max = -Infinity; - var plot; - for (plot = y_values.length - 1; plot >= 0; --plot) { - var values = y_values[plot][1]; - var temp = array_min(values); - if (temp < y_min) y_min = temp; - temp = array_max(values); - if (temp > y_max) y_max = temp; - } - var y_limits = view_limits(y_min,y_max); - y_min = y_limits[0]; - y_max = y_limits[1]; - var y_scale = pheight/(y_max - y_min); - - function plot_y(y) { - return (y_max - y)*y_scale + top_margin; - } - - // draw y grid - c.textAlign = 'right'; - c.textBaseline = 'middle'; - for (var y = y_min; y <= y_max; y += y_limits[2]) { - var temp = plot_y(y) + 0.5; // keep lines crisp! - - // grid line - c.beginPath(); - if (y == y_min) { - c.moveTo(left_margin,temp); - c.lineTo(left_margin + pwidth,temp); - } else - c.dashedLineTo(left_margin,temp,left_margin + pwidth,temp,grid_pattern); - c.stroke(); - - // tick mark - c.beginPath(); - c.moveTo(left_margin - tick_length,temp); - c.lineTo(left_margin,temp); - c.stroke(); - c.fillText(engineering_notation(y,2),left_margin - tick_length -2,temp); - } - - // now draw each plot - var x,y; - c.lineWidth = 3; - for (plot = y_values.length - 1; plot >= 0; --plot) { - c.strokeStyle = probe_colors_rgb[y_values[plot][0]]; - var values = y_values[plot][1]; - - c.beginPath(); - x = plot_x(x_values[0]); - y = plot_y(values[0]); - c.moveTo(x,y); - for (var i = 1; i < x_values.length; i++) { - x = plot_x(x_values[i]); - y = plot_y(values[i]); - c.lineTo(x,y); - } - c.stroke(); - } - - // draw legends - c.font = '12pt sans-serif'; - c.textAlign = 'center'; - c.textBaseline = 'bottom'; - c.fillText(x_legend,left_margin + pwidth/2,h - 5); - - c.textBaseline = 'top'; - c.save(); - c.translate(5 ,top_margin + pheight/2); - c.rotate(-Math.PI/2); - c.fillText(y_legend,0,0); - c.restore(); - - // save info need for interactions with the graph - canvas.x_values = x_values; - canvas.y_values = y_values; - canvas.x_legend = x_legend; - canvas.y_legend = y_legend; - canvas.x_min = x_min; - canvas.x_scale = x_scale; - canvas.y_min = y_min; - canvas.y_scale = y_scale; - canvas.left_margin = left_margin; - canvas.top_margin = top_margin; - canvas.pwidth = pwidth; - canvas.pheight = pheight; - canvas.tick_length = tick_length; - - canvas.cursor_x = undefined; - canvas.sch = this; - - // do something useful when user mouses over graph - canvas.addEventListener('mousemove',graph_mouse_move,false); - - // return our masterpiece - redraw_plot(canvas); - return canvas; - } - - function array_max(a) { - max = -Infinity; - for (var i = a.length - 1; i >= 0; --i) - if (a[i] > max) max = a[i]; - return max; - } - - function array_min(a) { - min = Infinity; - for (var i = a.length - 1; i >= 0; --i) - if (a[i] < min) min = a[i]; - return min; - } - - function redraw_plot(graph) { - var c = graph.getContext('2d'); - c.drawImage(graph.bg_image,0,0); - - if (graph.cursor_x != undefined) { - // draw dashed vertical marker that follows mouse - var x = graph.left_margin + graph.cursor_x; - var end_y = graph.top_margin + graph.pheight + graph.tick_length; - c.strokeStyle = grid_style; - c.lineWidth = 1; - c.beginPath(); - c.dashedLineTo(x,graph.top_margin,x,end_y,cursor_pattern); - c.stroke(); - - // add x label at bottom of marker - var graph_x = graph.cursor_x/graph.x_scale + graph.x_min; - c.font = '10pt sans-serif'; - c.textAlign = 'center'; - c.textBaseline = 'top'; - c.fillStyle = background_style; - c.fillText('\u2588\u2588\u2588\u2588\u2588',x,end_y); - c.fillStyle = normal_style; - c.fillText(engineering_notation(graph_x,3,false),x,end_y); - - // compute which points marker is between - var x_values = graph.x_values; - var len = x_values.length; - var index = 0; - while (index < len && graph_x >= x_values[index]) index += 1; - var x1 = (index == 0) ? x_values[0] : x_values[index-1]; - var x2 = x_values[index]; - - if (x2 != undefined) { - // for each plot, interpolate and output value at intersection with marker - c.textAlign = 'left'; - var tx = graph.left_margin + 4; - var ty = graph.top_margin; - for (var plot = 0; plot < graph.y_values.length; plot++) { - var values = graph.y_values[plot][1]; - - // interpolate signal value at graph_x using values[index-1] and values[index] - var y1 = (index == 0) ? values[0] : values[index-1]; - var y2 = values[index]; - var y = y1; - if (graph_x != x1) y += (graph_x - x1)*(y2 - y1)/(x2 - x1); - - // annotate plot with value of signal at marker - c.fillStyle = element_style; - c.fillText('\u2588\u2588\u2588\u2588\u2588',tx-3,ty); - c.fillStyle = probe_colors_rgb[graph.y_values[plot][0]]; - c.fillText(engineering_notation(y,3,false),tx,ty); - ty += 14; - } - } - } - } - - function graph_mouse_move(event) { - if (!event) event = window.event; - var g = (window.event) ? event.srcElement : event.target; - - g.relMouseCoords(event); - // not sure yet where the 3,-3 offset correction comes from (borders? padding?) - var gx = g.mouse_x - g.left_margin - 3; - var gy = g.pheight - (g.mouse_y - g.top_margin) + 3; - if (gx >= 0 && gx <= g.pwidth && gy >=0 && gy <= g.pheight) g.cursor_x = gx; - else g.cursor_x = undefined; - - redraw_plot(g); - } - - /////////////////////////////////////////////////////////////////////////////// - // - // Parts bin - // - //////////////////////////////////////////////////////////////////////////////// - - // one instance will be created for each part in the parts bin - function Part(sch) { - this.sch = sch; - this.component = undefined; - this.selected = false; - - // set up canvas - this.canvas = document.createElement('canvas'); - this.canvas.style.borderStyle = 'solid'; - this.canvas.style.borderWidth = '1px'; - this.canvas.style.borderColor = background_style; - //this.canvas.style.position = 'absolute'; - this.canvas.style.cursor = 'default'; - this.canvas.height = part_w; - this.canvas.width = part_h; - this.canvas.part = this; - - this.canvas.addEventListener('mouseover',part_enter,false); - this.canvas.addEventListener('mouseout',part_leave,false); - this.canvas.addEventListener('mousedown',part_mouse_down,false); - this.canvas.addEventListener('mouseup',part_mouse_up,false); - - // make the part "clickable" by registering a dummy click handler - // this should make things work on the iPad - this.canvas.addEventListener('click',function(){},false); - } - - Part.prototype.set_location = function(left,top) { - this.canvas.style.left = left + 'px'; - this.canvas.style.top = top + 'px'; - } - - Part.prototype.right = function() { - return this.canvas.offsetLeft + this.canvas.offsetWidth; - } - - Part.prototype.bottom = function() { - return this.canvas.offsetTop + this.canvas.offsetHeight; - } - - Part.prototype.set_component = function(component,tip) { - component.sch = this; - this.component = component; - this.tip = tip; - - // figure out scaling and centering of parts icon - var b = component.bounding_box; - var dx = b[2] - b[0]; - var dy = b[3] - b[1]; - this.scale = 0.8; //Math.min(part_w/(1.2*dx),part_h/(1.2*dy)); - this.origin_x = b[0] + dx/2.0 - part_w/(2.0*this.scale); - this.origin_y = b[1] + dy/2.0 - part_h/(2.0*this.scale); - - this.redraw(); - } - - Part.prototype.redraw = function(part) { - var c = this.canvas.getContext('2d'); - - // paint background color - c.fillStyle = this.selected ? selected_style : background_style; - c.fillRect(0,0,part_w,part_h); - - if (this.component) this.component.draw(c); - } - - Part.prototype.select = function(which) { - this.selected = which; - this.redraw(); - } - - Part.prototype.update_connection_point = function(cp,old_location) { - // no connection points in the parts bin - } - - Part.prototype.moveTo = function(c,x,y) { - c.moveTo((x - this.origin_x) * this.scale,(y - this.origin_y) * this.scale); - } - - Part.prototype.lineTo = function(c,x,y) { - c.lineTo((x - this.origin_x) * this.scale,(y - this.origin_y) * this.scale); - } - - Part.prototype.draw_line = function(c,x1,y1,x2,y2,width) { - c.lineWidth = width*this.scale; - c.beginPath(); - c.moveTo((x1 - this.origin_x) * this.scale,(y1 - this.origin_y) * this.scale); - c.lineTo((x2 - this.origin_x) * this.scale,(y2 - this.origin_y) * this.scale); - c.stroke(); - } - - Part.prototype.draw_arc = function(c,x,y,radius,start_radians,end_radians,anticlockwise,width,filled) { - c.lineWidth = width*this.scale; - c.beginPath(); - c.arc((x - this.origin_x)*this.scale,(y - this.origin_y)*this.scale,radius*this.scale, - start_radians,end_radians,anticlockwise); - if (filled) c.fill(); - else c.stroke(); - } - - Part.prototype.draw_text = function(c,text,x,y,size) { - // no text displayed for the parts icon - } - - function part_enter(event) { - if (!event) event = window.event; - var canvas = (window.event) ? event.srcElement : event.target; - var part = canvas.part; - - // avoid Chrome bug that changes to text cursor whenever - // drag starts. We'll restore the default handler at - // the appropriate point so behavior in other parts of - // the document are unaffected. - part.sch.saved_onselectstart = document.onselectstart; - document.onselectstart = function () { return false; }; - - canvas.style.borderColor = normal_style; - part.sch.message(part.tip+': drag onto diagram to insert'); - return false; - } - - function part_leave(event) { - if (!event) event = window.event; - var canvas = (window.event) ? event.srcElement : event.target; - var part = canvas.part; - - if (typeof part.sch.new_part == 'undefined') { - // leaving with no part selected? revert handler - document.onselectstart = part.sch.saved_onselectstart; - } - - canvas.style.borderColor = background_style; - part.sch.message(''); - return false; - } - - function part_mouse_down(event) { - if (!event) event = window.event; - var part = (window.event) ? event.srcElement.part : event.target.part; - - part.select(true); - part.sch.new_part = part; - return false; - } - - function part_mouse_up(event) { - if (!event) event = window.event; - var part = (window.event) ? event.srcElement.part : event.target.part; - - part.select(false); - part.sch.new_part = undefined; - return false; - } - - //////////////////////////////////////////////////////////////////////////////// - // - // Rectangle helper functions - // - //////////////////////////////////////////////////////////////////////////////// - - // rect is an array of the form [left,top,right,bottom] - - // ensure left < right, top < bottom - function canonicalize(r) { - var temp; - - // canonicalize bounding box - if (r[0] > r[2]) { - temp = r[0]; - r[0] = r[2]; - r[2] = temp; - } - if (r[1] > r[3]) { - temp = r[1]; - r[1] = r[3]; - r[3] = temp; - } - } - - function between(x,x1,x2) { - return x1 <= x && x <= x2; - } - - function inside(rect,x,y) { - return between(x,rect[0],rect[2]) && between(y,rect[1],rect[3]); - } - - // only works for manhattan rectangles - function intersect(r1,r2) { - // look for non-intersection, negate result - var result = !(r2[0] > r1[2] || - r2[2] < r1[0] || - r2[1] > r1[3] || - r2[3] < r1[1]); - - // if I try to return the above expression, javascript returns undefined!!! - return result; - } - - //////////////////////////////////////////////////////////////////////////////// - // - // Component base class - // - //////////////////////////////////////////////////////////////////////////////// - - function Component(type,x,y,rotation) { - this.sch = undefined; - this.type = type; - this.x = x; - this.y = y; - this.rotation = rotation; - this.selected = false; - this.properties = new Array(); - this.bounding_box = [0,0,0,0]; // in device coords [left,top,right,bottom] - this.bbox = this.bounding_box; // in absolute coords - this.connections = []; - } - - Component.prototype.json = function(index) { - this.properties['_json_'] = index; // remember where we are in the JSON list - - var props = {}; - for (var p in this.properties) props[p] = this.properties[p]; - - var conns = []; - for (var i = 0; i < this.connections.length; i++) - conns.push(this.connections[i].json()); - - var json = [this.type,[this.x, this.y, this.rotation],props,conns]; - return json; - } - - Component.prototype.add_connection = function(offset_x,offset_y) { - this.connections.push(new ConnectionPoint(this,offset_x,offset_y)); - } - - Component.prototype.update_coords = function() { - var x = this.x; - var y = this.y; - - // update bbox - var b = this.bounding_box; - this.bbox[0] = this.transform_x(b[0],b[1]) + x; - this.bbox[1] = this.transform_y(b[0],b[1]) + y; - this.bbox[2] = this.transform_x(b[2],b[3]) + x; - this.bbox[3] = this.transform_y(b[2],b[3]) + y; - canonicalize(this.bbox); - - // update connections - for (var i = this.connections.length - 1; i >= 0; --i) - this.connections[i].update_location(); - } - - Component.prototype.rotate = function(amount) { - var old_rotation = this.rotation; - this.rotation = (this.rotation + amount) % 8; - this.update_coords(); - - // create an undoable edit record here - // using old_rotation - } - - Component.prototype.move_begin = function() { - // remember where we started this move - this.move_x = this.x; - this.move_y = this.y; - } - - Component.prototype.move = function(dx,dy) { - // update coordinates - this.x += dx; - this.y += dy; - this.update_coords(); - } - - Component.prototype.move_end = function() { - var dx = this.x - this.move_x; - var dy = this.y - this.move_y; - - if (dx != 0 || dy != 0) { - // create an undoable edit record here - - this.sch.check_wires(this); - } - } - - Component.prototype.add = function(sch) { - this.sch = sch; // we now belong to a schematic! - sch.add_component(this); - this.update_coords(); - } - - Component.prototype.delete = function() { - // remove connection points from schematic - for (var i = this.connections.length - 1; i >= 0; --i) { - var cp = this.connections[i]; - this.sch.remove_connection_point(cp,cp.location); - } - - // remove component from schematic - this.sch.remove_component(this); - this.sch = undefined; - - // create an undoable edit record here - } - - Component.prototype.transform_x = function(x,y) { - var rot = this.rotation; - if (rot == 0 || rot == 6) return x; - else if (rot == 1 || rot == 5) return -y; - else if (rot == 2 || rot == 4) return -x; - else return y; - } - - Component.prototype.transform_y = function(x,y) { - var rot = this.rotation; - if (rot == 1 || rot == 7) return x; - else if (rot == 2 || rot == 6) return -y; - else if (rot == 3 || rot == 5) return -x; - else return y; - } - - Component.prototype.moveTo = function(c,x,y) { - var nx = this.transform_x(x,y) + this.x; - var ny = this.transform_y(x,y) + this.y; - this.sch.moveTo(c,nx,ny); - } - - Component.prototype.lineTo = function(c,x,y) { - var nx = this.transform_x(x,y) + this.x; - var ny = this.transform_y(x,y) + this.y; - this.sch.lineTo(c,nx,ny); - } - - Component.prototype.draw_line = function(c,x1,y1,x2,y2) { - c.strokeStyle = this.selected ? selected_style : normal_style; - var nx1 = this.transform_x(x1,y1) + this.x; - var ny1 = this.transform_y(x1,y1) + this.y; - var nx2 = this.transform_x(x2,y2) + this.x; - var ny2 = this.transform_y(x2,y2) + this.y; - this.sch.draw_line(c,nx1,ny1,nx2,ny2,1); - } - - Component.prototype.draw_circle = function(c,x,y,radius,filled) { - if (filled) c.fillStyle = this.selected ? selected_style : normal_style; - else c.strokeStyle = this.selected ? selected_style : normal_style; - var nx = this.transform_x(x,y) + this.x; - var ny = this.transform_y(x,y) + this.y; - - this.sch.draw_arc(c,nx,ny,radius,0,2*Math.PI,false,1,filled); - } - - rot_angle = [ - 0.0, // NORTH (identity) - Math.PI/2, // EAST (rot270) - Math.PI, // SOUTH (rot180) - 3*Math.PI/2, // WEST (rot90) - 0.0, // RNORTH (negy) - Math.PI/2, // REAST (int-neg) - Math.PI, // RSOUTH (negx) - 3*Math.PI/2, // RWEST (int-pos) - ]; - - Component.prototype.draw_arc = function(c,x,y,radius,start_radians,end_radians) { - c.strokeStyle = this.selected ? selected_style : normal_style; - var nx = this.transform_x(x,y) + this.x; - var ny = this.transform_y(x,y) + this.y; - this.sch.draw_arc(c,nx,ny,radius, - start_radians+rot_angle[this.rotation],end_radians+rot_angle[this.rotation], - false,1,false); - } - - Component.prototype.draw = function(c) { - } - - // result of rotating an alignment [rot*9 + align] - aOrient = [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, // NORTH (identity) - 2, 5, 8, 1, 4, 7, 0, 3, 6, // EAST (rot270) - 8, 7, 6, 5, 4, 3, 2, 1, 0, // SOUTH (rot180) - 6, 3, 0, 7, 4, 1, 8, 5, 3, // WEST (rot90) - 2, 1, 0, 5, 4, 3, 8, 7, 6, // RNORTH (negy) - 8, 5, 2, 7, 4, 1, 6, 3, 0, // REAST (int-neg) - 6, 7, 8, 3, 4, 5, 0, 1, 2, // RSOUTH (negx) - 0, 3, 6, 1, 4, 7, 2, 5, 8 // RWEST (int-pos) - ]; - - textAlign = [ - 'left', 'center', 'right', - 'left', 'center', 'right', - 'left', 'center', 'right' - ]; - - textBaseline = [ - 'top', 'top', 'top', - 'middle', 'middle', 'middle', - 'bottom', 'bottom', 'bottom' - ]; - - Component.prototype.draw_text = function(c,text,x,y,alignment,size,fill) { - var a = aOrient[this.rotation*9 + alignment]; - c.textAlign = textAlign[a]; - c.textBaseline = textBaseline[a]; - if (fill == undefined) - c.fillStyle = this.selected ? selected_style : normal_style; - else - c.fillStyle = fill; - this.sch.draw_text(c,text, - this.transform_x(x,y) + this.x, - this.transform_y(x,y) + this.y, - size); - } - - Component.prototype.set_select = function(which) { - if (which != this.selected) { - this.selected = which; - // create an undoable edit record here - } - } - - Component.prototype.select = function(x,y,shiftKey) { - this.was_previously_selected = this.selected; - if (this.near(x,y)) { - this.set_select(shiftKey ? !this.selected : true); - return true; - } else return false; - } - - Component.prototype.select_rect = function(s) { - this.was_previously_selected = this.selected; - if (intersect(this.bbox,s)) - this.set_select(true); - } - - // if connection point of component c bisects the - // wire represented by this compononent, return that - // connection point. Otherwise return null. - Component.prototype.bisect = function(c) { - return null; - } - - // does mouse click fall on this component? - Component.prototype.near = function(x,y) { - return inside(this.bbox,x,y); - } - - Component.prototype.edit_properties = function(x,y) { - if (this.near(x,y)) { - // make an widget for each property - var fields = new Array(); - for (var i in this.properties) - // underscore at beginning of property name => system property - if (i.charAt(0) != '_') - fields[i] = build_input('text',10,this.properties[i]); - - var content = build_table(fields); - content.fields = fields; - content.component = this; - - this.sch.dialog('Edit Properties',content,function(content) { - for (var i in content.fields) - content.component.properties[i] = content.fields[i].value; - content.component.sch.redraw_background(); - }); - return true; - } else return false; - } - - // clear the labels on all connections - Component.prototype.clear_labels = function() { - for (var i = this.connections.length - 1; i >=0; --i) { - this.connections[i].clear_label(); - } - } - - // default action: don't propagate label - Component.prototype.propagate_label = function(label) { - } - - // give components a chance to generate default labels for their connection(s) - // default action: do nothing - Component.prototype.add_default_labels = function() { - } - - // component should generate labels for all unlabeled connections - Component.prototype.label_connections = function() { - for (var i = this.connections.length - 1; i >=0; --i) { - var cp = this.connections[i]; - if (!cp.label) - cp.propagate_label(this.sch.get_next_label()); - } - } - - // default behavior: nothing to display for DC analysis - Component.prototype.display_current = function(c,vmap) { - } - - //////////////////////////////////////////////////////////////////////////////// - // - // Connection point - // - //////////////////////////////////////////////////////////////////////////////// - - connection_point_radius = 2; - - function ConnectionPoint(parent,x,y) { - this.parent = parent; - this.offset_x = x; - this.offset_y = y; - this.location = ''; - this.update_location(); - this.label = undefined; - } - - ConnectionPoint.prototype.toString = function() { - return ''; - } - - ConnectionPoint.prototype.json = function() { - return this.label; - } - - ConnectionPoint.prototype.clear_label = function() { - this.label = undefined; - } - - ConnectionPoint.prototype.propagate_label = function(label) { - // should we check if existing label is the same? it should be... - - if (this.label === undefined) { - // label this connection point - this.label = label; - - // propagate label to coincident connection points - this.parent.sch.propagate_label(label,this.location); - - // possibly label other cp's for this device? - this.parent.propagate_label(label); - } - } - - ConnectionPoint.prototype.update_location = function() { - // update location string which we use as a key to find coincident connection points - var old_location = this.location; - var parent = this.parent; - var nx = parent.transform_x(this.offset_x,this.offset_y) + parent.x; - var ny = parent.transform_y(this.offset_x,this.offset_y) + parent.y; - this.x = nx; - this.y = ny; - this.location = nx + ',' + ny; - - // add ourselves to the connection list for the new location - if (parent.sch) - parent.sch.update_connection_point(this,old_location); - } - - ConnectionPoint.prototype.coincident = function(x,y) { - return this.x==x && this.y==y; - } - - ConnectionPoint.prototype.draw = function(c,n) { - if (n != 2) - this.parent.draw_circle(c,this.offset_x,this.offset_y,connection_point_radius,n > 2); - } - - ConnectionPoint.prototype.display_voltage = function(c,vmap) { - var v = vmap[this.label]; - if (v != undefined) { - var label = v.toFixed(2) + 'V'; - - // first draw some solid blocks in the background - c.globalAlpha = 0.85; - this.parent.draw_text(c,'\u2588\u2588\u2588',this.offset_x,this.offset_y, - 4,annotation_size,element_style); - c.globalAlpha = 1.0; - - // display the node voltage at this connection point - this.parent.draw_text(c,label,this.offset_x,this.offset_y, - 4,annotation_size,annotation_style); - - // only display each node voltage once - delete vmap[this.label]; - } - } - - //////////////////////////////////////////////////////////////////////////////// - // - // Wire - // - //////////////////////////////////////////////////////////////////////////////// - - near_distance = 2; // how close to wire counts as "near by" - - function Wire(x1,y1,x2,y2) { - // arbitrarily call x1,y1 the origin - Component.call(this,'w',x1,y1,0); - this.dx = x2 - x1; - this.dy = y2 - y1; - this.add_connection(0,0); - this.add_connection(this.dx,this.dy); - - // compute bounding box (expanded slightly) - var r = [0,0,this.dx,this.dy]; - canonicalize(r); - r[0] -= near_distance; - r[1] -= near_distance; - r[2] += near_distance; - r[3] += near_distance; - this.bounding_box = r; - this.update_coords(); // update bbox - - // used in selection calculations - this.len = Math.sqrt(this.dx*this.dx + this.dy*this.dy); - } - Wire.prototype = new Component(); - Wire.prototype.constructor = Wire; - - Wire.prototype.toString = function() { - return ''; - } - - Wire.prototype.json = function(index) { - var json = ['w',[this.x, this.y, this.x+this.dx, this.y+this.dy]]; - return json; - } - - Wire.prototype.draw = function(c) { - this.draw_line(c,0,0,this.dx,this.dy); - } - - Wire.prototype.clone = function(x,y) { - return new Wire(x,y,x+this.dx,y+this.dy); - } - - Wire.prototype.near = function(x,y) { - // crude check: (x,y) within expanded bounding box of wire - if (inside(this.bbox,x,y)) { - // compute distance between x,y and nearst point on line - // http://www.allegro.cc/forums/thread/589720 - var D = Math.abs((x - this.x)*this.dy - (y - this.y)*this.dx)/this.len; - if (D <= near_distance) return true; - } - return false; - } - - // selection rectangle selects wire only if it includes - // one of the end points - Wire.prototype.select_rect = function(s) { - this.was_previously_selected = this.selected; - if (inside(s,this.x,this.y) || inside(s,this.x+this.dx,this.y+this.dy)) - this.set_select(true); - } - - // if connection point of component c bisects the - // wire represented by this compononent, return that - // connection point. Otherwise return null. - Wire.prototype.bisect = function(c) { - for (var i = c.connections.length - 1; i >= 0; --i) { - var cp = c.connections[i]; - var x = cp.x; - var y = cp.y; - - // crude check: (x,y) within expanded bounding box of wire - if (inside(this.bbox,x,y)) { - // compute distance between x,y and nearst point on line - // http://www.allegro.cc/forums/thread/589720 - var D = Math.abs((x - this.x)*this.dy - (y - this.y)*this.dx)/this.len; - // final check: ensure point isn't an end point of the wire - if (D < 1 && !this.connections[0].coincident(x,y) && !this.connections[1].coincident(x,y)) - return cp; - } - } - return null; - } - - Wire.prototype.move_end = function() { - this.sch.check_wires(this); - } - - // wires "conduct" their label to the other end - Wire.prototype.propagate_label = function(label) { - // don't worry about relabeling a cp, it won't recurse! - this.connections[0].propagate_label(label); - this.connections[1].propagate_label(label); - } - - // some actual component will start the labeling of electrical nodes, - // so do nothing here - Wire.prototype.label_connections = function() { - } - - //////////////////////////////////////////////////////////////////////////////// - // - // Ground - // - //////////////////////////////////////////////////////////////////////////////// - - function Ground(x,y,rotation) { - Component.call(this,'g',x,y,rotation); - this.add_connection(0,0); - this.bounding_box = [-6,0,6,8]; - this.update_coords(); - } - Ground.prototype = new Component(); - Ground.prototype.constructor = Ground; - - Ground.prototype.toString = function() { - return ''; - } - - Ground.prototype.draw = function(c) { - this.draw_line(c,0,0,0,8); - this.draw_line(c,-6,8,6,8); - } - - Ground.prototype.clone = function(x,y) { - return new Ground(x,y,this.rotation); - } - - // give components a chance to generate a label for their connection(s) - // default action: do nothing - Ground.prototype.add_default_labels = function() { - this.connections[0].propagate_label('0'); // canonical label for GND node - } - - //////////////////////////////////////////////////////////////////////////////// - // - // Label - // - //////////////////////////////////////////////////////////////////////////////// - - function Label(x,y,rotation,label) { - Component.call(this,'L',x,y,rotation); - this.properties['label'] = label ? label : '???'; - this.add_connection(0,0); - this.bounding_box = [-2,0,2,8]; - this.update_coords(); - } - Label.prototype = new Component(); - Label.prototype.constructor = Label; - - Label.prototype.toString = function() { - return ''; - } - - Label.prototype.draw = function(c) { - this.draw_line(c,0,0,0,8); - this.draw_text(c,this.properties['label'],0,9,1,property_size); - } - - Label.prototype.clone = function(x,y) { - return new Label(x,y,this.rotation,this.properties['label']); - } - - // give components a chance to generate a label for their connection(s) - // default action: do nothing - Label.prototype.add_default_labels = function() { - this.connections[0].propagate_label(this.properties['label']); - } - - //////////////////////////////////////////////////////////////////////////////// - // - // Scope Probe - // - //////////////////////////////////////////////////////////////////////////////// - - probe_colors = ['red','green','blue','cyan','magenta','black']; - probe_colors_rgb = { - 'red': 'rgb(255,64,64)', - 'green': 'rgb(64,255,64)', - 'blue': 'rgb(64,64,255)', - 'cyan': 'rgb(64,255,255)', - 'magenta' : 'rgb(255,64,255)', - 'black': 'rgb(0,0,0)', - }; - - function Probe(x,y,rotation,color) { - Component.call(this,'s',x,y,rotation); - this.add_connection(0,0); - this.properties['color'] = color ? color : 'cyan'; - this.bounding_box = [0,0,27,-21]; - this.update_coords(); - } - Probe.prototype = new Component(); - Probe.prototype.constructor = Probe; - - Probe.prototype.toString = function() { - return ''; - } - - Probe.prototype.draw = function(c) { - // draw outline - this.draw_line(c,0,0,4,-4); - this.draw_line(c,2,-6,6,-2); - this.draw_line(c,2,-6,17,-21); - this.draw_line(c,6,-2,21,-17); - this.draw_line(c,17,-21,21,-17); - this.draw_arc(c,19,-11,8,3*Math.PI/2,0); - - // fill body with plot color - c.fillStyle = probe_colors_rgb[this.properties['color']]; - c.beginPath(); - this.moveTo(c,2,-6) - this.lineTo(c,6,-2); - this.lineTo(c,21,-17); - this.lineTo(c,17,-21); - this.lineTo(c,2,-6); - c.fill(); - } - - Probe.prototype.clone = function(x,y) { - return new Probe(x,y,this.rotation,this.properties['color']); - } - - Probe.prototype.edit_properties = function(x,y) { - if (inside(this.bbox,x,y)) { - var fields = new Array(); - fields['Plot color'] = build_select(probe_colors,this.properties['color']); - - var content = build_table(fields); - content.fields = fields; - content.component = this; - - this.sch.dialog('Edit Properties',content,function(content) { - var color_choice = content.fields['Plot color']; - content.component.properties['color'] = probe_colors[color_choice.selectedIndex]; - content.component.sch.redraw_background(); - }); - return true; - } else return false; - } - - // return [color, node_label] for this probe - Probe.prototype.probe_info = function() { - return [this.properties['color'],this.connections[0].label]; - } - - //////////////////////////////////////////////////////////////////////////////// - // - // Resistor - // - //////////////////////////////////////////////////////////////////////////////// - - function Resistor(x,y,rotation,name,r) { - Component.call(this,'r',x,y,rotation); - this.properties['name'] = name; - this.properties['r'] = r ? r : '1'; - this.add_connection(0,0); - this.add_connection(0,48); - this.bounding_box = [-5,0,5,48]; - this.update_coords(); - } - Resistor.prototype = new Component(); - Resistor.prototype.constructor = Resistor; - - Resistor.prototype.toString = function() { - return ''; - } - - Resistor.prototype.draw = function(c) { - this.draw_line(c,0,0,0,12); - this.draw_line(c,0,12,4,14); - this.draw_line(c,4,14,-4,18); - this.draw_line(c,-4,18,4,22); - this.draw_line(c,4,22,-4,26); - this.draw_line(c,-4,26,4,30); - this.draw_line(c,4,30,-4,34); - this.draw_line(c,-4,34,0,36); - this.draw_line(c,0,36,0,48); - if (this.properties['r']) - this.draw_text(c,this.properties['r']+'\u03A9',5,24,3,property_size); - if (this.properties['name']) - this.draw_text(c,this.properties['name'],-5,24,5,property_size); - } - - Resistor.prototype.clone = function(x,y) { - return new Resistor(x,y,this.rotation,this.properties['name'],this.properties['r']); - } - - //////////////////////////////////////////////////////////////////////////////// - // - // Capacitor - // - //////////////////////////////////////////////////////////////////////////////// - - function Capacitor(x,y,rotation,name,c) { - Component.call(this,'c',x,y,rotation); - this.properties['name'] = name; - this.properties['c'] = c ? c : '1p'; - this.add_connection(0,0); - this.add_connection(0,48); - this.bounding_box = [-8,0,8,48]; - this.update_coords(); - } - Capacitor.prototype = new Component(); - Capacitor.prototype.constructor = Capacitor; - - Capacitor.prototype.toString = function() { - return ''; - } - - Capacitor.prototype.draw = function(c) { - this.draw_line(c,0,0,0,22); - this.draw_line(c,-8,22,8,22); - this.draw_line(c,-8,26,8,26); - this.draw_line(c,0,26,0,48); - if (this.properties['c']) - this.draw_text(c,this.properties['c']+'F',9,24,3,property_size); - if (this.properties['name']) - this.draw_text(c,this.properties['name'],-9,24,5,property_size); - } - - Capacitor.prototype.clone = function(x,y) { - return new Capacitor(x,y,this.rotation,this.properties['name'],this.properties['c']); - } - - //////////////////////////////////////////////////////////////////////////////// - // - // Inductor - // - //////////////////////////////////////////////////////////////////////////////// - - function Inductor(x,y,rotation,name,l) { - Component.call(this,'l',x,y,rotation); - this.properties['name'] = name; - this.properties['l'] = l ? l : '1n'; - this.add_connection(0,0); - this.add_connection(0,48); - this.bounding_box = [-4,0,5,48]; - this.update_coords(); - } - Inductor.prototype = new Component(); - Inductor.prototype.constructor = Inductor; - - Inductor.prototype.toString = function() { - return ''; - } - - Inductor.prototype.draw = function(c) { - this.draw_line(c,0,0,0,14); - this.draw_arc(c,0,18,4,6*Math.PI/4,3*Math.PI/4); - this.draw_arc(c,0,24,4,5*Math.PI/4,3*Math.PI/4); - this.draw_arc(c,0,30,4,5*Math.PI/4,2*Math.PI/4); - this.draw_line(c,0,34,0,48); - - if (this.properties['l']) - this.draw_text(c,this.properties['l']+'H',6,24,3,property_size); - if (this.properties['name']) - this.draw_text(c,this.properties['name'],-3,24,5,property_size); - } - - Inductor.prototype.clone = function(x,y) { - return new Inductor(x,y,this.rotation,this.properties['name'],this.properties['l']); - } - - //////////////////////////////////////////////////////////////////////////////// - // - // Diode - // - //////////////////////////////////////////////////////////////////////////////// - - function Diode(x,y,rotation,name,area) { - Component.call(this,'d',x,y,rotation); - this.properties['name'] = name; - this.properties['area'] = area ? area : '1'; - this.add_connection(0,0); // anode - this.add_connection(0,48); // cathode - this.bounding_box = [-8,0,8,48]; - this.update_coords(); - } - Diode.prototype = new Component(); - Diode.prototype.constructor = Diode; - - Diode.prototype.toString = function() { - return ''; - } - - Diode.prototype.draw = function(c) { - this.draw_line(c,0,0,0,16); - this.draw_line(c,-8,16,8,16); - this.draw_line(c,-8,16,0,32); - this.draw_line(c,8,16,0,32); - this.draw_line(c,-8,32,8,32); - this.draw_line(c,0,32,0,48); - - if (this.properties['area']) - this.draw_text(c,this.properties['area'],10,24,3,property_size); - if (this.properties['name']) - this.draw_text(c,this.properties['name'],-10,24,5,property_size); - } - - Diode.prototype.clone = function(x,y) { - return new Diode(x,y,this.rotation,this.properties['name'],this.properties['area']); - } - - //////////////////////////////////////////////////////////////////////////////// - // - // N-channel Mosfet - // - //////////////////////////////////////////////////////////////////////////////// - - function NFet(x,y,rotation,name,w_over_l) { - Component.call(this,'n',x,y,rotation); - this.properties['name'] = name; - this.properties['W/L'] = w_over_l ? w_over_l : '2'; - this.add_connection(0,0); // drain - this.add_connection(-24,24); // gate - this.add_connection(0,48); // source - this.bounding_box = [-24,0,8,48]; - this.update_coords(); - } - NFet.prototype = new Component(); - NFet.prototype.constructor = NFet; - - NFet.prototype.toString = function() { - return ''; - } - - NFet.prototype.draw = function(c) { - this.draw_line(c,0,0,0,16); - this.draw_line(c,-8,16,0,16); - this.draw_line(c,-8,16,-8,32); - this.draw_line(c,-8,32,0,32); - this.draw_line(c,0,32,0,48); - - this.draw_line(c,-24,24,-12,24); - this.draw_line(c,-12,16,-12,32); - - var dim = this.properties['W/L']; - if (this.properties['name']) { - this.draw_text(c,this.properties['name'],2,22,6,property_size); - this.draw_text(c,dim,2,26,0,property_size); - } else - this.draw_text(c,dim,2,24,3,property_size); - } - - NFet.prototype.clone = function(x,y) { - return new NFet(x,y,this.rotation,this.properties['name'],this.properties['W/L']); - } - - //////////////////////////////////////////////////////////////////////////////// - // - // P-channel Mosfet - // - //////////////////////////////////////////////////////////////////////////////// - - function PFet(x,y,rotation,name,w_over_l) { - Component.call(this,'p',x,y,rotation); - this.properties['name'] = name; - this.properties['W/L'] = w_over_l ? w_over_l : '2'; - this.add_connection(0,0); // drain - this.add_connection(-24,24); // gate - this.add_connection(0,48); // source - this.bounding_box = [-24,0,8,48]; - this.update_coords(); - } - PFet.prototype = new Component(); - PFet.prototype.constructor = PFet; - - PFet.prototype.toString = function() { - return ''; - } - - PFet.prototype.draw = function(c) { - this.draw_line(c,0,0,0,16); - this.draw_line(c,-8,16,0,16); - this.draw_line(c,-8,16,-8,32); - this.draw_line(c,-8,32,0,32); - this.draw_line(c,0,32,0,48); - - this.draw_line(c,-24,24,-16,24); - - this.draw_circle(c,-14,24,2,false); - this.draw_line(c,-12,16,-12,32); - - var dim = this.properties['W/L']; - if (this.properties['name']) { - this.draw_text(c,this.properties['name'],2,22,6,property_size); - this.draw_text(c,dim,2,26,0,property_size); - } else - this.draw_text(c,dim,2,24,3,property_size); - } - - PFet.prototype.clone = function(x,y) { - return new PFet(x,y,this.rotation,this.properties['name'],this.properties['W/L']); - } - - //////////////////////////////////////////////////////////////////////////////// - // - // Op Amp - // - //////////////////////////////////////////////////////////////////////////////// - - function OpAmp(x,y,rotation,name,A) { - Component.call(this,'o',x,y,rotation); - this.properties['name'] = name; - this.properties['A'] = A ? A : '30000'; - this.add_connection(0,0); // + - this.add_connection(0,16); // - - this.add_connection(48,8); // output - this.add_connection(24,32); // ground - this.bounding_box = [0,-8,48,32]; - this.update_coords(); - } - OpAmp.prototype = new Component(); - OpAmp.prototype.constructor = OpAmp; - - OpAmp.prototype.toString = function() { - return ''; - } - - OpAmp.prototype.draw = function(c) { - // triangle - this.draw_line(c,8,-8,8,24); - this.draw_line(c,8,-8,40,8); - this.draw_line(c,8,24,40,8); - // inputs and output - this.draw_line(c,0,0,8,0); - this.draw_line(c,0,16,8,16); - this.draw_text(c,'gnd',37,18,property_size); - this.draw_line(c,40,8,48,8); - this.draw_line(c,24,16,24,32); - // + and - - this.draw_line(c,10,0,16,0); - this.draw_line(c,13,-3,13,3); - this.draw_line(c,10,16,16,16); - - if (this.properties['name']) - this.draw_text(c,this.properties['name'],32,16,0,property_size); - } - - OpAmp.prototype.clone = function(x,y) { - return new OpAmp(x,y,this.rotation,this.properties['name'],this.properties['A']); - } - - //////////////////////////////////////////////////////////////////////////////// - // - // Source - // - //////////////////////////////////////////////////////////////////////////////// - - - function Source(x,y,rotation,name,type,value) { - Component.call(this,type,x,y,rotation); - this.properties['name'] = name; - if (value == undefined) value = 'dc(1)'; - this.properties['value'] = value; - this.add_connection(0,0); - this.add_connection(0,48); - this.bounding_box = [-12,0,12,48]; - this.update_coords(); - - this.content = document.createElement('div'); // used by edit_properties - } - Source.prototype = new Component(); - Source.prototype.constructor = Source; - - Source.prototype.toString = function() { - return '<'+this.type+'source '+this.properties['params']+' ('+this.x+','+this.y+')>'; - } - - Source.prototype.draw = function(c) { - this.draw_line(c,0,0,0,12); - this.draw_circle(c,0,24,12,false); - this.draw_line(c,0,36,0,48); - - if (this.type == 'v') { // voltage source - //this.draw_text(c,'+',0,12,1,property_size); - //this.draw_text(c,'\u2013',0,36,7,property_size); // minus sign - // draw + and - - this.draw_line(c,0,15,0,21); - this.draw_line(c,-3,18,3,18); - this.draw_line(c,-3,30,3,30); - // draw V - //this.draw_line(c,-3,20,0,28); - //this.draw_line(c,3,20,0,28); - } else if (this.type == 'i') { // current source - // draw arrow: pos to neg - this.draw_line(c,0,15,0,32); - this.draw_line(c,-3,26,0,32); - this.draw_line(c,3,26,0,32); - } - - if (this.properties['name']) - this.draw_text(c,this.properties['name'],-13,24,5,property_size); - if (this.properties['value']) - this.draw_text(c,this.properties['value'],13,24,3,property_size); - } - - // map source function name to labels for each source parameter - source_functions = { - 'dc': ['DC value'], - - 'impulse': ['Height', - 'Width (secs)'], - - 'step': ['Initial value', - 'Plateau value', - 'Delay until step (secs)', - 'Rise time (secs)'], - - 'square': ['Initial value', - 'Plateau value', - 'Frequency (Hz)'], - - 'triangle': ['Initial value', - 'Plateau value', - 'Frequency (Hz)'], - - 'pwl': ['Comma-separated list of alternating times and values'], - - 'pwl_repeating': ['Comma-separated list of alternating times and values'], - - 'pulse': ['Initial value', - 'Plateau value', - 'Delay until pulse (secs)', - 'Time for first transition (secs)', - 'Time for second transition (secs)', - 'Pulse width (secs)', - 'Period (secs)'], - - 'sin': ['Offset value', - 'Amplitude', - 'Frequency (Hz)', - 'Delay until sin starts (secs)', - 'Phase offset (degrees)'], - } - - // build property editor div - Source.prototype.build_content = function(src) { - // make an widget for each property - var fields = [] - fields['name'] = build_input('text',10,this.properties['name']); - - if (src == undefined) { - fields['value'] = this.properties['value']; - } else { - // fancy version: add select tag for source type - var src_types = []; - for (var t in source_functions) src_types.push(t); - var type_select = build_select(src_types,src.fun); - type_select.component = this; - type_select.addEventListener('change',source_type_changed,false) - fields['type'] = type_select; - - if (src.fun == 'pwl' || src.run == 'pwl_repeating') { - var v = ''; - var first = true; - for (var i = 0; i < src.args.length; i++) { - if (first) first = false; - else v += ','; - v += engineering_notation(src.args[i],3); - if (i % 2 == 0) v += 's'; - } - fields[source_functions[src.fun][0]] = build_input('text',30,v); - } else { - // followed separate input tag for each parameter - var labels = source_functions[src.fun]; - for (var i = 0; i < labels.length; i++) { - var v = engineering_notation(src.args[i],3); - fields[labels[i]] = build_input('text',10,v); - } - } - } - - var div = this.content; - if (div.hasChildNodes()) - div.removeChild(div.firstChild); // remove table of input fields - div.appendChild(build_table(fields)); - div.fields = fields; - div.component = this; - return div; - } - - function source_type_changed(event) { - if (!event) event = window.event; - var select = (window.event) ? event.srcElement : event.target; - - // see where to get source parameters from - var type = select.options[select.selectedIndex].value; - var src = undefined; - if (this.src != undefined && type == this.src.fun) - src = this.src; - else if (typeof cktsim != 'undefined') - src = cktsim.parse_source(type+'()'); - - select.component.build_content(src); - } - - Source.prototype.edit_properties = function(x,y) { - if (this.near(x,y)) { - this.src = undefined; - if (typeof cktsim != 'undefined') - this.src = cktsim.parse_source(this.properties['value']); - var content = this.build_content(this.src); - - this.sch.dialog('Edit Properties',content,function(content) { - var c = content.component; - var fields = content.fields; - - var first = true; - var value = ''; - for (var label in fields) { - if (label == 'name') - c.properties['name'] = fields['name'].value; - else if (label == 'value') { - // if unknown source type - value = fields['value'].value; - c.sch.redraw_background(); - return; - } else if (label == 'type') { - var select = fields['type']; - value = select.options[select.selectedIndex].value + '('; - } else { - if (first) first = false; - else value += ','; - value += fields[label].value; - } - } - c.properties['value'] = value + ')'; - c.sch.redraw_background(); - }); - return true; - } else return false; - } - - - function VSource(x,y,rotation,name,value) { - Source.call(this,x,y,rotation,name,'v',value); - this.type = 'v'; - } - VSource.prototype = new Component(); - VSource.prototype.constructor = VSource; - VSource.prototype.toString = Source.prototype.toString; - VSource.prototype.draw = Source.prototype.draw; - VSource.prototype.clone = Source.prototype.clone; - VSource.prototype.build_content = Source.prototype.build_content; - VSource.prototype.edit_properties = Source.prototype.edit_properties; - - // display current for DC analysis - VSource.prototype.display_current = function(c,vmap) { - var name = this.properties['name']; - var label = 'I(' + (name ? name : '_' + this.properties['_json_']) + ')'; - var v = vmap[label]; - if (v != undefined) { - // first draw some solid blocks in the background - c.globalAlpha = 0.5; - this.draw_text(c,'\u2588\u2588\u2588',-8,8,4,annotation_size,element_style); - c.globalAlpha = 1.0; - - // display the element current - var i = engineering_notation(v,2) + 'A'; - this.draw_text(c,i,-3,5,5,annotation_size,annotation_style); - // draw arrow for current - this.draw_line(c,-3,4,0,8); - this.draw_line(c,3,4,0,8); - // only display each current once - delete vmap[label]; - } - } - - VSource.prototype.clone = function(x,y) { - return new VSource(x,y,this.rotation,this.properties['name'],this.properties['value']); - } - - function ISource(x,y,rotation,name,value) { - Source.call(this,x,y,rotation,name,'i',value); - this.type = 'i'; - } - ISource.prototype = new Component(); - ISource.prototype.constructor = ISource; - ISource.prototype.toString = Source.prototype.toString; - ISource.prototype.draw = Source.prototype.draw; - ISource.prototype.clone = Source.prototype.clone; - ISource.prototype.build_content = Source.prototype.build_content; - ISource.prototype.edit_properties = Source.prototype.edit_properties; - - ISource.prototype.clone = function(x,y) { - return new ISource(x,y,this.rotation,this.properties['name'],this.properties['value']); - } - - /////////////////////////////////////////////////////////////////////////////// - // - // JQuery slider support for setting a component value - // - /////////////////////////////////////////////////////////////////////////////// - - function component_slider(event,ui) { - var sname = $(this).slider("option","schematic"); - - // set value of specified component - var cname = $(this).slider("option","component"); - var pname = $(this).slider("option","property"); - var suffix = $(this).slider("option","suffix"); - if (typeof suffix != "string") suffix = ""; - - var v = ui.value; - $(this).slider("value",v); // move slider's indicator - - var choices = $(this).slider("option","choices"); - if (choices instanceof Array) v = choices[v]; - - // selector may match several schematics - $("." + sname).each(function(index,element) { - element.schematic.set_property(cname,pname,v.toString() + suffix); - }) - - // perform requested analysis - var analysis = $(this).slider("option","analysis"); - if (analysis == "dc") - $("." + sname).each(function(index,element) { - element.schematic.dc_analysis(); - }) - - return false; - } - - /////////////////////////////////////////////////////////////////////////////// - // - // Module definition - // - /////////////////////////////////////////////////////////////////////////////// - - var module = { - 'Schematic': Schematic, - 'component_slider': component_slider, - } - return module; - }()); diff --git a/js/schematic.js b/js/schematic.js new file mode 120000 index 0000000000..4fdd928bc7 --- /dev/null +++ b/js/schematic.js @@ -0,0 +1 @@ +../../data/js/schematic.js \ No newline at end of file