Ticket #7786: trac_7786-template-jinja-idiomatic.10.patch

File trac_7786-template-jinja-idiomatic.10.patch, 266.3 KB (added by mpatel, 3 years ago)

DOM ready / load event timing fixes. Replaces previous.

  • deleted file sagenb/data/highlight/prettify.css

    # HG changeset patch
    # User Mitesh Patel <qed777@gmail.com>
    # Date 1262826026 28800
    # Node ID 52aad8c8742e464d4a7907226ea02d4df3487a5e
    # Parent  cc5ea607663824397f62312a594b4029297ff43f
    [mq]: trac_7786-template-jinja-idiomatic.5.patch
    
    diff --git a/sagenb/data/highlight/prettify.css b/sagenb/data/highlight/prettify.css
    deleted file mode 100644
    + -  
    1 /* Pretty printing styles. Used with prettify.js. */ 
    2  
    3 .str { color: #080; } 
    4 .kwd { color: #008; } 
    5 .com { color: #800; } 
    6 .typ { color: #606; } 
    7 .lit { color: #066; } 
    8 .pun { color: #660; } 
    9 .pln { color: #000; } 
    10 .tag { color: #008; } 
    11 .atn { color: #606; } 
    12 .atv { color: #080; } 
    13 .dec { color: #606; } 
    14 pre.prettyprint { padding: 2px; border: 1px solid #888; } 
    15  
    16 @media print { 
    17   .str { color: #060; } 
    18   .kwd { color: #006; font-weight: bold; } 
    19   .com { color: #600; font-style: italic; } 
    20   .typ { color: #404; font-weight: bold; } 
    21   .lit { color: #044; } 
    22   .pun { color: #440; } 
    23   .pln { color: #000; } 
    24   .tag { color: #006; font-weight: bold; } 
    25   .atn { color: #404; } 
    26   .atv { color: #060; } 
    27 } 
  • deleted file sagenb/data/sage/css/account_settings.css

    diff --git a/sagenb/data/sage/css/account_settings.css b/sagenb/data/sage/css/account_settings.css
    deleted file mode 100644
    + -  
    1 html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td { margin: 0; padding: 0; border: 0; outline: 0; font-weight: inherit; font-style: inherit; font-size: 100%; font-family: inherit; vertical-align: baseline; } 
    2  
    3 *:focus { outline: 0; } 
    4  
    5 body { line-height: 1em; color: black; background: #fff; } 
    6  
    7 ol, ul { list-style: none; } 
    8  
    9 /* tables still need 'cellspacing="0"' in the markup */ 
    10 table { border-collapse: separate; border-spacing: 0; vertical-align: middle; } 
    11  
    12 caption, th, td { text-align: left; font-weight: normal; vertical-align: middle; } 
    13  
    14 q, blockquote { quotes: "" ""; } 
    15 q:before, q:after, blockquote:before, blockquote:after { content: ""; } 
    16  
    17 img a { border: none; } 
    18  
    19 html { font-size: 100.1%; } 
    20  
    21 body { font: 100%/1.4 Arial, Helvetica, sans-serif; } 
    22  
    23 h1 { background: #DCDCDC; border-bottom: 1px solid #CCC; font-size: 2em; padding: 0 5px; } 
    24  
    25 label { display: block; } 
    26  
    27 #buttons { background: #DCDCDC; padding: 5px; } 
    28 #buttons button { margin-right: 1em; } 
    29  
    30 h2 { font-size: 1.5em; } 
    31  
    32 .section { border-bottom: 1px solid #CCC; padding: 5px; } 
    33 .section div { margin-bottom: 0.5em; } 
    34  
    35 .error { color: red; } 
    36  
    37 .updated { color: green; } 
    38  
    39 input.c1 { width: 200px; } 
  • sagenb/data/sage/css/main.css

    diff --git a/sagenb/data/sage/css/main.css b/sagenb/data/sage/css/main.css
    a b  
     1/* Warning: These .css files are automatically generated and will be overwritten */ 
     2/* when they are next generated. Please edit the SASS source located at */ 
     3/* <sagenb-spkg-root>/sass/src. Kindly refer to the readme for editing */ 
     4/* instructions at <sagenb-spkg-root>/sass */ 
    15thead { font-weight: bold; } 
    26 
    3 body { background-color: white; } 
     7body { background-color: white; font-family: "Gill Sans", "Gill Sans MT", "Myriad Pro", Myriad, "Liberation Sans", "Nimbus Sans L", Tahoma, Geneva, "Helvetica Neue", Helvetica, Arial, sans-serif; } 
    48body.worksheet-online { margin-bottom: 80%; } 
    59 
    610.hidden { display: none; } 
    711 
    812div.fivepix { height: 5px; } 
    913 
    10 /* ****** Top Bar (Banner, controls, etc.) ******** */ 
    1114body div#banner { font-size: 1.2em; float: left; margin: 0; max-width: 35%; } 
    1215body div#banner a.banner { text-decoration: none; border: none; margin-top: 2px; float: left; position: relative; } 
    1316body div#banner a.banner:visited { color: #1950c8; } 
    body div#banner a.banner span { margin-l 
    1619body div#banner #ping { float: left; } 
    1720body div#banner div.version { float: left; clear: left; font-size: xx-small; text-indent: 13px; color: black; } 
    1821 
    19 #controls { float: right; width: 65%; } 
    20 #controls ul { list-style: none; margin: 0; padding: 0; text-align: right; } 
    21 #controls ul li { border-right: 1px solid #000; color: #112abb; display: inline; font-size: 14px; margin: 0; padding: 0 0.5em; } 
    22 #controls ul li:last-child { border-right: 0; } 
    23 #controls ul li.username { border: 0; color: #000; font-family: sans-serif; font-weight: bold; padding: 0; } 
    24 #controls ul a { text-decoration: underline; white-space: nowrap; } 
    25 #controls ul a:hover { cursor: pointer; } 
     22#main-controls { float: right; width: 65%; } 
     23#main-controls ul { list-style: none; margin: 0; padding: 0; text-align: right; } 
     24#main-controls ul li { border-right: 1px solid #000; color: #112abb; display: inline; font-size: 14px; margin: 0; padding: 0 0.5em; } 
     25#main-controls ul li:last-child { border-right: 0; } 
     26#main-controls ul li.username { border: 0; color: #000; font-family: sans-serif; font-weight: bold; padding: 0; } 
     27#main-controls ul a { text-decoration: underline; white-space: nowrap; } 
     28#main-controls ul a:hover { cursor: pointer; } 
     29#main-controls ul #toggle-link { display: none; } 
     30 
     31.worksheet-online #main-controls ul #toggle-link { display: inline; } 
    2632 
    2733#top-bar { position: relative; padding: 10px 5px; border-bottom: 1px solid #c9d7f1; min-height: 40px; margin-bottom: 0.5em; overflow: hidden; display: inline-block; } 
    2834#top-bar { display: block; } 
    body div#banner div.version { float: lef 
    3137 
    3238hr.usercontrol { clear: both; float: left; } 
    3339 
    34 div#usercontrols { overflow: hidden; display: inline-block; clear: both; border-bottom: 1px solid #c9d7f1; padding: 10px; } 
    35 div#usercontrols { display: block; } 
     40div#user-controls { overflow: hidden; display: inline-block; clear: both; border-bottom: 1px solid #c9d7f1; padding: 10px; } 
     41div#user-controls { display: block; } 
    3642div#worksheet-list-controls { padding: 10px; clear: both; overflow: hidden; display: inline-block; } 
    3743div#worksheet-list-controls { display: block; } 
    3844div#worksheet-list-controls div.action-buttons { float: left; } 
    span.pane div.worksheet_list { position: 
    172178a.new_worksheet { font-family: arial, monospace; font-size: 12pt; text-align: right; color: #0000aa; } 
    173179a.new_worksheet:hover { cursor: pointer; } 
    174180 
    175 div.worksheet_bottom_padding { height: 50%; } 
    176 div.worksheet_top_padding { height: 5%; } 
    177181div.worksheet_menu { top: 50px; } 
    178182 
    179183a.worksheet_title { text-decoration: none; font-size: 20px; font-family: arial; font-weight: bold; color: #000000; } 
    span.control a.cs { color: #777777; text 
    212216span.control:hover a.cs, span.control a:hover.cs { color: black; border: 1px solid #333333; } 
    213217 
    214218/* *********** WORKSHEET ************************* */ 
    215 div.worksheet { background-color: white; border: 1px solid #aaa; } 
     219div.worksheet { background-color: white; border: 1px solid #aaa; padding: .75em 0.2em; } 
    216220div.banner { background-color: white; font-family: sans-serif; font-size: 18px; text-decoration: none; color: #1950c8; } 
    217221div.banner a.banner { text-decoration: none; border: none; margin-top: 2px; } 
    218222 
    pre.cell_input_hide:hover { cursor: text 
    248252textarea.cell_input_active { background-color: white; border: 2px solid  #8888fe; font-family: monospace; font-size: 12pt; overflow: hidden; padding-bottom: 0px; padding-left: 5px; padding-right: 0px; padding-top: 3px; margin-top: 0px; margin-bottom: 0px; line-height: 1.2em; width: 97%; } 
    249253 
    250254div.cell_input_active { background-color: white; border: 2px solid  #8888fe; font-family: monospace; font-size: 12pt; padding-bottom: 0px; padding-left: 5px; padding-right: 0px; padding-top: 3px; margin-top: 0px; margin-bottom: 0px; line-height: 1.2em; width: 97%; z-index: -100; visibility: hidden; position: absolute; } 
    251 div.cell_input_print { background-color: white; border: 1px solid  #a8a8a8; font-family: monospace; font-size: 12pt; padding-bottom: 1px; padding-left: 6px; padding-right: 1px; padding-top: 4px; margin-top: 0px; margin-bottom: 0px; line-height: 1.2em; width: 97%; } 
     255div.cell_input_print { background-color: white; border: 1px solid  #a8a8a8; font-family: monospace; font-size: 12pt; padding-bottom: 1px; padding-left: 6px; padding-right: 1px; padding-top: 4px; margin-top: 0px; margin-bottom: 0px; line-height: 1.2em; width: 97%; white-space: pre-wrap; } 
    252256 
    253257textarea.cell_input:hover { cursor: text; } 
    254258 
    span.worksheet_buttons { position: relat 
    304308.thin-right { position: absolute; top: auto; right: 0; width: 70%; } 
    305309 
    306310/* *********** User Home (Worksheet listing) ************************* */ 
    307 span.ratingmsg { color: #112abb; padding: 0.3em; font-size: 14px; } 
    308 span.pubmsg { font-family: sans-serif; color: #112abb; padding: 0.3em; font-size: 12px; } 
     311.ratingmsg { color: #112abb; padding: 0.3em; font-size: 14px; } 
     312 
     313.pubmsg { font-family: sans-serif; color: #112abb; padding: 0.3em; font-size: 12px; } 
    309314 
    310315#worksheet-list { clear: both; width: 100%; } 
    311316#worksheet-list thead { background-color: #e8eef7; } 
    312317#worksheet-list td.checkbox { padding: 4px; } 
    313318 
    314 a.usercontrol { color: #112abb; padding: 0.3em; font-size: 14px; text-decoration: underline; } 
    315 a.usercontrol:hover { cursor: pointer; } 
     319.controls a, .usercontrol { color: #112abb; font-size: 14px; text-decoration: underline; } 
     320.controls a:hover, .usercontrol:hover { cursor: pointer; } 
    316321 
    317 span.usercontrol { color: #112abb; padding: 0.3em; font-size: 14px; } 
     322.controls span { color: #112abb; padding: 0.3em; font-size: 14px; } 
    318323 
    319 a.boldusercontrol { color: #112abb; padding: 0.5em; font-weight: bold; font-size: 14px; } 
     324.user-controls a, .boldusercontrol { color: #112abb; font-weight: bold; font-size: 14px; } 
     325 
     326.user-controls a, .controls a, .controls span { padding: 0.3em; } 
     327 
    320328a.control, a.control-select { background-color: #7799bb; font-family: sans-serif; color: #ffffff; padding-top: 0.25em; padding-bottom: 0.25em; padding-left: 0.5em; padding-right: 0.5em; font-size: 15px; font-weight: bold; text-decoration: none; } 
    321329a.control:hover { cursor: pointer; } 
    322330a.control-select { background-color: #4477aa; } 
    323331a.control-select:hover { cursor: pointer; } 
    324332 
    325 span.sharebar { background-color: #4477aa; font-family: sans-serif; color: #ffffff; position: absolute; left: 0.5em; right: 0ex; padding-top: 0.5em; padding-bottom: 0.5em; padding-left: 2em; font-size: 18px; font-weight: bold; } 
     333.sharebar { background-color: #4477aa; font-family: sans-serif; color: #ffffff; padding-top: 0.5em; padding-bottom: 0.5em; padding-left: 2em; font-size: 1.25em; font-weight: bold; } 
    326334 
    327335textarea.edit { font-family: courier, monospace; font-size: 10pt; border: 1px solid #8cacbb; color: black; background-color: white; padding: 3px; overflow: auto; margin-top: 0.5em; } 
    328336 
    tr.thingreybox { background-color: #aaa; 
    347355 
    348356div.ultrathinspace { border: 0; height: 0px; } 
    349357 
    350 span.lastedit { font-family: sans-serif; font-size: 10px; color: #717171; } 
    351 span.revs { font-family: sans-serif; font-size: 12px; font-weight: bold; color: #333333; } 
    352 span.users { font-family: sans-serif; font-size: 13px; color: #222222; } 
     358.lastedit { font-family: sans-serif; font-size: 10px; color: #717171; } 
     359 
     360.revs { font-family: sans-serif; font-size: 12px; font-weight: bold; color: #333333; } 
     361 
     362.users { font-family: sans-serif; font-size: 13px; color: #222222; } 
    353363 
    354364a.share { font-family: sans-serif; font-size: 10px; color: #7777cc; } 
    355365 
    pre.plaintext { overflow: auto; font-fam 
    368378div.docidx { text-align: center; font-family: sans-serif; font-size: 16px; color: #222; font-weight: bold; } 
    369379 
    370380span.ping { display: none; } 
    371 span.pingdown { font-family: sans-serif; font-size: 15px; font-weight: bold; color: white; background-color: #990000; } 
     381span.pingdown { font-family: sans-serif; font-size: 15px; font-weight: bold; color: white; background-color: #990000; margin-left: 1em; } 
    372382 
    373 /* These have been scraped directly from pygment. */ 
     383#source-code-page .str { color: #080; } 
     384#source-code-page .kwd { color: #008; } 
     385#source-code-page .com { color: #800; } 
     386#source-code-page .typ { color: #606; } 
     387#source-code-page .lit { color: #066; } 
     388#source-code-page .pun { color: #660; } 
     389#source-code-page .pln { color: #000; } 
     390#source-code-page .tag { color: #008; } 
     391#source-code-page .atn { color: #606; } 
     392#source-code-page .atv { color: #080; } 
     393#source-code-page .dec { color: #606; } 
     394 
     395#source-code-page h1, #source-code-page h2 { text-align: center; } 
     396#source-code-page .filename { font-family: monospace; } 
     397#source-code-page code { display: block; border-top: 1px solid #ccc; border-bottom: 1px solid #ccc; padding: 1em; } 
     398 
     399#print-page h1 { text-align: center; } 
     400 
     401#guest-worksheet-page h1, #guest-worksheet-page h2 { text-align: center; } 
     402#guest-worksheet-page ul.controls { margin: 0; padding: 0; border: 0; outline: 0; overflow: hidden; display: inline-block; } 
     403#guest-worksheet-page ul.controls { display: block; } 
     404#guest-worksheet-page ul.controls li { list-style-type: none; margin-left: 0px; white-space: nowrap; display: inline; float: left; padding-left: 0.5em; padding-right: 0.5em; } 
     405#guest-worksheet-page ul.controls li.first { padding-left: 0px; } 
     406#guest-worksheet-page ul.controls li.last { padding-right: 0px; } 
     407 
     408#before-publish-page form a { text-decoration: none; } 
     409#before-publish-page form button { margin-left: 1em; margin-bottom: 0.5em; } 
     410#before-publish-page form input { margin-left: 1em; } 
     411 
     412#after-publish-page input { margin-top: 1em; } 
     413 
     414#edit-page .sharebar span { margin-right: 2em; } 
     415 
     416.settings-page { line-height: 1.4; } 
     417.settings-page h1 { font-size: 2em; padding: 0 5px; } 
     418.settings-page label { display: block; } 
     419.settings-page #buttons { padding: 5px; } 
     420.settings-page #buttons button { margin-right: 1em; } 
     421.settings-page #buttons a { text-decoration: none; } 
     422.settings-page h2 { font-size: 1.5em; margin: 0 0 0.75em; } 
     423.settings-page .section { border-bottom: 1px solid #CCC; padding: 5px; margin: 0.5em 0; } 
     424.settings-page .section div { margin-bottom: 0.5em; } 
     425.settings-page .error, .settings-page .error_found { color: red; } 
     426.settings-page .error_found { font-size: 1.2em; } 
     427.settings-page .updated { color: green; } 
     428.settings-page input.c1 { width: 200px; } 
     429 
     430#settings-nav { margin: 0; padding: 0; border: 0; outline: 0; overflow: hidden; display: inline-block; } 
     431#settings-nav { display: block; } 
     432#settings-nav li { list-style-type: none; margin-left: 0px; white-space: nowrap; display: inline; float: left; padding-left: 0.5em; padding-right: 0.5em; } 
     433#settings-nav li.first { padding-left: 0px; } 
     434#settings-nav li.last { padding-right: 0px; } 
     435#settings-nav li { border-right: 1px solid #ccc; } 
     436#settings-nav li:last-child, #settings-nav li.last { border-right: none; } 
     437 
     438#user-management-page table { border-collapse: collapse; } 
     439#user-management-page th, #user-management-page td { border: 1px solid #696969; padding: 0.25em; } 
     440#user-management-page th { background: #CCC; } 
     441#user-management-page a:link, #user-management-page a:visited { color: #112abb; } 
     442 
     443.accounts-page #wrapper { margin: 0 auto; max-width: 600px; } 
     444.accounts-page h1, .accounts-page h2, .accounts-page h3, .accounts-page h4, .accounts-page h5 { font-weight: normal; } 
     445.accounts-page h1 { border-bottom: 1px solid #696969; font-size: 2em; padding: 10px 0; } 
     446.accounts-page h2 { font-weight: bold; } 
     447.accounts-page h1, .accounts-page h2, .accounts-page p, .accounts-page li { margin-bottom: 10px; } 
     448.accounts-page .entry { margin-bottom: 10px; border: 1px solid #999; padding: 3px; width: 200; } 
     449.accounts-page li { border-bottom: 1px solid #CCC; } 
     450.accounts-page .error { color: red; } 
     451.accounts-page .error_found { color: red; font-size: 1.5em; } 
     452.accounts-page button { margin-right: 1em; } 
     453.accounts-page form label { display: block; } 
     454.accounts-page form div { margin-bottom: 1em; } 
     455.accounts-page form a { text-decoration: none; } 
     456 
     457#login-page h2 { font-size: 1.5em; margin-bottom: 0.375em; } 
     458#login-page h1, #login-page h2, #login-page h3, #login-page h4, #login-page h5, #login-page h6 { line-height: 1em; } 
     459#login-page p { margin-bottom: 1em; } 
     460#login-page strong { font-weight: bold; } 
     461#login-page #desc { float: left; margin-right: 400px; } 
     462#login-page div { padding: 0.5em 1em; } 
     463#login-page #sign-in-box { background-color: #efefff; float: left; margin-left: -400px; width: 350px; } 
     464#login-page #sign-in-box form label { display: block; } 
     465#login-page #sign-in-box a { font-size: 0.875em; } 
     466 
    374467.hll { background-color: #ffffcc; } 
    375468 
    376469.c { color: #408090; font-style: italic; } 
    span.pingdown { font-family: sans-serif; 
    474567.vc, .vg, .vi { color: #bb60d5; } 
    475568 
    476569.il { color: #208050; } 
    477  
    478 /* end stuff scraped from pygment */ 
  • deleted file sagenb/data/sage/css/master.css

    diff --git a/sagenb/data/sage/css/master.css b/sagenb/data/sage/css/master.css
    deleted file mode 100644
    + -  
    1 html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td { margin: 0; padding: 0; border: 0; outline: 0; font-weight: inherit; font-style: inherit; font-size: 100%; font-family: inherit; vertical-align: baseline; } 
    2  
    3 *:focus { outline: 0; } 
    4  
    5 body { line-height: 1em; color: black; background: #fff; } 
    6  
    7 ol, ul { list-style: none; } 
    8  
    9 /* tables still need 'cellspacing="0"' in the markup */ 
    10 table { border-collapse: separate; border-spacing: 0; vertical-align: middle; } 
    11  
    12 caption, th, td { text-align: left; font-weight: normal; vertical-align: middle; } 
    13  
    14 q, blockquote { quotes: "" ""; } 
    15 q:before, q:after, blockquote:before, blockquote:after { content: ""; } 
    16  
    17 img a { border: none; } 
    18  
    19 html { font-size: 100.1%; } 
    20  
    21 body { font: .9em/1.2em Arial, Helvetica, sans-serif; } 
    22  
    23 div { padding: 0.5em 1em; } 
    24  
    25 #desc { float: left; margin-right: 400px; } 
    26  
    27 #sign-in-box { float: left; margin-left: -400px; width: 350px; background-color: #efefff; } 
    28 #sign-in-box form label { display: block; } 
    29  
    30 p { margin-bottom: 1em; } 
    31  
    32 h1, h2, h3, h4, h5, h6 { line-height: 1em; } 
    33  
    34 h2 { font-size: 1.5em; margin-bottom: 0.375em; } 
    35  
    36 #banner { font-size: 1.2em; float: left; clear: both; margin-bottom: 0.25em; } 
    37 #banner a.banner { text-decoration: none; border: none; margin-top: 2px; float: left; } 
    38 #banner a.banner:visited { color: #1950c8; } 
    39 #banner #ping { display: none; } 
    40 #banner div.version { float: left; clear: left; font-size: xx-small; text-indent: 13px; color: black; } 
    41  
    42 .section { border-bottom: 1px solid #CCC; padding: 5px; } 
    43 .section > div { max-width: 350px; text-align: right; } 
    44  
    45 input.c1 { width: 200px; } 
    46  
    47 strong { font-weight: bold; } 
  • deleted file sagenb/data/sage/css/registration.css

    diff --git a/sagenb/data/sage/css/registration.css b/sagenb/data/sage/css/registration.css
    deleted file mode 100644
    + -  
    1 html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, dl, dt, dd, ol, ul, li, table, caption, tbody, tfoot, thead, tr, th, td { border: 0; font-family: inherit; font-size: 100%; font-style: inherit; font-weight: inherit; margin: 0; outline: 0; padding: 0; text-decoration: none; vertical-align: baseline; } 
    2  
    3 html { font-size: 100.1%; } 
    4  
    5 body { font: 0.88em/1.4 Arial, Helvetica, sans-serif; } 
    6  
    7 #wrapper { margin: 0 auto; max-width: 600px; } 
    8  
    9 h1, h2, h3, h4, h5 { font-wieght: normal; } 
    10  
    11 h1 { border-bottom: 1px solid #696969; font-size: 2em; padding: 10px 0; } 
    12  
    13 h2 { font-weight: bold; } 
    14  
    15 h1, h2, p, li { margin-bottom: 10px; } 
    16  
    17 .entry { margin-bottom: 10px; border: 1px solid #999; padding: 3px; width: 200; } 
    18  
    19 li { border-bottom: 1px solid #CCC; } 
    20  
    21 .error { color: red; } 
    22  
    23 .error_found { color: red; font-size: 1.5em; } 
    24  
    25 button { margin-right: 1em; } 
    26  
    27 form label { display: block; } 
    28 form div { margin-bottom: 1em; } 
  • sagenb/data/sage/css/test_report.css

    diff --git a/sagenb/data/sage/css/test_report.css b/sagenb/data/sage/css/test_report.css
    a b  
     1/* Warning: These .css files are automatically generated and will be overwritten */ 
     2/* when they are next generated. Please edit the SASS source located at */ 
     3/* <sagenb-spkg-root>/sass/src. Kindly refer to the readme for editing */ 
     4/* instructions at <sagenb-spkg-root>/sass */ 
    15body, table { background-color: #fff; color: #111; font-family: sans-serif; -moz-border-radius: 0.25em; -webkit-border-radius: 0.25em; } 
    26 
    37pre { margin: 0; padding: 0; padding-top: 0.25em; } 
  • deleted file sagenb/data/sage/css/user_management.css

    diff --git a/sagenb/data/sage/css/user_management.css b/sagenb/data/sage/css/user_management.css
    deleted file mode 100644
    + -  
    1 html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td { margin: 0; padding: 0; border: 0; outline: 0; font-weight: inherit; font-style: inherit; font-size: 100%; font-family: inherit; vertical-align: baseline; } 
    2  
    3 *:focus { outline: 0; } 
    4  
    5 body { line-height: 1em; color: black; background: #fff; } 
    6  
    7 ol, ul { list-style: none; } 
    8  
    9 /* tables still need 'cellspacing="0"' in the markup */ 
    10 table { border-collapse: separate; border-spacing: 0; vertical-align: middle; } 
    11  
    12 caption, th, td { text-align: left; font-weight: normal; vertical-align: middle; } 
    13  
    14 q, blockquote { quotes: "" ""; } 
    15 q:before, q:after, blockquote:before, blockquote:after { content: ""; } 
    16  
    17 img a { border: none; } 
    18  
    19 html { font-size: 100.1%; } 
    20  
    21 body { font: .9em/1.2em Arial, Helvetica, sans-serif; } 
    22  
    23 div { padding: 0.5em 1em; } 
    24  
    25 #desc { float: left; margin-right: 400px; } 
    26  
    27 #sign-in-box { float: left; margin-left: -400px; width: 350px; background-color: #efefff; } 
    28 #sign-in-box form label { display: block; } 
    29  
    30 p { margin-bottom: 1em; } 
    31  
    32 h1, h2, h3, h4, h5, h6 { line-height: 1em; } 
    33  
    34 h2 { font-size: 1.5em; margin-bottom: 0.375em; } 
    35  
    36 #banner { font-size: 1.2em; float: left; clear: both; margin-bottom: 0.25em; } 
    37 #banner a.banner { text-decoration: none; border: none; margin-top: 2px; float: left; } 
    38 #banner a.banner:visited { color: #1950c8; } 
    39 #banner #ping { display: none; } 
    40 #banner div.version { float: left; clear: left; font-size: xx-small; text-indent: 13px; color: black; } 
    41  
    42 .section { border-bottom: 1px solid #CCC; padding: 5px; } 
    43 .section > div { max-width: 350px; text-align: right; } 
    44  
    45 input.c1 { width: 200px; } 
    46  
    47 strong { font-weight: bold; } 
    48  
    49 body { margin: 10px; } 
  • deleted file sagenb/data/sage/html/account_recovery.html

    diff --git a/sagenb/data/sage/html/account_recovery.html b/sagenb/data/sage/html/account_recovery.html
    deleted file mode 100644
    + -  
    1 {% extends "html/base.html" %} 
    2  
    3 {% block title %}Account Recovery{% endblock %} 
    4 {% block css %}registration{% endblock %} 
    5  
    6 {% block body %} 
    7 <div id="wrapper"> 
    8     <h1>Account Recovery</h1> 
    9     <p>A new password will be emailed to the email address connected to your account. However if you didn't confirm your email address you will be unable to recover your account.</p>   
    10  
    11     <form method="GET" action="/forgotpass"> 
    12         <div> 
    13             <label for="username">Username</label> 
    14             <input type="text" name="username" size="15" /> 
    15         </div> 
    16         <div> 
    17             <button type="submit">Submit</button> <a href="/"><button >Cancel</button></a> 
    18         </div> 
    19 </form> 
    20 </div> 
    21  
    22  
    23 {% endblock %} 
  • deleted file sagenb/data/sage/html/account_settings.html

    diff --git a/sagenb/data/sage/html/account_settings.html b/sagenb/data/sage/html/account_settings.html
    deleted file mode 100644
    + -  
    1 {% extends "html/base.html" %} 
    2  
    3 {% block title %}Account Settings{% endblock %} 
    4 {% block css %}account_settings{% endblock %} 
    5 {% block page_id %}account-settings-page{% endblock %} 
    6 {% block body %} 
    7 <h1>Account Settings</h1> 
    8 <div class="section">{% if admin %}<a href="/users">Manage Users</a> | <a href="/notebooksettings">Notebook Settings</a> | {% endif %}<a href="/">My Worksheets</a> | <a href="/logout">Sign Out</a></div> 
    9  
    10   <form method="post" action="/settings"> 
    11      
    12     <div class="section"> 
    13       <h2>Change Auto-Save Interval</h2> 
    14       <div> 
    15         Minutes: 
    16         <select name="autosave"> 
    17         {% for i, selected in autosave_intervals %} 
    18           <option{{ selected }}>{{ i }}</option> 
    19         {% endfor %} 
    20         </select> 
    21       </div> 
    22     </div> 
    23     <div class="section"> 
    24       <h2>Change Password</h2> 
    25       <div id="passwd"> 
    26           <div> 
    27               <label for="old-pass">Old password</label> 
    28               <input type="password" name="old-pass" /> 
    29           </div> 
    30           <div> 
    31               <label for="new-pass">New password</label> 
    32               <input type="password" name="new-pass" /> 
    33           </div> 
    34           <div> 
    35               <label for="retype-pass">Retype new password</label> 
    36               <input type="password" name="retype-pass" /> 
    37           </div> 
    38       </div> 
    39     </div> 
    40  
    41     {% if true %} 
    42         <div class="section"> 
    43           <h2>Change E-mail Address</h2> 
    44      
    45           <div> 
    46               <div> 
    47                   <label>Current e-mail</label> 
    48                   {{ email_address }} {{ email_confirmed }} 
    49               </div> 
    50               <div> 
    51                   <label for="new-email">New e-mail</label> 
    52                   <input type="text" name="new-email" class="c1" /> 
    53               </div> 
    54           </div> 
    55         </div> 
    56         {% endif %} 
    57     <div id="buttons"> 
    58     <button type="submit">Save</button> 
    59     <a href="/"><button>Cancel</button></a> 
    60     </div> 
    61   </form> 
    62 {% endblock %} 
  • new file sagenb/data/sage/html/accounts/account_recovery.html

    diff --git a/sagenb/data/sage/html/accounts/account_recovery.html b/sagenb/data/sage/html/accounts/account_recovery.html
    new file mode 100644
    - +  
     1{% extends "html/accounts/base.html" %} 
     2 
     3{% block title %}Account Recovery{% endblock %} 
     4{% block page_id %}account-recovery-page{% endblock %} 
     5 
     6{% block body %} 
     7<div id="wrapper"> 
     8    <h1>Account Recovery</h1> 
     9    <p>A new password will be emailed to the email address connected to your account. However if you didn't confirm your email address you will be unable to recover your account.</p>   
     10 
     11    <form method="GET" action="/forgotpass"> 
     12        <div> 
     13            <label for="username">Username</label> 
     14            <input type="text" name="username" size="15" /> 
     15        </div> 
     16        <div> 
     17            <button type="submit">Submit</button> <a href="/"><button >Cancel</button></a> 
     18        </div> 
     19</form> 
     20</div> 
     21{% endblock %} 
  • new file sagenb/data/sage/html/accounts/base.html

    diff --git a/sagenb/data/sage/html/accounts/base.html b/sagenb/data/sage/html/accounts/base.html
    new file mode 100644
    - +  
     1{% extends "html/base.html" %} 
     2{% block body_classes %}accounts-page{% endblock %} 
  • new file sagenb/data/sage/html/accounts/registration.html

    diff --git a/sagenb/data/sage/html/accounts/registration.html b/sagenb/data/sage/html/accounts/registration.html
    new file mode 100644
    - +  
     1{% extends "html/accounts/base.html" %} 
     2 
     3{% block title %}Sign up{% endblock %} 
     4 
     5{% block page_id %}registration-page{% endblock %} 
     6 
     7{% block body %} 
     8<div id="wrapper"> 
     9    <h1>Sign up for a Sage Notebook account</h1> 
     10    {% if error %} 
     11    <h2 class="error_found">Error{{ error[1:] }}found</h2> 
     12    {% endif %} 
     13    <form method="POST" action="/register"> 
     14        <ol> 
     15            <li> 
     16                <h2>Create a username</h2> 
     17                <p>Your username must start with a letter and be between 3 and 64 
     18                characters long. You may only use letters, numbers, underscores, @, 
     19                and dots.</p> 
     20                <input type="text" name="username" value="{{ username }}" class="entry" tabindex="1" /> 
     21                {% if username_missing %} 
     22                <p><span class="error">Error:</span> No username given</p> 
     23                {% endif %} 
     24                {% if username_taken %} 
     25                <p><span class="error">Error:</span> Username already in use</p> 
     26                {% endif %} 
     27                {% if username_invalid %} 
     28                <p><span class="error">Error:</span> Bad username</p> 
     29                {% endif %} 
     30            </li> 
     31            <li> 
     32                <h2>Create a good password</h2> 
     33                <p> 
     34                    Your password must be between 4 and 32 characters 
     35                    long. Your password can not contain your username nor spaces. 
     36                </p> 
     37                <input type="password" name="password" class="entry" tabindex="2" /> 
     38                {% if password_missing %} 
     39                <p><span class="error">Error:</span> No password given</p> 
     40                {% endif %} 
     41                {% if password_invalid %} 
     42                <p><span class="error">Error:</span> Bad password</p> 
     43                {% endif %} 
     44            </li> 
     45            <li><h2>Re-type your password</h2> 
     46            <input type="password" name="retype_password" class="entry" tabindex="3" /> 
     47            {% if passwords_dont_match or retype_password_missing %} 
     48            <p><span class="error">Error:</span> Passwords didn't match</p> 
     49            {% endif %} 
     50            </li> 
     51            {% if email or email_missing or email_invaild %} 
     52            <li> 
     53                <h2>Enter your email address</h2> 
     54                <p> 
     55                    Your email address is required for account 
     56                    confirmation and recovery. You will be emailed a confirmation link 
     57                    right after you successfully sign up. 
     58                </p> 
     59                <input type="text" name="email" value="{{ email_address }}" class="entry" tabindex="4" /> 
     60                {% if email_missing %} 
     61                <p><span class="error">Error:</span> No email address given</p> 
     62                {% endif %} 
     63                {% if email_invalid %} 
     64                <p><span class="error">Error:</span> Invalid email address</p> 
     65                {% endif %} 
     66            </li> 
     67            {% endif %} 
     68            {% if challenge %} 
     69            <li> 
     70                <h2>Answer a challenge</h2> 
     71                {{ challenge_html }} 
     72                {% if challenge_missing %} 
     73                <p><span class="error">Error:</span> No challenge response given</p> 
     74                {% endif %} 
     75                {% if challenge_invalid %} 
     76                <p><span class="error">Error:</span> Invalid challenge response</p> 
     77                {% endif %} 
     78            </li> 
     79            {% endif %} 
     80        </ol> 
     81        <button type="submit" tabindex="100" id="create-account-button">Create account</button> 
     82        <a href="/"><button tabindex="101">Cancel</button></a> 
     83    </form> 
     84</div>  
     85{% endblock %} 
     86 No newline at end of file 
  • deleted file sagenb/data/sage/html/admin_add_user.html

    diff --git a/sagenb/data/sage/html/admin_add_user.html b/sagenb/data/sage/html/admin_add_user.html
    deleted file mode 100644
    + -  
    1 <html> 
    2 <head> 
    3 <title>Add New User | {{ sitename }}</title> 
    4 <style> 
    5 /***** Global Settings *****/ 
    6  
    7 html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,dl,dt,dd,ol,ul,li,table,caption,tbody,tfoot,thead,tr,th,td { 
    8 border:0; 
    9 font-family:inherit; 
    10 font-size:100%; 
    11 font-style:inherit; 
    12 font-weight:inherit; 
    13 margin:0; 
    14 outline:0; 
    15 padding:0; 
    16 text-decoration:none; 
    17 vertical-align:baseline 
    18 } 
    19  
    20 html { 
    21 font-size:100.1% 
    22 } 
    23  
    24 body { 
    25 font:0.88em/1.4 Arial, Helvetica, sans-serif; 
    26 } 
    27  
    28 #wrapper { 
    29 margin:0 auto; 
    30 max-width:600px 
    31 } 
    32  
    33 /***** Headings *****/ 
    34  
    35 h1,h2,h3,h4,h5 { 
    36 font-wieght:normal 
    37 } 
    38  
    39 h1 { 
    40 border-bottom:1px solid #696969; 
    41 font-size:2em; 
    42 padding:10px 0 
    43 } 
    44  
    45 h2 { 
    46 font-weight:bold 
    47 } 
    48  
    49 h1, h2, p, li, .entry { 
    50 margin-bottom:10px 
    51 } 
    52  
    53 .entry { 
    54 border:1px solid #999; 
    55 padding:3px; 
    56 width:200 
    57 } 
    58  
    59 li { 
    60 border-bottom:1px solid #CCC 
    61 } 
    62  
    63 .error, .error_found { 
    64 color:red 
    65 } 
    66  
    67 .error_found { 
    68 font-size:1.5em 
    69 } 
    70  
    71 .button { 
    72 font-size:1.2em 
    73 } 
    74 </style> 
    75 </head> 
    76 <body> 
    77 <div id="wrapper"> 
    78 <h1>Add New User</h1> 
    79 {% if error %} 
    80 <h2 class="error_found">Username Error</h2> 
    81 {% endif %} 
    82 <form method="POST" action="/adduser"> 
    83 <ol> 
    84 <li><h2>Pick a username</h2> 
    85 <p>The username must start with a letter and be between 4 and 32 characters long. It can only consist of letters, numbers, underscores, and one dot (.).</p> 
    86 <input type="text" name="username" value="{{ username }}" class="entry" /> 
    87 {% if username_error %} 
    88 {% if username_error == 'invalid' %} 
    89 <p><span class="error">Error:</span> Invalid username</p> 
    90 {% else %} 
    91 <p><span class="error">Error:</span> Username taken</p> 
    92 {% endif %} 
    93 {% endif %} 
    94 </li> 
    95 </ol> 
    96 <input type="submit" value="Create account" class="button" /> 
    97 <input type="button" value="Cancel" style="margin-left:10px" onClick="parent.location='/users'" class="button" /> 
    98 </form> 
    99 </div> 
    100 </body> 
    101 </html> 
    102  No newline at end of file 
  • deleted file sagenb/data/sage/html/banner.html

    diff --git a/sagenb/data/sage/html/banner.html b/sagenb/data/sage/html/banner.html
    deleted file mode 100644
    + -  
    1 <div id="banner"> 
    2     <a class="banner" href="http://nb.sagemath.org/"> 
    3         <img align="top" src="/images/sagenb.png" alt="Sage" /><span>The Sage Notebook</span> 
    4     </a> 
    5         <span class="ping" id="ping">Searching for Sage server...</span> 
    6     <div class="version"> 
    7         Version {{ sage_version }} 
    8     </div> 
    9 </div> 
  • sagenb/data/sage/html/base.html

    diff --git a/sagenb/data/sage/html/base.html b/sagenb/data/sage/html/base.html
    a b  
     1{%- macro render_title -%}{% block title %}{% endblock %}{%- endmacro -%} 
    12<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> 
    23<html lang="en"> 
    34    <head> 
    4         <title>{% block title %}{% endblock %}</title> 
     5        <title>{{ render_title() }} -- Sage</title> 
    56        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
    67        {% block pre_main_css %}{% endblock %} 
    7         <link type="text/css" rel="stylesheet" href="/css/{% block css %}master{% endblock %}.css" media="screen" /> 
     8        <link type="text/css" rel="stylesheet" href="/css/{% block css %}main{% endblock %}.css" /> 
    89        {% block more_css %}{% endblock %} 
    9         <!-- jQuery - general-purpose functions --> 
     10        {# jQuery and other universally used libraries #} 
    1011        <script type="text/javascript" src="/javascript/jquery/jquery-1.3.2.min.js"></script> 
    1112        {% block javascript %} 
    12         <!-- Worksheet list functions --> 
     13        {# Page-specific libraries #} 
    1314        <script type="text/javascript" src="/javascript/sage/ws_list.js"></script> 
    1415        {% endblock %} 
     16        {# Behavior #} 
     17        <script type="text/javascript" src="/javascript/sage/master.js"></script> 
    1518    </head> 
    16     <body {% block body_attrs %}{% endblock %} id="{% block page_id %}{% endblock %}"> 
    17         {% block body %}{% endblock %} 
     19    <body id="{% block page_id %}{% endblock %}" 
     20          class="{% block body_classes %}{% endblock %}"> 
     21        {% block body %} 
     22        <div id="header"> 
     23            {% block header %} 
     24            <div id="top-bar"> 
     25                <div id="banner"> 
     26                    <a class="banner" href="http://nb.sagemath.org/"> 
     27                        <img align="top" src="/images/sagenb.png" alt="Sage" /><span>The Sage Notebook</span> 
     28                    </a> 
     29                    <span class="ping" id="ping">Searching for Sage server...</span> 
     30                    <div class="version"> 
     31                        Version {{ sage_version }} 
     32                    </div> 
     33                </div> 
     34                {% block controls %} 
     35                {% endblock %} 
     36            </div> 
     37            {% endblock %} 
     38        </div> 
     39        <div id="main"> 
     40            {% block main %} 
     41 
     42            {% endblock %} 
     43        </div> 
     44        {% endblock %} 
    1845    </body> 
    19 </html> 
     46</html> 
     47 No newline at end of file 
  • new file sagenb/data/sage/html/base_authenticated.html

    diff --git a/sagenb/data/sage/html/base_authenticated.html b/sagenb/data/sage/html/base_authenticated.html
    new file mode 100644
    - +  
     1{% extends "html/base.html" %} 
     2{% block controls %} 
     3<div id="main-controls" class="controls"> 
     4    <ul> 
     5        <li class="username">{{ username }}</li> 
     6        {% if username == 'guest' %} 
     7        <li><a title="Please log in to the Sage notebook" href="/">Log in</a></li> 
     8        {% else %} 
     9        <li><a id="toggle-link" title="Toggle the top bar" onClick="$('#worksheet-bar').toggle()">Toggle</a></li> 
     10        <li><a title="Back to your personal worksheet list" href="/home/{{ username }}">Home</a></li> 
     11        {% if pub %} 
     12        <li><span>Published</span></li> 
     13        {% else %} 
     14        <li><a title="Browse the published worksheets" href="/pub">Published</a></li> 
     15        <li><a title="View a log of recent computations" href="#" onClick="history_window()">Log</a></li> 
     16        {% endif %} 
     17        <li><a title="Change account settings including password" href="/settings">Settings</a></li> 
     18        <li><a title="Documentation" href="#" onClick="help()">Help</a></li> 
     19        <li><a title="Report a problem or submit a bug to improve Sage" href="#" onClick="bugreport()">Report a Problem</a></li> 
     20        <li><a title="Log out of the Sage notebook" href="/logout">Sign out</a></li> 
     21        {% endif %} 
     22    </ul> 
     23</div> 
     24{% endblock %} 
  • deleted file sagenb/data/sage/html/command_history.html

    diff --git a/sagenb/data/sage/html/command_history.html b/sagenb/data/sage/html/command_history.html
    deleted file mode 100644
    + -  
    1  
    2 {# 
    3 INPUT: 
    4     - history_text - a string containing the history text of the notebook 
    5 #} 
    6 <html> 
    7     <head> 
    8         <title>Command History</title> 
    9         <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
    10     </head> 
    11     <body>  
    12         <pre>{{history_text}}</pre> 
    13         <a name="bottom"></a> 
    14         <script type="text/javascript"> window.location="#bottom"</script> 
    15     </body> 
    16 </html> 
    17  No newline at end of file 
  • sagenb/data/sage/html/docs.html

    diff --git a/sagenb/data/sage/html/docs.html b/sagenb/data/sage/html/docs.html
    a b  
    1 {% extends "html/base.html" %} 
     1{% extends "html/base_authenticated.html" %} 
    22 
    33{% block title %}Sage Documentation{% endblock %} 
    44 
    5 {% block css %}main{% endblock %} 
    6  
    75{% block javascript %} 
    86<script type="text/javascript" src="/javascript/sage/ws_list.js"></script> 
    97{% endblock%} 
    108 
    119{% block page_id %}docs-main-page{% endblock %} 
    1210 
    13 {% block body %} 
    14  
    15 {% include "html/top_bar.html" %} 
     11{% block main %} 
    1612 
    1713<div class="control-bar"> 
    1814    <ul class="controls"> 
    1915        <li><a title="To quickly try out Sage start here" href="/doc/live/tutorial/index.html">Tutorial</a></li> 
    20         <li><a title="View a 2000 page reference manual about Sage" href="/doc/live/reference/index.html">Reference Manual</a></li> 
     16        <li><a title="View a 4000+ page reference manual about Sage" href="/doc/live/reference/index.html">Reference Manual</a></li> 
    2117        <li><a title="Learn to write Sage programs" href="/doc/live/developer/index.html">Developer Guide</a></li> 
    2218        <li><a title="How do I construct ... in Sage?" href="/doc/live/constructions/index.html">Constructions</a></li> 
    2319    </ul> 
  • sagenb/data/sage/html/error_message.html

    diff --git a/sagenb/data/sage/html/error_message.html b/sagenb/data/sage/html/error_message.html
    a b  
    1 {% extends "html/base.html" %} 
     1{% extends "html/base_authenticated.html" %} 
    22 
    33{% block title %}Error{% endblock %} 
    44 
    5 {% block body %} 
    6 <br><a class="usercontrol" href="/">Home</a> 
    7 <hr class="usercontrol"> 
    8 <br/><br/> 
    9 {{ msg }} 
    10 <br/><br/> 
     5{% block main %} 
     6<div> 
     7    {{ msg }} 
     8</div> 
    119{% if cont %} 
    12 <center><a class="boldusercontrol" href="{{ cont }}"><font size=+1>Continue</font></a></center> 
     10<div> 
     11    <a class="boldusercontrol" href="{{ cont }}">Continue</a> 
     12</div> 
    1313{% endif %} 
    1414{% endblock %} 
  • sagenb/data/sage/html/history.html

    diff --git a/sagenb/data/sage/html/history.html b/sagenb/data/sage/html/history.html
    a b  
    22 
    33{% block title %}Sage: History for {{username}} {% endblock %} 
    44 
    5 {% block css %}main{% endblock %} 
    6  
    75{% block javascript %} 
    86<script type="text/javascript" src="/javascript/sage/ws_list.js"></script> 
    97{% endblock %} 
     
    119{% block page_id %}history-page{% endblock %} 
    1210 
    1311{% block body %} 
    14  
    15 {% include "html/top_bar.html" %} 
    16  
    1712    <pre>{{ text | escape }}</pre> 
    1813    <a title="Click here to turn the above into a Sage worksheet" href="/live_history">Create a new Sage worksheet version of the last 100 commands in the above log.</a> 
    1914    <a name="bottom"></a> 
    20     <script type="text/javascript">$(document).load(function(){window.location="#bottom"});</script> 
    21  
     15    <script type="text/javascript"> 
     16      $(window).load(function () { 
     17          window.location = "#bottom"; 
     18      }); 
     19    </script> 
    2220{% endblock %} 
  • deleted file sagenb/data/sage/html/list_top.html

    diff --git a/sagenb/data/sage/html/list_top.html b/sagenb/data/sage/html/list_top.html
    deleted file mode 100644
    + -  
    1 {% include "html/top_bar.html" %} 
    2  
    3 <div id="usercontrols"> 
    4     {% if pub is not defined or not pub %} 
    5     <a class="boldusercontrol" href="/new_worksheet" target="_blank">New Worksheet</a> 
    6     <a class="boldusercontrol" href="/upload">Upload</a> 
    7     {% if not accounts %} 
    8     <a class="boldusercontrol" href="/download_worksheets.zip">Download All Active</a> 
    9     {% endif %} 
    10     {% endif %} 
    11  
    12     <div id='search-area'> 
    13       <form action="." method="GET"> 
    14         <input type="hidden" value="{{ typ if not pub else 'pub' }}" name="typ" /> 
    15         <input id="search-worksheets" size="20" value="{{ search if search else "" }}" name="search" /> 
    16         <button class="add_new_worksheet_menu" id="search-worksheets-button" type="submit">Search Worksheets</button> 
    17       </form> 
    18     </div> 
    19 </div> 
  • sagenb/data/sage/html/login.html

    diff --git a/sagenb/data/sage/html/login.html b/sagenb/data/sage/html/login.html
    a b  
    22 
    33{% block title %}Sign in{% endblock %} 
    44 
    5 {% block body %} 
    6 {% include "html/banner.html" %}         
     5{% block page_id %}login-page{% endblock %} 
    76 
     7{% block main %} 
    88{% if welcome %} 
    99<h2>Congratulations {{ welcome }}! You can now sign into the Sage Notebook.</h2> 
    1010{% endif %} 
     
    5858            <label for="email">Username</label> 
    5959            <input type="text" name="email" value="{{ default_user }}" size="15" /> 
    6060            {% if username_error %} 
    61             <span style="color:red">Error:</span>Username is not in the system 
     61            <span style="color:red">Error: </span>Username is not in the system 
    6262            {% endif %} 
    6363        </div> 
    6464        <div> 
    6565            <label for="password">Password</label> 
    6666            <input type="password" name="password" size="15" /> 
    6767            {% if password_error %} 
    68             <span style="color:red">Error:</span>Wrong password 
     68            <span style="color:red">Error: </span>Wrong password 
    6969            {% endif %} 
    7070        </div> 
    7171        <div> 
    72             <input type="checkbox" name="remember" />Remember me 
     72            <input type="checkbox" name="remember" /> Remember me 
    7373        </div> 
    7474        <div> 
    7575            <button type="submit">Sign in</button> 
    7676        </div> 
    7777    </form> 
     78    {% if accounts %} 
    7879    <div> 
    79         {% if accounts %} 
    8080        <a href="/register" id="register-link"><strong>Sign up for a new Sage Notebook account</strong></a> 
    81         {% endif %} 
    8281    </div> 
     82    {% endif %} 
    8383    <div> 
    8484        <a href="/pub"><strong>Browse published Sage worksheets<br>(no login required)</strong></a> 
    8585    </div> 
     86    {% if recovery %} 
    8687    <div> 
    87         {% if recovery %} 
    8888        <a href="/forgotpass"><strong>Forgot password</strong></a> 
    89         {% endif %} 
    9089    </div> 
     90    {% endif %} 
    9191</div> 
    9292{% endblock %} 
    9393 
  • sagenb/data/sage/html/notebook/afterpublish_window.html

    diff --git a/sagenb/data/sage/html/notebook/afterpublish_window.html b/sagenb/data/sage/html/notebook/afterpublish_window.html
    a b  
    1 {% extends "html/notebook/worksheet_page_template.html" %} 
    2 {# 
    3 INPUT: 
    4 - worksheet - an instance of Worksheet 
    5 - worksheet_filename - a string containing a worksheet's filename 
    6 - username - a string containing a username 
    7 - url - a string containing the url of the published page 
    8 - time - a string representing the time of publication 
    9 - JSMATH - a boolean stating whether to include jsMath 
    10 - JEDITABLE_TINYMCE - a boolean stating whether to include jEditable and TinyMCE 
    11 #} 
     1{% extends "html/notebook/base_aux.html" %} 
     2 
     3{% block page_id %}after-publish-page{% endblock %} 
    124 
    135{% set checked = 'checked="true"' if worksheet.is_auto_publish() else '' %} 
    146 
    157{% block sharebar_title %} 
    16 Worksheet is publicly viewable at <a href="{{ url }}" style="color:#FFF" target="_blank">{{ url }}</a> 
    17 <br /> 
    18 Published on {{ time }} 
    19 <br /> 
    20 <br /> 
    21 <input type="button" value="Re-publish worksheet" onClick="parent.location='?re'" /> 
    22 <input type="button" value="Stop publishing" style="margin-left:5px" onClick="parent.location='?stop'" /> 
    23 <br /><br /> 
     8<p>Worksheet is publicly viewable at <a href="{{ url }}" style="color:#FFF" target="_blank">{{ url }}</a></p> 
     9<p>Published on {{ time }}</p> 
     10<div> 
     11    <a href=".?re"><button>Re-publish worksheet</button></a> 
     12    <a onClick="parent.location+='?stop'"><button>Stop publishing</button></p></a> 
     13</div> 
    2414<input type="checkbox" name="auto" {{ checked }} onchange="parent.location='?auto'"/> <label for="auto">Automatically re-publish when changes are made</label> 
    2515{% endblock %} 
    2616{% set select = "publish" %} 
  • new file sagenb/data/sage/html/notebook/base.html

    diff --git a/sagenb/data/sage/html/notebook/base.html b/sagenb/data/sage/html/notebook/base.html
    new file mode 100644
    - +  
     1{% extends "html/base_authenticated.html" %} 
     2{# 
     3INPUT: 
     4- notebook - an instance of Notebook 
     5- worksheet - an instance of Worksheet 
     6- username  - a string containing a username 
     7- title - a string 
     8- select    - a string containing the control that is selected 
     9- backwards - a boolean 
     10#} 
     11 
     12{% set system_names = worksheet.notebook().system_names() %} 
     13{% block title %}{{ worksheet.name() }}{% endblock %} 
     14 
     15 
     16{% block javascript %} 
     17<!-- jQuery UI - interacts, widgets, drag-drop, etc. --> 
     18<link rel="stylesheet" href="/javascript/jqueryui/css/sage/jquery-ui-1.7.2.custom.css" /> 
     19<script type="text/javascript" src="/javascript/jqueryui/js/jquery-ui-1.7.2.custom.min.js"></script> 
     20 
     21<!-- jQuery plugins - color pickers, shift-click, AJAX forms, IE fixes --> 
     22<link rel="stylesheet" href="/javascript/jquery/plugins/farbtastic/farbtastic.css" type="text/css" /> 
     23<script type="text/javascript" src="/javascript/jquery/plugins/farbtastic/farbtastic.min.js"></script> 
     24<script type="text/javascript" src="/javascript/jquery/plugins/extendedclick/jquery.event.extendedclick.min.js"></script> 
     25<script type="text/javascript" src="/javascript/jquery/plugins/form/jquery.form.min.js"></script> 
     26<script type="text/javascript" src="/javascript/jquery/plugins/jquery.bgiframe.min.js"></script> 
     27<link rel="stylesheet" href="/javascript/jquery/plugins/jpicker/css/jPicker-1.0.11.css" type="text/css" /> 
     28<script type="text/javascript" src="/javascript/jquery/plugins/jpicker/jpicker-1.0.11.min.js"></script> 
     29<link rel="stylesheet" media="screen" type="text/css" href="/javascript/jquery/plugins/colorpicker/css/colorpicker.css" /> 
     30<script type="text/javascript" src="/javascript/jquery/plugins/colorpicker/js/colorpicker.min.js"></script> 
     31 
     32<script type="text/javascript" src="/javascript/sage/main.js"></script> 
     33 
     34{% if JSMATH %} 
     35<!-- jsMath - typeset mathematics --> 
     36<script type="text/javascript" src="/javascript/sage/jsmath.js"></script> 
     37{% endif %} 
     38 
     39<!-- Sage3d - accelerated 3D graphics --> 
     40<script type="text/javascript" src="/javascript/sage3d/sage3d.js"></script> 
     41 
     42<!-- Jmol - embedded 3D graphics --> 
     43<script type="text/javascript" src="/java/jmol/appletweb/Jmol.js"></script> 
     44<!-- This must stay in head --> 
     45<script>jmolInitialize("/java/jmol");jmolSetCallback("menuFile","/java/jmol/appletweb/SageMenu.mnu");</script> 
     46 
     47{% if JEDITABLE_TINYMCE and not worksheet.docbrowser() and not worksheet.is_published() %} 
     48<!-- TinyMCE and jEditable - in-place editing of text cells --> 
     49<script type="text/javascript" src="/javascript/tiny_mce/tiny_mce.js"></script> 
     50<script type="text/javascript" src="/javascript/jquery/plugins/jeditable/jquery.jeditable.mini.js" charset="utf-8"></script> 
     51<script type="text/javascript" src="/javascript/sage/tinymce.js"></script> 
     52{% endif %} 
     53 
     54<script type="text/javascript">user_name= "{{ username }}";</script> 
     55{% if worksheet.filename() %} 
     56<script  type="text/javascript"> 
     57    worksheet_filename = "{{ worksheet.filename() }}"; 
     58    worksheet_name = "{{ worksheet.name() }}"; 
     59    server_ping_while_alive(); 
     60</script> 
     61{% endif %} 
     62 
     63{% endblock %} 
     64 
     65{% block main %} 
     66<div id="worksheet-bar"> 
     67    <div class="worksheet_title"> 
     68        <a id="worksheet_title" class="worksheet_title" 
     69           onClick="rename_worksheet(); return false;" 
     70           title="Click to rename this worksheet"> 
     71            {{ worksheet.name() }} 
     72        </a> 
     73        <div><span class="lastedit">{{ worksheet.html_time_last_edited() }}</span></div> 
     74        {% if worksheet.warn_about_other_person_editing(username) and username != 'guest' and not worksheet.is_doc_worksheet() %} 
     75        <span class="pingdown">(Someone else is viewing this worksheet)</span> 
     76        {% endif %} 
     77    </div> 
     78    <div id="save-discard-buttons"> 
     79        {% if not worksheet.is_doc_worksheet() %} 
     80        <button name="button_save" title="Save changes" onClick="save_worksheet();">Save</button><button title="Save changes and close window" onClick="save_worksheet_and_close();" name="button_save">Save & quit</button><button title="Discard changes to this worksheet" onClick="worksheet_discard();">Discard & quit</button> 
     81        {% endif %} 
     82    </div> 
     83     
     84    <div id="worksheet-menu"> 
     85        <select class="worksheet"  onchange="go_option(this);" id="file-menu"> 
     86            <option title="Select a file related function" value=""  selected>File...</option> 
     87            <option title="Load a new worksheet stored in a file" value="upload_worksheet_button();">Load worksheet from a file...</option> 
     88            <option title="Create a new worksheet" value="new_worksheet();">New worksheet</option> 
     89            <option title="Save this worksheet to an sws file" value="download_worksheet();">Save worksheet to a file...</option> 
     90            <option title="Print this worksheet" value="print_worksheet();">Print</option> 
     91            <option title="Rename this worksheet" value="rename_worksheet();">Rename worksheet</option> 
     92            <option title="Copy this worksheet" value="copy_worksheet();">Copy worksheet</option> 
     93            <option title="Move this worksheet to the trash" value="delete_worksheet('{{ worksheet.filename() }}');">Delete worksheet</option> 
     94        </select> 
     95 
     96        <select class="worksheet"  onchange="go_option(this);"  id="action-menu"> 
     97            <option title="Select a worksheet function" value="" selected>Action...</option> 
     98            <option title="Interrupt currently running calculations, if possible" value="interrupt();">Interrupt</option> 
     99            <option title="Restart the worksheet process" value="restart_sage();">Restart worksheet</option> 
     100            <option title="Quit the worksheet process" value="save_worksheet_and_close();">Save and quit worksheet</option>  
     101            <option value="">---------------------------</option> 
     102            <option title="Evaluate all input cells in the worksheet" value="evaluate_all();">Evaluate All</option> 
     103            <option title="Hide all output" value="hide_all();">Hide All Output</option> 
     104            <option title="Show all output" value="show_all();">Show All Output</option> 
     105            <option title="Delete all output" value="delete_all_output();">Delete All Output</option> 
     106            <option value="">---------------------------</option> 
     107            <option title="Switch to single-cell mode" value="slide_mode();">One Cell Mode</option> 
     108            <option title="Switch to multi-cell mode" value="cell_mode();">Multi Cell Mode</option>  
     109        </select> 
     110        <select class="worksheet" onchange="handle_data_menu(this);" id="data-menu"> 
     111            <option title="Select an attached file" value="" selected>Data...</option> 
     112            <option title="Upload or create a data file in a wide range of formats" value="__upload_data_file__">Upload or create file...</option> 
     113            <option value="">--------------------</option> 
     114            {% for name in worksheet.attached_data_files()|sort %} 
     115            <option value="datafile?name={{ name }}">{{ name }}</option> 
     116            {% endfor %} 
     117        </select> 
     118 
     119        {% if not worksheet.is_doc_worksheet() %} 
     120        <select onchange="go_system_select(this, {{ worksheet.system_index() }});" class="worksheet" id="systems-menu"> 
     121            {% for system_name in worksheet.notebook().systems() %} 
     122            <option title="Evaluate all input cells using {{ system_names[loop.index0] }}" 
     123                    {{ "selected" if worksheet.system_index() == loop.index0 else "" }} value="{{ system_names[loop.index0] }}"> 
     124                {{ system_name }} 
     125            </option> 
     126            {% endfor %} 
     127        </select>     
     128        <input type="checkbox" title="Enable/disable pretty_printing" 
     129               onchange="pretty_print_check(this.checked);" 
     130               class="worksheet" value="pretty_print" {{ "checked" if worksheet.pretty_print() else "" }} />&nbsp;Typeset 
     131        {% endif %} 
     132    </div> 
     133    <div id="share-publish-buttons"> 
     134        {% if not worksheet.is_doc_worksheet() %} 
     135        {% macro cls(x) %} 
     136        {{ "control-select" if x == select else "control" }} 
     137        {% endmacro %} 
     138        {% macro backwards_text() %}{{ "../" if backwards else "" }}{% endmacro %} 
     139        <a title="Print this worksheet" class="print-link" onClick="print_worksheet()"><img border=0 src="/images/icon_print.gif" alt="Print">Print</a> 
     140        <a class="{{ cls('use') }}" title="Interactively use this worksheet" onClick="edit_worksheet();">Worksheet</a>         
     141        <a class="{{ cls('edit') }}" title="Edit text version of this worksheet" href="{{ backwards_text() }}edit">Edit</a> 
     142        <a class="{{ cls('text') }}" title="View plain text version of this worksheet" href="{{ backwards_text() }}text">Text</a> 
     143        <a class="{{ cls('undo') }}" title="View changes to this worksheet over time" href="{{ backwards_text() }}revisions">Undo</a> 
     144        <a class="{{ cls('share') }}" title="Let others edit this worksheet" href="{{ backwards_text() }}share">Share</a> 
     145        <a class="{{ cls('publish') }}" title="Make this worksheet publicly viewable" href="{{ backwards_text() }}publish">Publish</a> 
     146        {% endif %} 
     147    </div> 
     148</div> 
     149<div class="hidden" id="slide_controls"> 
     150    <div class="slideshow_control"> 
     151        <a class="slide_arrow" onClick="slide_next()">&gt;</a> 
     152        <a class="slide_arrow" onClick="slide_last()">&gt;&gt;</a> <span class="vbar"></span> 
     153        <a class="cell_mode" onClick="cell_mode()">Exit</a> 
     154    </div> 
     155    <div class="slideshow_progress" id="slideshow_progress" onClick="slide_next()"> 
     156        <div class="slideshow_progress_bar" id="slideshow_progress_bar">&nbsp;</div> 
     157        <div class="slideshow_progress_text" id="slideshow_progress_text">&nbsp;</div> 
     158    </div> 
     159    <div class="slideshow_control"> 
     160        <a class="slide_arrow" onClick="slide_first()">&lt;&lt;</a> 
     161        <a class="slide_arrow" onClick="slide_prev()">&lt;</a> 
     162    </div> 
     163</div> 
     164{% block worksheet_main %}{% endblock %} 
     165{% endblock %} 
     166 
  • new file sagenb/data/sage/html/notebook/base_aux.html

    diff --git a/sagenb/data/sage/html/notebook/base_aux.html b/sagenb/data/sage/html/notebook/base_aux.html
    new file mode 100644
    - +  
     1{% extends "html/notebook/base.html" %} 
     2{# Base template for auxilliary pages (Edit, Text, etc.) #} 
     3 
     4{% block worksheet_main %} 
     5{% block before_sharebar %}{% endblock %} 
     6<div class="sharebar">{% block sharebar_title %}{% endblock %}</div> 
     7{% block after_sharebar %}{% endblock %} 
     8{% endblock %} 
  • sagenb/data/sage/html/notebook/beforepublish_window.html

    diff --git a/sagenb/data/sage/html/notebook/beforepublish_window.html b/sagenb/data/sage/html/notebook/beforepublish_window.html
    a b  
    1 {% extends "html/notebook/worksheet_page_template.html" %} 
    2 {# 
    3 INPUT: 
    4 - worksheet - an instance of Worksheet 
    5 - worksheet_filename - a string containing a worksheet's filename 
    6 - username - a string containing a username 
    7 - JSMATH - a boolean stating whether to include jsMath 
    8 - JEDITABLE_TINYMCE - a boolean stating whether to include jEditable and TinyMCE 
    9 #} 
     1{% extends "html/notebook/base_aux.html" %} 
    102 
     3{% block page_id %}before-publish-page{% endblock %} 
    114{% block sharebar_title %} 
    125<p>You can publish your worksheet to the Internet, where anyone will be able to access and view it online.</p> 
    136 
    INPUT: 
    1710 
    1811<form method="get" action="."> 
    1912    <input type="hidden" name="yes" value="" /> 
    20     <input type="submit" value="Yes" style="margin-left:10px" /> 
    21     <input type="button" value="No" style="margin-left:5px" onClick="parent.location='../'" /> 
    22     <br/> 
    23     <br/> 
    24     <input type="checkbox" name="auto" style="margin-left:13px" /> Automatically re-publish when changes are made 
     13    <div> 
     14        <button type="submit">Yes</button> 
     15        <a href="../"><button>No</button></a> 
     16    </div> 
     17    <div> 
     18        <input type="checkbox" name="auto" /> <label for="auto"> Automatically re-publish when changes are made</label> 
     19    </div> 
    2520</form> 
    2621{% endblock %} 
    2722{% set select = "publish" %} 
  • new file sagenb/data/sage/html/notebook/cell.html

    diff --git a/sagenb/data/sage/html/notebook/cell.html b/sagenb/data/sage/html/notebook/cell.html
    new file mode 100644
    - +  
     1{# 
     2INPUT: 
     3 
     4        - ``cell`` -- Cell instance 
     5 
     6        - ``wrap`` - an integer stating column position to wrap lines. Defaults to 
     7          configuration if not given. 
     8 
     9        - ``div_wrap`` - a boolean stating whether to wrap ``div``. 
     10 
     11        - ``do_print`` - a boolean stating whether the HTML is for 
     12        print or not. 
     13#} 
     14{% if do_print %} 
     15    {% set wrap = 68 %} 
     16    {% set div_wrap = true %} 
     17{% endif %} 
     18{% set cell_cls = "cell_evaluated" if cell.evaluated() or do_print else "cell_not_evaluated" %} 
     19 
     20{% if div_wrap %} 
     21<div id="cell_outer_{{ cell.id() }}" class="cell_visible"> 
     22    <div id="cell_{{ cell.id() }}" class="{{ cell_cls }}"> 
     23{% endif %} 
     24        {% if 'hideall' not in cell.percent_directives() %} 
     25        {# input #} 
     26        {% if not do_print %} 
     27            <div class="insert_new_cell" id="insert_new_cell_before{{ cell.id() }}"> 
     28            </div> 
     29            <script type="text/javascript"> 
     30                $("#insert_new_cell_before{{ cell.id() }}").plainclick(function (e) { 
     31                    insert_new_cell_before({{ cell.id() }}); 
     32                }); 
     33                {% if not cell.worksheet().docbrowser() %} 
     34                $("#insert_new_cell_before{{ cell.id() }}").shiftclick(function (e) { 
     35                    insert_new_text_cell_before({{ cell.id() }}); 
     36                }); 
     37                {% endif %} 
     38            </script> 
     39        {% endif %} 
     40            {% if 'hide' in cell.percent_directives() %} 
     41                {% set input_cls = 'cell_input_hide' %} 
     42            {% else %} 
     43                {% set input_cls = 'cell_input' %} 
     44            {% endif %} 
     45            {% if do_print %} 
     46                <div class="cell_input_print">{{ cell.input_text().rstrip()|escape }}&nbsp;</div> 
     47            {% else %} 
     48                <textarea class="cell_input" rows="{{ (1, cell.input_text().strip()|number_of_rows(80))|max }}" 
     49                          cols="80" 
     50                          id="cell_input_{{ cell.id() }}" 
     51                          {# TODO: Migrate these 'on' handlers to a .js file #} 
     52                          onKeyPress="return input_keypress({{ cell.id() }}, event);" 
     53                          onKeyDown="return input_keydown({{ cell.id() }},event);" 
     54                          onKeyUp="return input_keyup({{ cell.id() }}, event);" 
     55                          onBlur="cell_blur({{ cell.id() }}); return true;" 
     56                          onFocus="cell_focused(this, {{ cell.id() }}); return true;">{{ cell.input_text().rstrip() }}</textarea> 
     57                <a href="javascript:evaluate_cell({{ cell.id() }},0)" 
     58                   class="eval_button" 
     59                   id="eval_button{{ cell.id() }}" 
     60                   alt="Click here or press shift-return to evaluate"> 
     61                    evaluate 
     62                </a> 
     63            {% endif %} 
     64            {# end input #} 
     65 
     66            <div id='introspect_div_{{ cell.id() }}' class='introspection'></div> 
     67        {% endif %} 
     68 
     69        {% if do_print and cell.cell_output_type() == 'hidden' %} 
     70        <pre> 
     71        </pre> 
     72        {% else %} 
     73        {% set output_cls = 'cell_div_output_running' if cell.computing() else 'cell_div_output_' + cell.cell_output_type() %} 
     74        <div class="cell_output_div"> 
     75            <table class="cell_output_box"> 
     76                <tr> 
     77                    <td class="cell_number" id="cell_number_{{ cell.id() }}" 
     78                        {{ '' if do_print else 'onClick="cycle_cell_output_type(%s);"'|format(cell.id()) }} > 
     79                        {% for i in range(7) %}&nbsp;{% endfor %} 
     80                    </td> 
     81                    <td class="output_cell"> 
     82                        <div class="{{ output_cls }}" id="cell_div_output_{{ cell.id() }}"> 
     83                            <div class="cell_output_{{ "print_" if do_print else '' }}{{ cell.cell_output_type() }}" 
     84                                id="cell_output_{{ cell.id() }}"> 
     85                                {% if cell.introspect() %} 
     86                                    {{ cell.output_text(0, html=true) }} 
     87                                {% else %} 
     88                                    {{ cell.output_text(wrap, html=true) }} 
     89                                {% endif %} 
     90                            </div> 
     91                            {% if not do_print %} 
     92                                <div class="cell_output_{{ 'print_' if do_print else '' }}nowrap_{{ cell.cell_output_type() }}" 
     93                                     id="cell_output_nowrap_{{ cell.id() }}"> 
     94                                    {{ cell.output_text(0, html=true) }} 
     95                                </div> 
     96                            {% endif %} 
     97                                <div class="cell_output_html_{{ cell.cell_output_type() }}" 
     98                                     id="cell_output_html_{{ cell.id() }}"> 
     99                                    {{ cell.output_html() }} 
     100                                </div> 
     101                        </div> 
     102                    </td> 
     103                </tr> 
     104            </table> 
     105        </div> 
     106        {% endif %} 
     107         
     108{% if div_wrap %} 
     109    </div> 
     110</div> 
     111{% endif %} 
  • deleted file sagenb/data/sage/html/notebook/debug_window.html

    diff --git a/sagenb/data/sage/html/notebook/debug_window.html b/sagenb/data/sage/html/notebook/debug_window.html
    deleted file mode 100644
    + -  
    1  
    2 <div class='debug_window'> 
    3     <div class='debug_output'><pre id='debug_output'></pre></div> 
    4     <textarea rows=5 id='debug_input' class='debug_input'  
    5               onKeyPress='return debug_keypress(event);'  
    6               onFocus='debug_focus();' onBlur='debug_blur();'></textarea> 
    7 </div> 
    8  No newline at end of file 
  • sagenb/data/sage/html/notebook/doc_page.html

    diff --git a/sagenb/data/sage/html/notebook/doc_page.html b/sagenb/data/sage/html/notebook/doc_page.html
    a b  
    1 {% extends "html/notebook/index.html" %} 
     1{% extends "html/notebook/worksheet_page.html" %} 
    22 
    33{% block pre_main_css %} 
    44<link type="text/css" rel="stylesheet" href="_static/default.css" media="screen" /> 
  • sagenb/data/sage/html/notebook/download_or_delete_datafile.html

    diff --git a/sagenb/data/sage/html/notebook/download_or_delete_datafile.html b/sagenb/data/sage/html/notebook/download_or_delete_datafile.html
    a b  
    1 {% extends "html/notebook/worksheet_page_template.html" %} 
     1{% extends "html/notebook/base_aux.html" %} 
    22{# 
    33INPUT: 
    44- worksheet - an instance of Worksheet 
    5 - worksheet_filename - a string containing a worksheet's filename 
    65- username - a string containing a username 
    7 - active_worksheets - a list of the Worksheet instances that are active for username 
    86- filename_ - the name of the file 
    9 - path - the path to the file 
    107- file_is_image - a boolean stating whether the file is an image 
    118- file_is_text - a boolean stating whether the file is a text file 
    129- text_file_content - a string containing the content of a text file 
    13 - JSMATH - a boolean stating whether to include jsMath 
    14 - JEDITABLE_TINYMCE - a boolean stating whether to include jEditable and TinyMCE 
    1510#} 
    1611 
     12{% set path = "/home/%s/data/%s"|format(worksheet.filename(), filename_) %} 
     13 
    1714{% block sharebar_title %} 
    1815Data file: {{ filename_ }} 
    1916{% endblock %} 
    Data file: {{ filename_ }} 
    2118{% block after_sharebar %} 
    2219<p>You may download <a href="{{ path }}">{{ filename_ }}</a> or create a linked copy to the worksheet <select onchange="go_option(this);" class="worksheet"> 
    2320<option selected>select worksheet</option> 
    24 {% for worksheet in active_worksheets %} 
     21{% for worksheet in notebook.active_worksheets_for(username) %} 
    2522    <option value='link_datafile("{{ worksheet.filename() }}","{{ filename_ }}")'>{{ worksheet.name() }}</option> 
    2623{% endfor %} 
    2724</select> or <a href="/home/{{ worksheet.filename() }}/datafile?name={{ filename_ }}&action=delete">delete {{ filename_ }}.</a></p> 
    Data file: {{ filename_ }} 
    3532{% elif file_is_text %} 
    3633<form method="post" action="savedatafile" enctype="multipart/form-data"> 
    3734    <input type="submit" value="Save Changes" name="button_save" /> <input type="submit" value="Cancel" name="button_cancel" style="display:block" /> 
    38     <textarea class="edit" name="textfield" rows=17 cols=70 id="textfield">{{ text_file_content }}</textarea> 
     35    <textarea class="edit" name="textfield" rows=17 cols=70 id="textfield">{{ text_file_content | escape }}</textarea> 
    3936    <input type="hidden" name="filename" value="{{ filename_ }}" id="filename" /> 
    4037</form> 
    4138{% endif %} 
  • sagenb/data/sage/html/notebook/edit_window.html

    diff --git a/sagenb/data/sage/html/notebook/edit_window.html b/sagenb/data/sage/html/notebook/edit_window.html
    a b  
    1 {% extends "html/notebook/worksheet_page_template.html" %} 
    2 {# 
    3 INPUT: 
    4 - worksheet - an instance of Worksheet 
    5 - worksheet_filename - a string containing a worksheet's filename 
    6 - username - a string containing a username 
    7 - text - a string containing the text of the worksheet 
    8 - n_lines - number of lines of the text of the worksheet 
    9 - JSMATH - a boolean stating whether to include jsMath 
    10 - JEDITABLE_TINYMCE - a boolean stating whether to include jEditable and TinyMCE 
    11 #} 
     1{% extends "html/notebook/base_aux.html" %} 
    122 
    13 {% block sharebar_title %} 
    14 Edit plain text &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input type="submit" value="Save Changes" name="button_save" id="button_save"> <input type="submit" value="Cancel" name="button_cancel"> 
    15 {% endblock %} 
    16 {% set select = "edit" %} 
     3{% block page_id %}edit-page{% endblock %} 
    174 
    185{% block before_sharebar %} 
    196<form method="post" action="save" enctype="multipart/form-data"> 
    207{% endblock %} 
     8     
     9{% block sharebar_title %} 
     10    <span>Edit plain text</span> 
     11    <button type="submit" name="button_save" id="button_save">Save Changes</button> 
     12    <button type="submit" name="button_cancel">Cancel</button> 
     13{% endblock %} 
     14{% set select = "edit" %} 
     15 
    2116{% block after_sharebar %} 
    2217<script type="text/javascript"> 
    2318    function save_worksheet() { 
    Edit plain text &nbsp;&nbsp;&nbsp;&nbsp; 
    2520    function save_worksheet_and_close() { 
    2621    } 
    2722</script> 
    28     <textarea class="plaintextedit" id="cell_intext" name="textfield" rows="{{ n_lines }}">{{ text }}</textarea> 
     23    <textarea class="plaintextedit" id="cell_intext" name="textfield" rows="{{ worksheet.edit_text().count("\n")+1 }}">{{ worksheet.edit_text()|escape }}</textarea> 
    2924</form> 
    3025{% endblock %} 
  • deleted file sagenb/data/sage/html/notebook/guest_top_bar_and_worksheet.html

    diff --git a/sagenb/data/sage/html/notebook/guest_top_bar_and_worksheet.html b/sagenb/data/sage/html/notebook/guest_top_bar_and_worksheet.html
    deleted file mode 100644
    + -  
    1  
    2 {# 
    3 INPUT: 
    4 - original_worksheet - an instance of Worksheet 
    5 - worksheet - an instance of Worksheet 
    6 - notebook - an instance of Notebook which contains worksheet 
    7 - worksheet_html - a string containing the html for the worksheet 
    8 - username - a string containing a username 
    9 #} 
    10 {% if original_worksheet.is_collaborator(username) or original_worksheet.is_owner(username) %} 
    11     {% set edit_text = "Edit this." %} 
    12     {% set url       = "edit_published_page" %} 
    13 {% elif notebook.user_is_guest(username) %} 
    14     {% set edit_text = "Log in to edit a copy." %} 
    15     {% set url       = "/" %} 
    16 {% else %} 
    17     {% set edit_text = "Edit a copy." %} 
    18     {% set url       = "edit_published_page" %} 
    19 {% endif %} 
    20  
    21 {% set download_name = worksheet.download_name() %} 
    22  
    23 <a class="usercontrol" href="{{ url }}">{{ edit_text }}</a> 
    24 &nbsp;&nbsp;<a class="usercontrol" href="download/{{ download_name }}.sws">Download.</a> 
    25 &nbsp;&nbsp;<span class="ratingmsg"> 
    26     {% if worksheet.rating() != -1 %} 
    27         <a class="usercontrol" href="rating_info"> 
    28             This page is rated {{ "%.1f"|format(worksheet.rating()) }}. 
    29         </a> 
    30     {% endif %} 
    31     {% if not notebook.user_is_guest(username) 
    32         and not worksheet.is_publisher(username) %} 
    33         &nbsp;&nbsp; 
    34         <span class="usercontrol"> 
    35             {{ "Rerate" if worksheet.is_rater(username) else "Rate" }} it:  
    36         </span> 
    37         {% for i in range(5) %} 
    38             <a class="usercontrol" 
    39                onClick="rate_worksheet({{ i }})"> 
    40                 &nbsp;{{ i }}&nbsp; 
    41             </a> 
    42         {% endfor %} 
    43             &nbsp;&nbsp; <input name="rating_comment" id="rating_comment"></input> 
    44     {% endif %} 
    45 </span> 
    46 <span class="pubmsg"> 
    47     <a href="/pub/">Other published documents...</a> 
    48 </span> 
    49 <hr class="usercontrol" /> 
    50 <h1 align="center" class="title">{{ worksheet.name() }}</h1> 
    51 <h2 align="center">{{ worksheet.html_time_since_last_edited() }}</h2> 
    52 {{ worksheet_html }} 
    53 <hr class="usercontrol" /> 
    54 {% for i in range(10) %} 
    55 &nbsp; 
    56 {% endfor %} 
    57  
    58  
    59  
  • new file sagenb/data/sage/html/notebook/guest_worksheet_page.html

    diff --git a/sagenb/data/sage/html/notebook/guest_worksheet_page.html b/sagenb/data/sage/html/notebook/guest_worksheet_page.html
    new file mode 100644
    - +  
     1{% extends "html/notebook/base.html" %} 
     2{# 
     3INPUT: 
     4- worksheet - an instance of Worksheet 
     5- notebook - an instance of Notebook which contains worksheet 
     6- username - a string containing a username 
     7#} 
     8 
     9{% block page_id %}guest-worksheet-page{% endblock %} 
     10 
     11{% set original_worksheet = worksheet.worksheet_that_was_published() %} 
     12{% if original_worksheet.is_collaborator(username) or original_worksheet.is_owner(username) %} 
     13    {% set edit_text = "Edit this." %} 
     14    {% set url       = "edit_published_page" %} 
     15{% elif notebook.user_is_guest(username) %} 
     16    {% set edit_text = "Log in to edit a copy." %} 
     17    {% set url       = "/" %} 
     18{% else %} 
     19    {% set edit_text = "Edit a copy." %} 
     20    {% set url       = "edit_published_page" %} 
     21{% endif %} 
     22 
     23{% set download_name = worksheet.download_name() %} 
     24 
     25{% block body %} 
     26<ul class="controls"> 
     27    <li><a href="{{ url }}">{{ edit_text }}</a></li> 
     28    <li><a href="download/{{ download_name }}.sws">Download.</a></li> 
     29    {% if worksheet.rating() != -1 or 
     30       not (notebook.user_is_guest(username) or worksheet.is_publisher(username)) %} 
     31    <li> 
     32        {% if worksheet.rating() != -1 %} 
     33            <a class="usercontrol" href="rating_info"> 
     34                This page is rated {{ "%.1f"|format(worksheet.rating()) }}. 
     35            </a> 
     36        {% endif %} 
     37        {% if not (notebook.user_is_guest(username) or worksheet.is_publisher(username)) %} 
     38            <span> 
     39                {{ "Rerate" if worksheet.is_rater(username) else "Rate" }} it:  
     40            </span> 
     41            {% for i in range(5) %} 
     42                <a class="usercontrol" 
     43                   onClick="rate_worksheet({{ i }})">{{ i }}</a> 
     44            {% endfor %} 
     45                &nbsp;&nbsp; <input name="rating_comment" id="rating_comment" /> 
     46        {% endif %} 
     47    </li> 
     48    {% endif %} 
     49    <li><a href="/pub/">Other published documents...</a></li> 
     50</ul> 
     51<hr class="usercontrol" /> 
     52<h1 class="title">{{ worksheet.name() }}</h1> 
     53<h2 class="lastedit">{{ worksheet.html_time_since_last_edited() }}</h2> 
     54{{ worksheet.html(do_print=false, publish=true) }} 
     55<hr class="usercontrol" /> 
     56{% for i in range(10) %} 
     57&nbsp; 
     58{% endfor %} 
     59{% endblock %} 
     60 
     61 
     62 
  • deleted file sagenb/data/sage/html/notebook/head.tmpl

    diff --git a/sagenb/data/sage/html/notebook/head.tmpl b/sagenb/data/sage/html/notebook/head.tmpl
    deleted file mode 100644
    + -  
    1 {# 
    2 INPUT: 
    3 - worksheet - an instance of Worksheet 
    4 - worksheet_filename - a string containing a worksheet's filename 
    5 - username - a string containing a user's name 
    6 - JSMATH - a boolean stating whether to include jsMath 
    7 - JEDITABLE_TINYMCE - a boolean stating whether to include jEditable and TinyMCE 
    8   #} 
    9 {% macro common_title(worksheet_filename, worksheet) %} 
    10     {% if worksheet_filename %} 
    11         {{ worksheet.name() }} (Sage) 
    12     {% else %} 
    13         Sage Notebook | Welcome 
    14     {% endif %} 
    15 {% endmacro %} 
    16  
    17 {% macro common_javascript(worksheet, worksheet_filename, username, JSMATH, JEDITABLE_TINYMCE) %} 
    18 <!-- jQuery UI - interacts, widgets, drag-drop, etc. --> 
    19 <link rel="stylesheet" href="/javascript/jqueryui/css/sage/jquery-ui-1.7.2.custom.css" /> 
    20 <script type="text/javascript" src="/javascript/jqueryui/js/jquery-ui-1.7.2.custom.min.js"></script> 
    21  
    22 <!-- jQuery plugins - color pickers, shift-click, AJAX forms, IE fixes --> 
    23 <link rel="stylesheet" href="/javascript/jquery/plugins/farbtastic/farbtastic.css" type="text/css" /> 
    24 <script type="text/javascript" src="/javascript/jquery/plugins/farbtastic/farbtastic.min.js"></script> 
    25 <script type="text/javascript" src="/javascript/jquery/plugins/extendedclick/jquery.event.extendedclick.min.js"></script> 
    26 <script type="text/javascript" src="/javascript/jquery/plugins/form/jquery.form.min.js"></script> 
    27 <script type="text/javascript" src="/javascript/jquery/plugins/jquery.bgiframe.min.js"></script> 
    28 <link rel="stylesheet" href="/javascript/jquery/plugins/jpicker/css/jPicker-1.0.11.css" type="text/css" /> 
    29 <script type="text/javascript" src="/javascript/jquery/plugins/jpicker/jpicker-1.0.11.min.js"></script> 
    30 <link rel="stylesheet" media="screen" type="text/css" href="/javascript/jquery/plugins/colorpicker/css/colorpicker.css" /> 
    31 <script type="text/javascript" src="/javascript/jquery/plugins/colorpicker/js/colorpicker.min.js"></script> 
    32  
    33 <script type="text/javascript" src="/javascript/sage/main.js"></script> 
    34    
    35 {% if JSMATH %} 
    36 <!-- jsMath - typeset mathematics --> 
    37 <script type="text/javascript" src="/javascript/sage/jsmath.js"></script> 
    38 {% endif %} 
    39  
    40 <!-- Sage3d - accelerated 3D graphics --> 
    41 <script type="text/javascript" src="/javascript/sage3d/sage3d.js"></script> 
    42  
    43 <!-- Jmol - embedded 3D graphics --> 
    44 <script type="text/javascript" src="/java/jmol/appletweb/Jmol.js"></script> 
    45 <!-- This must stay in head --> 
    46 <script>jmolInitialize("/java/jmol");jmolSetCallback("menuFile","/java/jmol/appletweb/SageMenu.mnu");</script> 
    47  
    48 {% if JEDITABLE_TINYMCE and not worksheet.docbrowser() and not worksheet.is_published() %} 
    49 <!-- TinyMCE and jEditable - in-place editing of text cells --> 
    50 <script type="text/javascript" src="/javascript/tiny_mce/tiny_mce.js"></script> 
    51 <script type="text/javascript" src="/javascript/jquery/plugins/jeditable/jquery.jeditable.mini.js" charset="utf-8"></script> 
    52 <script type="text/javascript" src="/javascript/sage/tinymce.js"></script> 
    53 {% endif %} 
    54  
    55 <script type="text/javascript">user_name= "{{ username }}";</script> 
    56 {% if worksheet_filename %} 
    57 <script  type="text/javascript"> 
    58   worksheet_filename="{{ worksheet_filename }}"; 
    59   worksheet_name="{{ worksheet.name() }}"; 
    60   server_ping_while_alive(); 
    61 </script> 
    62 {% endif %} 
    63  
    64 {% endmacro %} 
  • deleted file sagenb/data/sage/html/notebook/index.html

    diff --git a/sagenb/data/sage/html/notebook/index.html b/sagenb/data/sage/html/notebook/index.html
    deleted file mode 100644
    + -  
    1 {% extends "html/base.html" %} 
    2  {# 
    3  INPUT: 
    4  - worksheet - an instance of Worksheet 
    5  - worksheet_filename - a string containing a worksheet's filename 
    6  - notebook - an instance of Notebook which contains worksheet 
    7  - username  - a string containing a username 
    8  - show_debug - a boolean stating whether to show debug information 
    9  - JSMATH - a boolean stating whether to include jsMath 
    10  - JSMATH_IMAGE_FONTS - a boolean stating whether to include jsMath iamage fonts 
    11  - JEDITABLE_TINYMCE - a boolean stating whether to include jEditable and TinyMCE 
    12  - sage_jsmath_macros - an array containing strings of Javascript of Sage macros for jsMath 
    13  - do_print - a boolean stating whether the file is for print mode 
    14  - worksheet_html - a string containing the html for a worksheet 
    15  - select    - a string containing the control that is selected 
    16  - backwards - a boolean 
    17  - warn - boolean stating whether to warn that another user is viewing 
    18           the worksheet 
    19 #} 
    20  
    21 {% if not select %} 
    22     {% set select = none %} 
    23 {% endif %} 
    24  
    25 {% if not backwards %} 
    26     {% set backwards = false %} 
    27 {% endif %} 
    28      
    29 {% include "html/notebook/head.tmpl"%} 
    30  
    31 {% block title %} 
    32 {{ common_title(worksheet_filename, worksheet) }} 
    33 {% endblock %} 
    34      
    35 {% block css %}main{% endblock %} 
    36  
    37 {% block javascript %} 
    38 {{ common_javascript(worksheet, worksheet_filename, username, JSMATH, JEDITABLE_TINYMCE) }} 
    39 {% endblock %} 
    40  
    41 {# TODO: Hack until the template restructuring #} 
    42 {% block body_attrs %} 
    43 {% if worksheet.is_published() or notebook.user_is_guest(username) %} 
    44         class="worksheet-online" onLoad="initialize_the_notebook();" 
    45     {% else %} 
    46         class="worksheet-online" onLoad="initialize_the_notebook();" id="user-worksheet-index" 
    47 {% endif %} 
    48 {% endblock %} 
    49  
    50  
    51 {% block body %} 
    52 {% if worksheet.is_published() or notebook.user_is_guest(username) %} 
    53     {% set original_worksheet = worksheet.worksheet_that_was_published() %} 
    54     {% include "html/notebook/guest_top_bar_and_worksheet.html" %} 
    55 {% else %} 
    56     {% include "html/notebook/top_bar_and_worksheet.html" %} 
    57 {% endif %} 
    58 {% if not worksheet %} 
    59     </td></tr></table></span> 
    60 {% endif %} 
    61 {% if worksheet.is_only_viewer(username) %} 
    62     <script type="text/javascript">worksheet_locked=true;</script> 
    63 {% else %} 
    64     <script type="text/javascript">worksheet_locked=false;</script> 
    65 {% endif %} 
    66 {% if worksheet.computing() %} 
    67     <!-- Set the update checking back in motion. --> 
    68     <script type="text/javascript"> 
    69         active_cell_list = {{ worksheet.queue_id_list() }}; 
    70         for(var i = 0; i < active_cell_list.length; i++) { 
    71             cell_set_running(active_cell_list[i]); 
    72         } 
    73         start_update_check(); 
    74     </script> 
    75 {% endif %} 
    76 {% endblock %} 
  • sagenb/data/sage/html/notebook/plain_text_window.html

    diff --git a/sagenb/data/sage/html/notebook/plain_text_window.html b/sagenb/data/sage/html/notebook/plain_text_window.html
    a b  
    1 {% extends "html/notebook/worksheet_page_template.html" %} 
    2 {# 
    3 INPUT: 
    4 - worksheet - an instance of Worksheet 
    5 - worksheet_filename - a string containing a worksheet's filename 
    6 - username - a string containing a username 
    7 - plain_text - a string containing the plain text version 
    8 - JSMATH - a boolean stating whether to include jsMath 
    9 - JEDITABLE_TINYMCE - a boolean stating whether to include jEditable and TinyMCE 
    10 #} 
     1{% extends "html/notebook/base_aux.html" %} 
    112 
    123{% block sharebar_title %} 
    134View plain text 
    View plain text 
    167{% set select = "text" %} 
    178 
    189{% block after_sharebar %} 
    19 <pre class="plaintext" id="cell_intext" name="textfield">{{ plain_text }}</pre> 
     10<pre class="plaintext" id="cell_intext" name="textfield">{{ worksheet.plain_text(prompts=true, banner=false)|escape|trim }}</pre> 
    2011{% endblock %} 
  • deleted file sagenb/data/sage/html/notebook/plain_text_worksheet.html

    diff --git a/sagenb/data/sage/html/notebook/plain_text_worksheet.html b/sagenb/data/sage/html/notebook/plain_text_worksheet.html
    deleted file mode 100644
    + -  
    1  
    2 {# 
    3 INPUT: 
    4      - worksheet_name - a string containing a worksheet's name 
    5      - worksheet_plain_text - a string containing the plain text version of a worksheet 
    6 #} 
    7 <head> 
    8     <title>Sage Worksheet: {{ worksheet_name }}</title> 
    9     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
    10 </head> 
    11 <body> 
    12     <h1><a href=".">Sage Worksheet: %s</a></h1> 
    13     <pre>{{ worksheet_plain_text }}</pre> 
    14 </body> 
    15  No newline at end of file 
  • new file sagenb/data/sage/html/notebook/print_worksheet.html

    diff --git a/sagenb/data/sage/html/notebook/print_worksheet.html b/sagenb/data/sage/html/notebook/print_worksheet.html
    new file mode 100644
    - +  
     1{% extends "html/notebook/base.html" %} 
     2 
     3{% block page_id %}print-page{% endblock %} 
     4 
     5{% block body %} 
     6<h1>{{ worksheet.name() }}</h1> 
     7{{ worksheet.html(do_print=true) }} 
     8{% endblock %} 
     9 
     10  
     11 No newline at end of file 
  • deleted file sagenb/data/sage/html/notebook/slide_controls.html

    diff --git a/sagenb/data/sage/html/notebook/slide_controls.html b/sagenb/data/sage/html/notebook/slide_controls.html
    deleted file mode 100644
    + -  
    1  
    2 <div class="hidden" id="slide_controls"> 
    3     <div class="slideshow_control"> 
    4         <a class="slide_arrow" onClick="slide_next()">&gt;</a> 
    5         <a class="slide_arrow" onClick="slide_last()">&gt;&gt;</a> <span class="vbar"></span> 
    6         <a class="cell_mode" onClick="cell_mode()">Exit</a> 
    7     </div> 
    8     <div class="slideshow_progress" id="slideshow_progress" onClick="slide_next()"> 
    9         <div class="slideshow_progress_bar" id="slideshow_progress_bar">&nbsp;</div> 
    10         <div class="slideshow_progress_text" id="slideshow_progress_text">&nbsp;</div> 
    11     </div> 
    12     <div class="slideshow_control"> 
    13         <a class="slide_arrow" onClick="slide_first()">&lt;&lt;</a> 
    14         <a class="slide_arrow" onClick="slide_prev()">&lt;</a> 
    15     </div> 
    16 </div> 
    17  
    18  
    19  
    20  
    21  
    22  
    23  
  • sagenb/data/sage/html/notebook/specific_revision.html

    diff --git a/sagenb/data/sage/html/notebook/specific_revision.html b/sagenb/data/sage/html/notebook/specific_revision.html
    a b  
    1 {% extends "html/notebook/worksheet_page_template.html" %} 
    2 {# 
    3 INPUT: 
    4 - worksheet - an instance of Worksheet 
    5 - worksheet_filename - a string containing a worksheet's filename 
    6 - username - a string containing a username 
    7 - rev - this revision's key 
    8 - prev_rev - the previous revision's key 
    9 - next_rev - the next revision's key 
    10 - time_ago - a string containing the time since revision 
    11 - body_worksheet_html - the body html of the worksheet 
    12 - JSMATH - a boolean stating whether to include jsMath 
    13 - JEDITABLE_TINYMCE - a boolean stating whether to include jEditable and TinyMCE 
    14 #} 
     1{% extends "html/notebook/base_aux.html" %} 
    152 
    163{% set select = "revisions" %} 
    174{% block sharebar_title %} 
    Revision from {{ time_ago }} ago&nbsp;&n 
    4027{% block after_sharebar %} 
    4128{{ actions() }} 
    4229<div id="revision-data"> 
    43     {{ body_worksheet_html }} 
     30    {{ worksheet.html(do_print=true, publish=true) }} 
    4431</div> 
    4532{{ actions() }} 
    4633<script type="text/javascript"> 
  • new file sagenb/data/sage/html/notebook/text_cell.html

    diff --git a/sagenb/data/sage/html/notebook/text_cell.html b/sagenb/data/sage/html/notebook/text_cell.html
    new file mode 100644
    - +  
     1{# 
     2INPUT: 
     3 
     4- cell -- Cell instance 
     5 
     6- wrap -- number of columns to wrap 
     7 
     8- do_print -- whether to display for printing 
     9 
     10- do_math_parse -- whether to parse jsMath 
     11 
     12- editing -- whether user is editing the cell 
     13#} 
     14<span id="cell_outer_{{ cell.id() }}"> 
     15    {% if not do_print and not cell.worksheet().docbrowser() %} 
     16    <div class="insert_new_cell" id="insert_new_cell_before{{ cell.id() }}"> 
     17    </div> 
     18    <script type="text/javascript"> 
     19        $("#insert_new_cell_before{{ cell.id() }}").plainclick(function (e) { 
     20            insert_new_cell_before({{ cell.id() }}); 
     21        }); 
     22        $("#insert_new_cell_before{{ cell.id() }}").shiftclick(function (e) { 
     23            insert_new_text_cell_before({{ cell.id() }}); 
     24        }); 
     25    </script> 
     26    {% endif %} 
     27    <div class="text_cell" id="cell_text_{{ cell.id() }}"> 
     28        {% if do_math_parse %} 
     29            {{ cell.plain_text()|math_parse }} 
     30        {% else %} 
     31            {{ cell.plain_text() }} 
     32    {% endif %} 
     33    </div> 
     34{% if JEDITABLE_TINYMCE and not cell.worksheet().is_published() and not cell.worksheet().docbrowser() and not do_print %} 
     35    <script type="text/javascript"> 
     36        $("#cell_text_{{ cell.id() }}").unbind('dblclick').editable(function(value,settings) { 
     37            evaluate_text_cell_input({{ cell.id() }},value,settings); 
     38            return(value); 
     39            }, 
     40            { 
     41                tooltip   : "", 
     42                placeholder : "", 
     43        //      type   : 'textarea', 
     44                type   : 'mce', 
     45                onblur : 'ignore', 
     46                select : false, 
     47                submit : 'Save changes', 
     48                cancel : 'Cancel changes', 
     49                event  : "dblclick", 
     50                style  : "inherit", 
     51        }); 
     52    </script> 
     53{% endif %} 
     54 
     55{% if editing and not do_print %} 
     56    <script> 
     57        $("#cell_text_{{ cell.id() }}").trigger('dblclick'); 
     58    </script> 
     59{% endif %} 
     60</span> 
  • deleted file sagenb/data/sage/html/notebook/top_bar_and_worksheet.html

    diff --git a/sagenb/data/sage/html/notebook/top_bar_and_worksheet.html b/sagenb/data/sage/html/notebook/top_bar_and_worksheet.html
    deleted file mode 100644
    + -  
    1 {# 
    2 INPUT: 
    3 - username - a string containing a username 
    4 - worksheet_filename - a string containing a worksheet's filename 
    5 - worksheet_html - a string containing the html for a worksheet 
    6 - show_debug - a boolean stating whether to show debug information 
    7   #} 
    8 {% include "html/notebook/worksheet_topbar.tmpl" %} 
    9 {% set toggle=true %} 
    10 {% include "html/top_bar.html" %} 
    11 {% if worksheet.filename() %} 
    12     {{ worksheet_topbar(worksheet, "use", username) }} 
    13 {% endif %} 
    14 {% if show_debug %} 
    15     {% include "html/notebook/debug_window.html" %} 
    16 {% endif %} 
    17  
    18 <div class="worksheet" id="worksheet"> 
    19     {{ worksheet_html }} 
    20 </div> 
    21  
  • sagenb/data/sage/html/notebook/upload_data_window.html

    diff --git a/sagenb/data/sage/html/notebook/upload_data_window.html b/sagenb/data/sage/html/notebook/upload_data_window.html
    a b  
    1 {% extends "html/notebook/worksheet_page_template.html" %} 
    2 {# 
    3 INPUT: 
    4 - worksheet - an instance of Worksheet 
    5 - worksheet_filename - a string containing a worksheet's filename 
    6 - username - a string containing a username 
    7 - JSMATH - a boolean stating whether to include jsMath 
    8 - JEDITABLE_TINYMCE - a boolean stating whether to include jEditable and TinyMCE 
    9 #} 
     1{% extends "html/notebook/base_aux.html" %} 
     2 
    103 
    114{% block page_id %}upload-data-page{% endblock %} 
    125 
    Upload or Create Data File to attach to  
    2013          name="upload" enctype="multipart/form-data"> 
    2114        <div> 
    2215            <label for="file">Browse your computer to select a worksheet file to upload:</label> 
    23             <input size="50" type="file" name="file"></input> 
     16            <input size="50" type="file" name="file" /> 
    2417        </div> 
    2518        <div> 
    2619            <label for="url">Or enter the url of a worksheet file on the web:</label> 
    27             <input size="50" type="text" name="url"></input> 
     20            <input size="50" type="text" name="url" /> 
    2821        </div> 
    2922        <div> 
    3023            <label for="new">Or enter the name of a new file, which will be created:</label> 
    31             <input size="50" type="text" name="new"></input> 
     24            <input size="50" type="text" name="new" /> 
    3225        </div> 
    3326        <div> 
    3427            <label for="name">What do you want to call it? (if different than the original name)</label> 
    35             <input size="50" type="text" name="name"></input> 
     28            <input size="50" type="text" name="name" /> 
    3629        </div> 
    3730        <button type="submit">Upload or Create Data File</button> 
    3831    </form> 
  • sagenb/data/sage/html/notebook/worksheet.html

    diff --git a/sagenb/data/sage/html/notebook/worksheet.html b/sagenb/data/sage/html/notebook/worksheet.html
    a b  
    11{# 
    22INPUT: 
    3      - worksheet_name - a string containing a worksheet's name 
    4      - worksheet_html - a string containing the html for a worksheet 
    5      - do_print - a boolean stating whether to render a print version of the 
    6                   worksheet 
    7   #} 
    8 {% extends "html/base.html" %} 
    93 
    10 {% block title %}Sage Worksheet: {{ worksheet_name }}{% endblock %} 
     4- worksheet -- Worksheet object 
    115 
    12 {% block css %}main{% endblock %} 
     6- publish -- boolean whether this is for the published version 
    137 
    14 {% block javascript %} 
    15 <script type="text/javascript" src="/javascript/sage/main.js"></script> 
    16 {% if do_print %} 
    17 <script type="text/javascript" src="/javascript/sage/jsmath.js"></script> 
    18 {% endif %}     
    19 {% endblock %} 
     8- do_print -- boolean whether this is for a print version 
    209 
    21 {% block body_attrs %} 
    22 {% if not do_print %} 
    23     class="worksheet-online" onLoad="initialize_the_notebook();" 
     10#} 
     11 
     12{% set wrap = conf['word_wrap_cols'] %} 
     13{% if not publish %} 
     14    {% set publish = worksheet.is_published() %} 
    2415{% endif %} 
    25 {% endblock %} 
    2616 
    27 {% block body %} 
    28 {% if do_print %} 
    29     <div class="worksheet_print_title"> {{ worksheet_name }}</div> 
     17<div class="cell_input_active" id="cell_resizer"></div> 
     18{% if not publish %} 
     19<div class="worksheet_cell_list" id="worksheet_cell_list"> 
    3020{% endif %} 
    31 {{ worksheet_html }} 
    32 {% if do_print %} 
    33     <script type="text/javascript">jsMath.Process();</script> 
     21 
     22{% for cell in worksheet.cell_list() %} 
     23    {{ cell.html(wrap = wrap, div_wrap = true, do_print = do_print or publish) }} 
     24{% endfor %} 
     25 
     26{% if not do_print and not publish %} 
     27</div> 
     28<div class="insert_new_cell" id="insert_last_cell"></div> 
     29<script type="text/javascript"> 
     30    $("#insert_last_cell").plainclick(function (e) { 
     31        insert_new_cell_after(cell_id_list[cell_id_list.length - 1]); 
     32    }); 
     33{% if not worksheet.docbrowser() %} 
     34    $("#insert_last_cell").shiftclick(function (e) { 
     35        insert_new_text_cell_after(cell_id_list[cell_id_list.length - 1]); 
     36    }); 
    3437{% endif %} 
    35 {% endblock %} 
     38</script> 
     39{% endif %} 
  • new file sagenb/data/sage/html/notebook/worksheet_page.html

    diff --git a/sagenb/data/sage/html/notebook/worksheet_page.html b/sagenb/data/sage/html/notebook/worksheet_page.html
    new file mode 100644
    - +  
     1{% extends "html/notebook/base.html" %} 
     2{# 
     3INPUT: 
     4- worksheet - an instance of Worksheet 
     5- notebook - an instance of Notebook which contains worksheet 
     6- show_debug - a boolean stating whether to show debug information 
     7- do_print - a boolean stating whether the file is for print mode 
     8#} 
     9 
     10{% block body_classes %}worksheet-online{% if not (worksheet.is_published() or notebook.user_is_guest(username) or worksheet.is_doc_worksheet()) %} active-worksheet-page{% endif %}{% endblock %} 
     11{% block page_id %}user-worksheet-index{% endblock %} 
     12 
     13{% block worksheet_main %} 
     14{% set toggle=true %} 
     15<div class="worksheet" id="worksheet"> 
     16    {{ worksheet.html() }} 
     17    {% if do_print %} 
     18    <script> 
     19        jsMath.ProcessBeforeShowing(); 
     20    </script> 
     21    {% else %} 
     22    <script type="text/javascript"> 
     23        cell_id_list = {{ worksheet.cell_id_list() }}; 
     24        state_number = {{ worksheet.state_number() }}; 
     25        {% if not published %} 
     26        $(document).ready(function () { 
     27            if (worksheet_name === "Untitled") { 
     28                rename_worksheet(); 
     29            } 
     30         }); 
     31        {% endif %} 
     32    </script> 
     33    {% endif %} 
     34</div> 
     35 
     36{% if show_debug %} 
     37<div class='debug_window'> 
     38    <div class='debug_output'><pre id='debug_output'></pre></div> 
     39    <textarea rows=5 id='debug_input' class='debug_input'  
     40              onKeyPress='return debug_keypress(event);'  
     41              onFocus='debug_focus();' onBlur='debug_blur();'> 
     42    </textarea> 
     43</div> 
     44{% endif %} 
     45 
     46<script type="text/javascript"> 
     47{% if worksheet.is_only_viewer(username) %} 
     48    worksheet_locked = true; 
     49{% else %} 
     50    worksheet_locked = false; 
     51{% endif %} 
     52</script> 
     53 
     54{% if worksheet.computing() %} 
     55<!-- Set the update checking back in motion. --> 
     56<script type="text/javascript"> 
     57    active_cell_list = {{ worksheet.queue_id_list() }}; 
     58    for (var i = 0; i < active_cell_list.length; i += 1) { 
     59        cell_set_running(active_cell_list[i]); 
     60    } 
     61    start_update_check(); 
     62</script> 
     63{% endif %} 
     64{% endblock %} 
  • deleted file sagenb/data/sage/html/notebook/worksheet_page_template.html

    diff --git a/sagenb/data/sage/html/notebook/worksheet_page_template.html b/sagenb/data/sage/html/notebook/worksheet_page_template.html
    deleted file mode 100644
    + -  
    1 {% extends "html/base.html" %} 
    2 {# 
    3 INPUT: 
    4 - worksheet - an instance of Worksheet 
    5 - worksheet_filename - a string containing a worksheet's filename 
    6 - username  - a string containing a username 
    7 - title - a string 
    8 - select    - a string containing the control that is selected 
    9 - backwards - a boolean 
    10 - JSMATH - a boolean stating whether to include jsMath 
    11 - JEDITABLE_TINYMCE - a boolean stating whether to include jEditable and TinyMCE 
    12 #} 
    13  
    14 {% if not select %} 
    15     {% set select = none %} 
    16 {% endif %} 
    17  
    18 {% if not backwards %} 
    19     {% set backwards = false %} 
    20 {% endif %} 
    21      
    22 {% include "html/notebook/head.tmpl" %} 
    23 {% include "html/notebook/worksheet_topbar.tmpl" %} 
    24  
    25 {% block title %} 
    26 {{ common_title(worksheet_filename, worksheet) }} 
    27 {% endblock %} 
    28      
    29 {% block css %}main{% endblock %} 
    30  
    31 {% block javascript %} 
    32 {{ common_javascript(worksheet, worksheet_filename, username, JSMATH, JEDITABLE_TINYMCE) }} 
    33 {% endblock %} 
    34  
    35 {% block body %} 
    36 {% set toggle=true %} 
    37 {% include "html/top_bar.html" %} 
    38 {{ worksheet_topbar(worksheet, select, username, backwards) }} 
    39 <hr class="usercontrol" /> 
    40 {% block before_sharebar %}{% endblock %} 
    41 <span class="sharebar">{% block sharebar_title %}{% endblock %}</span> 
    42 <br /><br /><br /> 
    43 {% block after_sharebar %}{% endblock %} 
    44 {% endblock %} 
    45  
  • sagenb/data/sage/html/notebook/worksheet_revision_list.html

    diff --git a/sagenb/data/sage/html/notebook/worksheet_revision_list.html b/sagenb/data/sage/html/notebook/worksheet_revision_list.html
    a b  
    1 {% extends "html/notebook/worksheet_page_template.html" %} 
    2 {# 
    3 INPUT: 
    4 - data - a list of pairs of the form ('how long ago', key) 
    5 - worksheet - an instance of Worksheet 
    6 - worksheet_filename - a string containing a worksheet's filename 
    7 - username - a string containing a username 
    8 - JSMATH - a boolean stating whether to include jsMath 
    9 - JEDITABLE_TINYMCE - a boolean stating whether to include jEditable and TinyMCE 
    10 #} 
     1{% extends "html/notebook/base_aux.html" %} 
    112 
    123{% block page_id %}revision-list-page{% endblock %} 
    134 
    Revision History 
    2617        </tr> 
    2718    </thead> 
    2819    <tbody> 
    29         {% for desc, key in data|reverse %} 
     20        {% for desc, key in worksheet.snapshot_data()|reverse %} 
    3021        <tr> 
    3122            <td><a href="revisions?rev={{ key }}">Revision {{ loop.revindex0 }}</a></td> 
    3223            <td><span class="revs">{{ desc }}</span></td> 
  • deleted file sagenb/data/sage/html/notebook/worksheet_settings.html

    diff --git a/sagenb/data/sage/html/notebook/worksheet_settings.html b/sagenb/data/sage/html/notebook/worksheet_settings.html
    deleted file mode 100644
    + -  
    1 {% extends "html/notebook/worksheet_page_template.html" %} 
    2 {# 
    3 INPUT: 
    4 - worksheet - an instance of Worksheet 
    5 - worksheet_filename - a string containing a worksheet's filename 
    6 - username - a string containing a username 
    7 - JSMATH - a boolean stating whether to include jsMath 
    8 - JEDITABLE_TINYMCE - a boolean stating whether to include jEditable and TinyMCE 
    9 #} 
    10  
    11 {% block sharebar_title %} 
    12 Worksheet Settings &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<button name="button_save">Save Settings</button>  <input type="submit" value="Cancel" name="button_cancel"/> 
    13 {% endblock %} 
    14  
    15 {% block before_sharebar %} 
    16 <form width=70% method="post" action="input_settings"  enctype="multipart/form-data"> 
    17 {% endblock %} 
    18 {% block after_sharebar %} 
    19 </form> 
    20 {% endblock %} 
    21  
    22  
    23  
  • sagenb/data/sage/html/notebook/worksheet_share.html

    diff --git a/sagenb/data/sage/html/notebook/worksheet_share.html b/sagenb/data/sage/html/notebook/worksheet_share.html
    a b  
    1 {% extends "html/notebook/worksheet_page_template.html" %} 
     1{% extends "html/notebook/base_aux.html" %} 
    22{# 
    33INPUT: 
    44    - worksheet - an instance of Worksheet 
    5     - worksheet_filename - a string containing a worksheet's filename 
    65    - username - a string containing a username 
    76    - other_users - a list of strings containing other users names 
    8     - user_is_admin - a boolean stating whether the user is an admin 
    9     - JSMATH - a boolean stating whether to include jsMath 
    10     - JEDITABLE_TINYMCE - a boolean stating whether to include jEditable and TinyMCE 
    117#} 
    128 
    139{% block sharebar_title %} 
    Share this document 
    1713{% set select = "share" %} 
    1814 
    1915{% block after_sharebar %} 
    20 {% if not (user_is_admin or username == worksheet.owner()) %} 
     16{% if not (notebook.user_is_admin(username) or username == worksheet.owner()) %} 
    2117    Only the owner of a worksheet is allowed to share it. You can do whatever you want if you <a href="copy">make your own copy</a>. 
    2218{% else %} 
    2319<p>This Sage Worksheet is currently shared with the people listed in the box below.</p> 
  • deleted file sagenb/data/sage/html/notebook/worksheet_topbar.tmpl

    diff --git a/sagenb/data/sage/html/notebook/worksheet_topbar.tmpl b/sagenb/data/sage/html/notebook/worksheet_topbar.tmpl
    deleted file mode 100644
    + -  
    1 {# 
    2 INPUT: 
    3 - worksheet - an instance of Worksheet 
    4 - select    - a string containing the control that is selected 
    5 - username  - a string containing a username 
    6 - backwards - a boolean 
    7 #} 
    8 {% macro worksheet_topbar(worksheet, select=None, username='guest', 
    9 backwards=false, warn=false) %} 
    10 <div id="worksheet-bar"> 
    11     <div class="worksheet_title"> 
    12         <a id="worksheet_title" class="worksheet_title" 
    13            onClick="rename_worksheet(); return false;" 
    14            title="Click to rename this worksheet"> 
    15             {{ worksheet.name() }} 
    16         </a> 
    17         <br> {{ worksheet.html_time_last_edited() }} 
    18         {% if worksheet.warn_about_other_person_editing(username) and username != 'guest' and not worksheet.is_doc_worksheet() %} 
    19         &nbsp;&nbsp;<span class="pingdown">(Someone else is viewing this worksheet)</span> 
    20         {% endif %} 
    21     </div> 
    22     <div id="save-discard-buttons"> 
    23         {{ worksheet.html_save_discard_buttons() }} 
    24     </div> 
    25      
    26     <div id="worksheet-menu"> 
    27         {{ worksheet.html_menu() }} 
    28     </div> 
    29     <div id="share-publish-buttons"> 
    30         {{ worksheet.html_share_publish_buttons(select, backwards) }} 
    31     </div> 
    32 </div> 
    33 <div class="hidden" id="slide_controls"> 
    34     <div class="slideshow_control"> 
    35         <a class="slide_arrow" onClick="slide_next()">&gt;</a> 
    36         <a class="slide_arrow" onClick="slide_last()">&gt;&gt;</a> <span class="vbar"></span> 
    37         <a class="cell_mode" onClick="cell_mode()">Exit</a> 
    38     </div> 
    39     <div class="slideshow_progress" id="slideshow_progress" onClick="slide_next()"> 
    40         <div class="slideshow_progress_bar" id="slideshow_progress_bar">&nbsp;</div> 
    41         <div class="slideshow_progress_text" id="slideshow_progress_text">&nbsp;</div> 
    42     </div> 
    43     <div class="slideshow_control"> 
    44         <a class="slide_arrow" onClick="slide_first()">&lt;&lt;</a> 
    45         <a class="slide_arrow" onClick="slide_prev()">&lt;</a> 
    46     </div> 
    47 </div>  
    48 {% endmacro %} 
  • deleted file sagenb/data/sage/html/notebook_settings.html

    diff --git a/sagenb/data/sage/html/notebook_settings.html b/sagenb/data/sage/html/notebook_settings.html
    deleted file mode 100644
    + -  
    1 {% extends "html/base.html" %} 
    2  
    3 {% block title %}Notebook Settings{% endblock %} 
    4 {% block css %}account_settings{% endblock %} 
    5 {% block more_css %} 
    6 <link rel="stylesheet" href="/javascript/jquery/plugins/farbtastic/farbtastic.css" type="text/css" />   
    7 {% endblock %} 
    8  
    9 {% block javascript %} 
    10 <script type="text/javascript" src="/javascript/jquery/plugins/farbtastic/farbtastic.min.js"></script> 
    11 {% endblock %} 
    12  
    13 {% block body %} 
    14 <h1>Notebook Settings</h1> 
    15 <div class="section"><a href="/users">Manage Users</a> | <a href="/settings">My Settings</a> | <a href="/">My Worksheets</a> | <a href="/logout">Sign Out</a></div> 
    16  
    17 <form method="get" action="/notebooksettings"> 
    18   <input type="hidden" name="form" value="on" /> 
    19   {%- if auto_table %} 
    20   {{ auto_table }} 
    21   {%- endif %} 
    22   <div id="buttons"> 
    23     <input type="submit" value="Save"> 
    24     <input type="button" value="Cancel" style="margin-left:5px" onClick="parent.location='/'"> 
    25   </div> 
    26 </form> 
    27 {% endblock %} 
  • deleted file sagenb/data/sage/html/registration.html

    diff --git a/sagenb/data/sage/html/registration.html b/sagenb/data/sage/html/registration.html
    deleted file mode 100644
    + -  
    1 {% extends "html/base.html" %} 
    2  
    3 {% block title %}Sign up{% endblock %} 
    4  
    5 {% block css %}registration{% endblock %} 
    6  
    7 {% block body %} 
    8 <div id="wrapper"> 
    9   <h1>Sign up for a Sage Notebook account</h1> 
    10   {% if error %} 
    11   <h2 class="error_found">Error{{ error[1:] }}found</h2> 
    12   {% endif %} 
    13   <form method="POST" action="/register"> 
    14     <ol> 
    15       <li><h2>Create a username</h2> 
    16         <p>Your username must start with a letter and be between 3 and 64 
    17           characters long. You may only use letters, numbers, underscores, @, 
    18           and dots.</p> 
    19         <input type="text" name="username" value="{{ username }}" class="entry" tabindex="1" /> 
    20         {% if username_missing %} 
    21         <p><span class="error">Error:</span> No username given</p> 
    22         {% endif %} 
    23         {% if username_taken %} 
    24         <p><span class="error">Error:</span> Username already in use</p> 
    25         {% endif %} 
    26         {% if username_invalid %} 
    27         <p><span class="error">Error:</span> Bad username</p> 
    28         {% endif %} 
    29       </li> 
    30       <li><h2>Create a good password</h2> 
    31         <p>Your password must be between 4 and 32 characters long. Your password can not contain your username nor spaces.</p> 
    32         <input type="password" name="password" class="entry" tabindex="2" /> 
    33         {% if password_missing %} 
    34         <p><span class="error">Error:</span> No password given</p> 
    35         {% endif %} 
    36         {% if password_invalid %} 
    37         <p><span class="error">Error:</span> Bad password</p> 
    38         {% endif %} 
    39       </li> 
    40       <li><h2>Re-type your password</h2> 
    41         <input type="password" name="retype_password" class="entry" tabindex="3" /> 
    42         {% if passwords_dont_match or retype_password_missing %} 
    43         <p><span class="error">Error:</span> Passwords didn't match</p> 
    44         {% endif %} 
    45       </li> 
    46       {% if email or email_missing or email_invaild %} 
    47       <li><h2>Enter your email address</h2> 
    48         <p>Your email address is required for account confirmation and recovery. You will be emailed a confirmation link right after you successfully sign up.</p> 
    49         <input type="text" name="email" value="{{ email_address }}" class="entry" tabindex="4" /> 
    50         {% if email_missing %} 
    51         <p><span class="error">Error:</span> No email address given</p> 
    52         {% endif %} 
    53         {% if email_invalid %} 
    54         <p><span class="error">Error:</span> Invalid email address</p> 
    55         {% endif %} 
    56       </li> 
    57       {% endif %} 
    58       {% if challenge %} 
    59       <li><h2>Answer a challenge</h2> 
    60         {{ challenge_html }} 
    61         {% if challenge_missing %} 
    62         <p><span class="error">Error:</span> No challenge response given</p> 
    63         {% endif %} 
    64         {% if challenge_invalid %} 
    65         <p><span class="error">Error:</span> Invalid challenge response</p> 
    66         {% endif %} 
    67       </li> 
    68       {% endif %} 
    69     </ol> 
    70     <button type="submit" tabindex="100" id="create-account-button">Create account</button> 
    71     <a href="/"><button tabindex="101">Cancel</button></a> 
    72   </form> 
    73 </div>  
    74 {% endblock %} 
  • new file sagenb/data/sage/html/settings/account_settings.html

    diff --git a/sagenb/data/sage/html/settings/account_settings.html b/sagenb/data/sage/html/settings/account_settings.html
    new file mode 100644
    - +  
     1{% extends "html/settings/base.html" %} 
     2 
     3{% block title %}Account Settings{% endblock %} 
     4{% block page_id %}account-settings-page{% endblock %} 
     5 
     6{% block settings_main %} 
     7<form method="post" action="/settings"> 
     8     
     9    <div class="section"> 
     10        <h2>Change Auto-Save Interval</h2> 
     11        <div> 
     12            Minutes: 
     13            <select name="autosave"> 
     14                {% for i, selected in autosave_intervals %} 
     15                <option{{ selected }}>{{ i }}</option> 
     16                {% endfor %} 
     17            </select> 
     18        </div> 
     19    </div> 
     20    <div class="section"> 
     21        <h2>Change Password</h2> 
     22        <div id="passwd"> 
     23            <div> 
     24                <label for="old-pass">Old password</label> 
     25                <input type="password" name="old-pass" /> 
     26            </div> 
     27            <div> 
     28                <label for="new-pass">New password</label> 
     29                <input type="password" name="new-pass" /> 
     30            </div> 
     31            <div> 
     32                <label for="retype-pass">Retype new password</label> 
     33                <input type="password" name="retype-pass" /> 
     34            </div> 
     35        </div> 
     36    </div> 
     37 
     38    {% if true %} 
     39    <div class="section"> 
     40        <h2>Change E-mail Address</h2> 
     41         
     42        <div> 
     43            <div> 
     44                <label>Current e-mail</label> 
     45                {{ email_address }} {{ email_confirmed }} 
     46            </div> 
     47            <div> 
     48                <label for="new-email">New e-mail</label> 
     49                <input type="text" name="new-email" class="c1" /> 
     50            </div> 
     51        </div> 
     52    </div> 
     53    {% endif %} 
     54    <div id="buttons"> 
     55        <button type="submit">Save</button> 
     56        <a href="/"><button>Cancel</button></a> 
     57    </div> 
     58</form> 
     59{% endblock %} 
  • new file sagenb/data/sage/html/settings/admin_add_user.html

    diff --git a/sagenb/data/sage/html/settings/admin_add_user.html b/sagenb/data/sage/html/settings/admin_add_user.html
    new file mode 100644
    - +  
     1{% extends "html/settings/base.html" %} 
     2{% block title %}Add New User{% endblock %} 
     3{% block page_id %}add-user-page{% endblock %} 
     4 
     5{% block main %} 
     6<h1>Add New User</h1> 
     7{% if error %} 
     8<h2 class="error_found">Username Error</h2> 
     9{% endif %} 
     10<form method="POST" action="/adduser"> 
     11  <ol> 
     12    <li><h2>Pick a username</h2> 
     13      <p>The username must start with a letter and be between 4 and 32 characters long. It can only consist of letters, numbers, underscores, and one dot (.).</p> 
     14      <input type="text" name="username" value="{{ username_input if username_input else '' }}" /> 
     15      {% if username_error %} 
     16      {% if username_error == 'invalid' %} 
     17      <p><span class="error">Error:</span> Invalid username</p> 
     18      {% else %} 
     19      <p><span class="error">Error:</span> Username taken</p> 
     20      {% endif %} 
     21      {% endif %} 
     22    </li> 
     23  </ol> 
     24  <div id="buttons"> 
     25    <button type="submit">Create Account</buttoN> 
     26    <a href="/users"><button>Cancel</button></a> 
     27  </div> 
     28</form> 
     29</div> 
     30{% endblock %} 
     31 
  • new file sagenb/data/sage/html/settings/base.html

    diff --git a/sagenb/data/sage/html/settings/base.html b/sagenb/data/sage/html/settings/base.html
    new file mode 100644
    - +  
     1{% extends "html/base_authenticated.html" %} 
     2 
     3{% block body_classes %}settings-page{% endblock %} 
     4 
     5{% block main %} 
     6<h1>{{ render_title() }}</h1> 
     7{% block settings_nav %} 
     8<ul id="settings-nav" class="user-controls"> 
     9    {% if admin %} 
     10    <li><a href="/users">Manage Users</a></li> 
     11    <li><a href="/notebooksettings">Notebook Settings</a></li> 
     12    {% endif %} 
     13    <li><a href="/settings">Account Settings</a></li> 
     14</ul> 
     15{% endblock %} 
     16{% block settings_main %} 
     17{% endblock %} 
     18{% endblock %} 
  • new file sagenb/data/sage/html/settings/notebook_settings.html

    diff --git a/sagenb/data/sage/html/settings/notebook_settings.html b/sagenb/data/sage/html/settings/notebook_settings.html
    new file mode 100644
    - +  
     1{% extends "html/settings/base.html" %} 
     2{% block title %}Notebook Settings{% endblock %} 
     3 
     4{% block more_css %} 
     5<link rel="stylesheet" href="/javascript/jquery/plugins/farbtastic/farbtastic.css" type="text/css" />   
     6{% endblock %} 
     7 
     8{% block javascript %} 
     9<script type="text/javascript" src="/javascript/sage/ws_list.js"></script> 
     10<script type="text/javascript" src="/javascript/jquery/plugins/farbtastic/farbtastic.min.js"></script> 
     11{% endblock %} 
     12 
     13{% block page_id %}notebook-settings-page{% endblock %} 
     14 
     15{% block settings_main %} 
     16<form method="get" action="/notebooksettings"> 
     17  <input type="hidden" name="form" value="on" /> 
     18  {%- if auto_table %} 
     19  {{ auto_table }} 
     20  {%- endif %} 
     21  <div id="buttons"> 
     22    <input type="submit" value="Save" /> 
     23    <input type="button" value="Cancel" style="margin-left:5px" onClick="parent.location='/'" /> 
     24  </div> 
     25</form> 
     26{% endblock %} 
  • new file sagenb/data/sage/html/settings/user_management.html

    diff --git a/sagenb/data/sage/html/settings/user_management.html b/sagenb/data/sage/html/settings/user_management.html
    new file mode 100644
    - +  
     1{% extends "html/settings/base.html" %} 
     2 
     3{% block title %}Users{% endblock %} 
     4{% block page_id %}user-management-page{% endblock %} 
     5 
     6{% block settings_main %} 
     7    <h1>User Management</h1> 
     8    <a href="/adduser" class="boldusercontrol">Add User</a> 
     9    {% if reset %} 
     10    <p>The password for the user {{ reset[0] }} has been reset to <strong>{{ reset[1] }}</strong></p> 
     11    {% endif %} 
     12    <table> 
     13      <tr><th>Users</th><th>Password</th><th>Suspension</th></tr> 
     14      {% for user in users %} 
     15      {% if user != 'admin' %} 
     16      <tr><td><a href="/home/{{ user }}/">{{ user }}</a></td><td><a href="/users/?reset={{ user }}">Reset</a></td><td><a href="/users/?suspension={{ user }}">{% if user.is_suspended() %}Unsuspend{% else %}Suspend{% endif %}</td></tr> 
     17      {% endif %} 
     18      {% endfor %} 
     19    </table> 
     20{% endblock %} 
  • sagenb/data/sage/html/source_code.html

    diff --git a/sagenb/data/sage/html/source_code.html b/sagenb/data/sage/html/source_code.html
    a b  
    1 {% extends "html/base.html" %} 
     1{% extends "html/base_authenticated.html" %} 
    22 
    33{% block title %}{{ src_filename }} - Source Code{% endblock %} 
    44 
    55{% block css %}main{% endblock %} 
    66 
     7{% block more_css %}<link type="text/css" ref="stylesheet" href="/javascript/highlight/prettify.css" />{% endblock %} 
     8 
     9{% block page_id %}source-code-page{% endblock %} 
     10 
    711{% block body %} 
    8 {% include "html/top_bar.html" %} 
    9 <h1 align=center>Sage Source Browser</h1> 
    10 <h2 align=center><tt>{{ src_filename }}  <a href="..">(browse directory)</a></tt></h2> 
    11 <br><hr><br> 
    12 <font size=+1><pre id="code">{{ src }}</pre></font> 
    13 <br><hr><br> 
     12<div> 
     13<h1>Sage Source Browser</h1> 
     14<h2 class="filename" >{{ src_filename }}  <a href="..">(browse directory)</a></h2> 
     15</div> 
     16 
     17<code id="code">{{ src }}</code> 
     18 
    1419<script src="/javascript/highlight/prettify.js" type="text/javascript"></script> 
    1520<script type="text/javascript"> 
    16 function get_element(id) { 
    17   if(document.getElementById) 
    18     return document.getElementById(id); 
    19   if(document.all) 
    20     return document.all[id]; 
    21   if(document.layers) 
    22     return document.layers[id]; 
    23 } 
    24  
    25 var x = get_element("code"); 
    26 x.innerHTML = prettyPrintOne(x.innerHTML); 
     21    code = $('code'); 
     22    code.html(prettyPrintOne(code.html())) 
    2723</script> 
    2824{% endblock %} 
  • deleted file sagenb/data/sage/html/template_error.html

    diff --git a/sagenb/data/sage/html/template_error.html b/sagenb/data/sage/html/template_error.html
    deleted file mode 100644
    + -  
    1 {% extends "html/base.html" %} 
    2  
    3 {% block title %}Error{% endblock %} 
    4  
    5 {% block body %} 
    6 <span style="color:red;font-weight:bold;">Internal Server Error:</span> The template <em>{{ template }}</em> wasn't found. 
    7 {% endblock %} 
  • sagenb/data/sage/html/test_report.html

    diff --git a/sagenb/data/sage/html/test_report.html b/sagenb/data/sage/html/test_report.html
    a b  
    8686          <td class="value">{{ sage_version }}</td> 
    8787        </tr> 
    8888        {% endif %} 
     89        {%- if environment %} 
     90        <tr> 
     91          <td class="label">Environment</td> 
     92          <td class="value">{{ environment }}</td> 
     93        </tr> 
     94        {% endif %} 
    8995        <tr> 
    9096          <td class="label">Start</td> 
    9197          <td class="value">{{ start_time }}</td> 
  • deleted file sagenb/data/sage/html/top_bar.html

    diff --git a/sagenb/data/sage/html/top_bar.html b/sagenb/data/sage/html/top_bar.html
    deleted file mode 100644
    + -  
    1 <div id="top-bar"> 
    2   {% include "html/banner.html" %} 
    3   <div id="controls"> 
    4     <ul> 
    5       <li class="username">{{ username }}</li> 
    6       {% if username == 'guest' %} 
    7       <li><a title="Please log in to the Sage notebook" class="usercontrol" href="/">Log in</a></li> 
    8       {% else %} 
    9       {# TODO: Hack-ish. Remove on template cleanup. #} 
    10       {% if toggle %} 
    11       <li><a title="Toggle the top bar" class="usercontrol" onClick="$('#worksheet-bar').toggle()">Toggle</a></li> 
    12       {% endif %} 
    13       <li><a title="Back to your personal worksheet list" class="usercontrol" href="/home/{{ username }}">Home</a></li> 
    14       {% if pub %} 
    15       <li><span class="usercontrol">Published</span></li> 
    16       {% else %} 
    17       <li><a title="Browse the published worksheets" class="usercontrol" href="/pub">Published</a></li> 
    18       <li><a title="View a log of recent computations" class="usercontrol" href="#" onClick="history_window()">Log</a></li> 
    19       {% endif %} 
    20       <li><a title="Change account settings including password" class="usercontrol" href="/settings">Settings</a></li> 
    21       <li><a title="Documentation" class="usercontrol" href="#" onClick="help()">Help</a></li> 
    22       <li><a title="Report a problem or submit a bug to improve Sage" class="usercontrol" href="#" onClick="bugreport()">Report a Problem</a></li> 
    23       <li><a title="Log out of the Sage notebook" class="usercontrol" href="/logout">Sign out</a></li> 
    24       {% endif %} 
    25     </ul> 
    26   </div> 
    27 </div> 
  • sagenb/data/sage/html/upload.html

    diff --git a/sagenb/data/sage/html/upload.html b/sagenb/data/sage/html/upload.html
    a b  
    1 {% extends "html/base.html" %} 
     1{% extends "html/base_authenticated.html" %} 
    22 
    33{% block title %}Upload File{% endblock %} 
    44 
    5 {% block css %}main{% endblock %} 
    6  
    75{% block page_id %}upload-worksheet-page{% endblock %} 
    86 
    9 {% block body %} 
     7{% block main %} 
    108 
    11 {% include "html/top_bar.html" %} 
    129<div> 
    1310    <h2>Upload worksheet (an sws or txt file) to the Sage Notebook</h2> 
    1411    <form method="POST" action="upload_worksheet" 
    1512          name="upload" enctype="multipart/form-data"> 
    1613        <div> 
    1714            <label for="file">Browse your computer to select a worksheet file to upload:</label> 
    18             <input size="50" type="file" name="file"></input> 
     15            <input size="50" type="file" name="file" /> 
    1916        </div> 
    2017        <div> 
    2118            <label for="url">Or enter the url of a worksheet file on the web:</label> 
    22             <input size="50" type="text" name="url"></input> 
     19            <input size="50" type="text" name="url" /> 
    2320        </div> 
    2421        <div> 
    2522            <label for="name">What do you want to call it? (if different than the original name)</label> 
    26             <input size="50" type="text" name="name"></input> 
     23            <input size="50" type="text" name="name" /> 
    2724        </div> 
    2825        <button type="submit">Upload Worksheet</button> 
    2926    </form> 
  • deleted file sagenb/data/sage/html/user_management.html

    diff --git a/sagenb/data/sage/html/user_management.html b/sagenb/data/sage/html/user_management.html
    deleted file mode 100644
    + -  
    1 <html> 
    2   <head> 
    3     <title>Users | {{ sitename }}</title> 
    4     <style> 
    5       body { 
    6       font:1em Arial, Sans-serif; 
    7       } 
    8  
    9       table { 
    10       border-collapse:collapse 
    11       } 
    12  
    13       th, td { 
    14       border:1px solid #696969; 
    15       padding:5px 
    16       } 
    17  
    18       th { 
    19       background:#CCC 
    20       } 
    21  
    22       a:link, a:visited { 
    23       color:blue 
    24       } 
    25     </style> 
    26   </head> 
    27   <body> 
    28     <h1>User Management</h1> 
    29     <a href="/adduser">Add User</a> | <a href="/notebooksettings">Notebook Settings</a> | <a href="/settings">My Settings</a> | <a href="/">My Worksheets</a> | <a href="/logout">Sign Out</a> {% if number_of_users %} <br/><br/>{{ number_of_users }} users {% endif %}<br/><br/> 
    30     {% if reset %} 
    31     <p>The password for the user {{ reset[0] }} has been reset to <strong>{{ reset[1] }}</strong></p> 
    32     {% endif %} 
    33     <table> 
    34       <tr><th>Users</th><th>Password</th><th>Suspension</th></tr> 
    35       {% for user in users %} 
    36       {% if user != 'admin' %} 
    37       <tr><td><a href="/home/{{ user }}/">{{ user }}</a></td><td><a href="/users/?reset={{ user }}">Reset</a></td><td><a href="/users/?suspension={{ user }}">{% if user.is_suspended() %}Unsuspend{% else %}Suspend{% endif %}</td></tr> 
    38       {% endif %} 
    39       {% endfor %} 
    40     </table> 
    41   </body> 
    42 </html> 
  • deleted file sagenb/data/sage/html/worksheet/menu.html

    diff --git a/sagenb/data/sage/html/worksheet/menu.html b/sagenb/data/sage/html/worksheet/menu.html
    deleted file mode 100644
    + -  
    1 {# 
    2 INPUT 
    3 - name - string with worksheet name 
    4 - filename_ - string with worksheet filename 
    5 - data - list of data to put in the Data menu 
    6 - systems_enumerated - enumerated list of systems 
    7 - system_names - list of system names 
    8 - current_system_index - the currently selected system_index 
    9 - pretty_print - a boolean stating whether to typeset as default 
    10 - doc_worksheet - a boolean stating whether the worksheet is the doc worksheet 
    11 #} 
    12 <select class="worksheet"  onchange="go_option(this);" id="file-menu"> 
    13     <option title="Select a file related function" value=""  selected>File...</option> 
    14     <option title="Load a new worksheet stored in a file" value="upload_worksheet_button();">Load worksheet from a file...</option> 
    15     <option title="Create a new worksheet" value="new_worksheet();">New worksheet</option> 
    16     <option title="Save this worksheet to an sws file" value="download_worksheet();">Save worksheet to a file...</option> 
    17     <option title="Print this worksheet" value="print_worksheet();">Print</option> 
    18     <option title="Rename this worksheet" value="rename_worksheet();">Rename worksheet</option> 
    19     <option title="Copy this worksheet" value="copy_worksheet();">Copy worksheet</option> 
    20     <option title="Move this worksheet to the trash" value="delete_worksheet('{{ filename_ }}');">Delete worksheet</option> 
    21 </select> 
    22  
    23 <select class="worksheet"  onchange="go_option(this);"  id="action-menu"> 
    24     <option title="Select a worksheet function" value="" selected>Action...</option> 
    25     <option title="Interrupt currently running calculations, if possible" value="interrupt();">Interrupt</option> 
    26     <option title="Restart the worksheet process" value="restart_sage();">Restart worksheet</option> 
    27     <option title="Quit the worksheet process" value="save_worksheet_and_close();">Save and quit worksheet</option>  
    28     <option value="">---------------------------</option> 
    29     <option title="Evaluate all input cells in the worksheet" value="evaluate_all();">Evaluate All</option> 
    30     <option title="Hide all output" value="hide_all();">Hide All Output</option> 
    31     <option title="Show all output" value="show_all();">Show All Output</option> 
    32     <option title="Delete all output" value="delete_all_output();">Delete All Output</option> 
    33     <option value="">---------------------------</option> 
    34     <option title="Switch to single-cell mode" value="slide_mode();">One Cell Mode</option> 
    35     <option title="Switch to multi-cell mode" value="cell_mode();">Multi Cell Mode</option>  
    36 </select> 
    37 <select class="worksheet" onchange="handle_data_menu(this);" id="data-menu"> 
    38     <option title="Select an attached file" value="" selected>Data...</option> 
    39     <option title="Upload or create a data file in a wide range of formats" value="__upload_data_file__">Upload or create file...</option> 
    40     <option value="">--------------------</option> 
    41     {% for name in data %} 
    42     <option value="datafile?name={{ name }}">{{ name }}</option> 
    43     {% endfor %} 
    44 </select> 
    45  
    46 {% if not doc_worksheet %} 
    47 <select onchange="go_system_select(this, {{ current_system_index }});" class="worksheet" id="systems-menu"> 
    48     {% for system_index, system_name in systems_enumerated %} 
    49         <option title="Evaluate all input cells using {{ system_names[system_index] }}" 
    50             {{ "selected" if current_system_index == system_index else "" }} value="{{ system_names[system_index] }}"> 
    51             {{ system_name }} 
    52         </option> 
    53     {% endfor %} 
    54 </select>     
    55 <input type="checkbox" title="Enable/disable pretty_printing" 
    56        onchange="pretty_print_check(this.checked);" 
    57        class="worksheet" value="pretty_print" {{ "checked" if pretty_print else "" }} />&nbsp;Typeset 
    58 {% endif %} 
  • deleted file sagenb/data/sage/html/worksheet/published_worksheet.html

    diff --git a/sagenb/data/sage/html/worksheet/published_worksheet.html b/sagenb/data/sage/html/worksheet/published_worksheet.html
    deleted file mode 100644
    + -  
    1 {# 
    2 INPUT: 
    3 - cell_id_list - a list of cell id's 
    4 - cells_html - string of cells HTML 
    5 #} 
    6 {% set published = true %} 
    7 {% set do_print = true %} 
    8  
    9 {% include "html/worksheet/worksheet_body.html" %} 
    10  
    11  
    12 <script language=javascript>jsMath.ProcessBeforeShowing();</script> 
  • new file sagenb/data/sage/html/worksheet/ratings_info.html

    diff --git a/sagenb/data/sage/html/worksheet/ratings_info.html b/sagenb/data/sage/html/worksheet/ratings_info.html
    new file mode 100644
    - +  
     1{% extends "html/base.html" %} 
     2 
     3{% block title %}Ratings for {{ worksheet.name() }}{% endblock %} 
     4 
     5{% block body %} 
     6<h2 align=center>Ratings for {{ worksheet.name() }}</h2> 
     7<h3 align=center><a href='/home/{{ worksheet.filename() }}'>Go to the worksheet.</a> 
     8<table width=70%%align=center border=1 cellpadding=10 cellspacing=0> 
     9    <tr bgcolor="#7799bb"><td width=30em>User</td><td width=10em align=center>Rating</td><td width=10em align=center width=60em>Comment</td></tr> 
     10    {% for rating in worksheet.ratings()|sort %} 
     11    <tr> 
     12        <td>{{ rating[0] }}{# User #}</td> 
     13        <td>{{ rating[1] }}{# Rating #}</td> 
     14        <td>{{'' if rating|length < 3 else rating[2]}}{# Comment #}</td> 
     15    </tr> 
     16    {% endfor %} 
     17</table> 
     18{% endblock %} 
  • deleted file sagenb/data/sage/html/worksheet/save_discard_buttons.html

    diff --git a/sagenb/data/sage/html/worksheet/save_discard_buttons.html b/sagenb/data/sage/html/worksheet/save_discard_buttons.html
    deleted file mode 100644
    + -  
    1 {# 
    2 INPUT: 
    3 doc_worksheet - boolean stating whether this worksheet is the doc worksheet 
    4 #} 
    5 {% if not doc_worksheet %} 
    6 <button name="button_save" title="Save changes" onClick="save_worksheet();">Save</button><button title="Save changes and close window" onClick="save_worksheet_and_close();" name="button_save">Save & quit</button><button title="Discard changes to this worksheet" onClick="worksheet_discard();">Discard & quit</button> 
    7 {% endif %} 
  • deleted file sagenb/data/sage/html/worksheet/share_publish_buttons.html

    diff --git a/sagenb/data/sage/html/worksheet/share_publish_buttons.html b/sagenb/data/sage/html/worksheet/share_publish_buttons.html
    deleted file mode 100644
    + -  
    1  
    2 {# 
    3 INPUT: 
    4 - worksheet - Worksheet instance 
    5 - select - a boolean 
    6 - backwards - a boolean 
    7 #} 
    8 {% if not worksheet.is_doc_worksheet() %} 
    9 {% macro cls(x) %} 
    10 {{ "control-select" if x == select else "control" }} 
    11 {% endmacro %} 
    12 {% macro backwards_text() %} 
    13 {{ "../" if backwards else "" }} 
    14 {% endmacro %} 
    15 <a title="Print this worksheet" class="print-link" onClick="print_worksheet()"><img border=0 src="/images/icon_print.gif" alt="Print">Print</a> 
    16 <a class="{{ cls('use') }}" title="Interactively use this worksheet" onClick="edit_worksheet();">Worksheet</a>         
    17 <a class="{{ cls('edit') }}" title="Edit text version of this worksheet" href="{{ backwards_text() }}edit">Edit</a> 
    18 <a class="{{ cls('text') }}" title="View plain text version of this worksheet" href="{{ backwards_text() }}text">Text</a> 
    19 <a class="{{ cls('undo') }}" title="View changes to this worksheet over time" href="{{ backwards_text() }}revisions">Undo</a> 
    20 <a class="{{ cls('share') }}" title="Let others edit this worksheet" href="{{ backwards_text() }}share">Share</a> 
    21 <a class="{{ cls('publish') }}" title="Make this worksheet publicly viewable" href="{{ backwards_text() }}publish">Publish</a> 
    22 {% endif %} 
  • deleted file sagenb/data/sage/html/worksheet/title.html

    diff --git a/sagenb/data/sage/html/worksheet/title.html b/sagenb/data/sage/html/worksheet/title.html
    deleted file mode 100644
    + -  
    1 {# 
    2 MARKED FOR DELETION. 
    3 - worksheet - Worksheet instance 
    4 - name - escaped name of the worksheet 
    5 - username - string of username 
    6 #} 
    7 <div class="worksheet_title"> 
    8      <a id="worksheet_title" class="worksheet_title" onClick="rename_worksheet(); return false;" title="Click to rename this worksheet">{{ name }}</a> 
    9      <br> {{ worksheet.html_time_last_edited() }} 
    10      {% if warn and username != 'guest' and not doc_worksheet%} 
    11      &nbsp;&nbsp;<span class="pingdown">(Someone else is viewing this worksheet)</span> 
    12      {% endif %} 
    13  </div> 
    14  No newline at end of file 
  • deleted file sagenb/data/sage/html/worksheet/worksheet.html

    diff --git a/sagenb/data/sage/html/worksheet/worksheet.html b/sagenb/data/sage/html/worksheet/worksheet.html
    deleted file mode 100644
    + -  
    1 {# 
    2 INPUT: 
    3 - do_print - a boolean 
    4 - cell_id_list - a list of cell id's 
    5 - confirm_before_leave - a boolean stating whether to popup a js confirm 
    6   dialog before leaving 
    7 - cells_html - string of cells HTML 
    8 - published - a boolean stating whether the worksheet is published 
    9 - state_number - worksheet.state_number() 
    10 #} 
    11 {% include "html/worksheet/worksheet_body.html" %} 
    12  
    13 {% if do_print %} 
    14 <script language="javascript">jsMath.ProcessBeforeShowing();</script> 
    15 {% else %} 
    16 <script type="text/javascript"> 
    17 $(document).ready(function() {                               
    18    cell_id_list={{ cell_id_list }}; 
    19    state_number={{ state_number }}; 
    20    {% if not published %}if(worksheet_name == "Untitled") rename_worksheet();{% endif %} 
    21 });                      
    22 </script> 
    23 {% endif %} 
    24  
    25 {% if not do_print and confirm_before_leave %} 
    26 <script type="text/javascript"> 
    27 $(document).ready(function() {                                   
    28             window.onbeforeunload = confirmBrowseAway; 
    29             function confirmBrowseAway() 
    30             { 
    31             return "Unsubmitted cells will be lost."; 
    32             } 
    33 });                               
    34 </script> 
    35 {% endif %} 
    36  
  • deleted file sagenb/data/sage/html/worksheet/worksheet_body.html

    diff --git a/sagenb/data/sage/html/worksheet/worksheet_body.html b/sagenb/data/sage/html/worksheet/worksheet_body.html
    deleted file mode 100644
    + -  
    1 {# 
    2 INPUT: 
    3 - cells_html - string of cells HTML 
    4 - published - a boolean stating whether the worksheet is published 
    5 #} 
    6  
    7 <div class="cell_input_active" id="cell_resizer"></div> 
    8 {% if not published %} 
    9 <div class="worksheet_cell_list" id="worksheet_cell_list"> 
    10 {% endif %} 
    11  
    12 {{ cells_html }} 
    13  
    14 {% if not do_print and not published %} 
    15 </div> 
    16 <div class="insert_new_cell" id="insert_last_cell"></div> 
    17 <script type="text/javascript"> 
    18         $("#insert_last_cell").plainclick(function(e) {insert_new_cell_after(cell_id_list[cell_id_list.length-1]);}); 
    19         $("#insert_last_cell").shiftclick(function(e) {insert_new_text_cell_after(cell_id_list[cell_id_list.length-1]);}); 
    20 </script> 
    21 <div class="worksheet_bottom_padding"></div> 
    22 {% endif %} 
    23  
    24  
  • sagenb/data/sage/html/worksheet_listing.html

    diff --git a/sagenb/data/sage/html/worksheet_listing.html b/sagenb/data/sage/html/worksheet_listing.html
    a b  
    1 {% extends "html/base.html" %} 
     1{% extends "html/base_authenticated.html" %} 
    22{# 
    33INPUT: 
    4 - pub - a boolean stating whether to show in public mode. 
    5 - typ - a string stating what kind of worksheets this listing shows 
     4- pub -- a boolean stating whether to show in public mode. 
     5- typ -- a string stating what kind of worksheets this listing shows 
     6- worksheets -- list of Worksheet objects 
    67#} 
    78{% if pub %} 
    89{% set worksheet_heading='Published Worksheets' %} 
    INPUT: 
    1415{% set worksheet_heading='Archived Worksheets' %} 
    1516{% endif %}   
    1617 
    17  
    1818{% block title %} 
    1919{{ worksheet_heading }} 
    2020{% endblock %} 
    2121 
    22 {% block css %}main{% endblock %} 
     22{% block page_id %}worksheet-listing-page{% endblock %} 
    2323 
    2424{% block javascript %} 
    2525{% if not pub %} 
    INPUT: 
    2727<script type="text/javascript" src="/javascript/jqueryui/js/jquery-ui-1.7.2.custom.min.js"></script> 
    2828<script type="text/javascript" src="/javascript/jquery/plugins/form/jquery.form.min.js"></script> 
    2929<script type="text/javascript" src="/javascript/jquery/plugins/jquery.bgiframe.min.js"></script> 
    30 {% endif %} 
    31 {% if not pub %} 
    3230<script type="text/javascript"> 
    33                     var worksheet_filenames = {{ worksheet_filenames }};  
     31    var worksheet_filenames = {{ worksheet_filenames }};  
    3432</script> 
    3533<script type="text/javascript" src="/javascript/sage/main.js"></script> 
    3634<script type="text/javascript" src="/javascript/gears/gears_init.js"></script>  
    INPUT: 
    4038{% endif %} 
    4139{% endblock %} 
    4240 
    43 {% block onload %} onLoad="checkForGearsInstalled();"{% endblock %} 
    4441 
    45 {% block body %} 
     42{% block main %} 
     43<div id="user-main-controls" class="user-controls"> 
     44    {% if pub is not defined or not pub %} 
     45    <a href="/new_worksheet" target="_blank">New Worksheet</a> 
     46    <a href="/upload">Upload</a> 
     47    {% if not accounts %} 
     48    <a href="/download_worksheets.zip">Download All Active</a> 
     49    {% endif %} 
     50    {% endif %} 
    4651 
    47 {% include "html/list_top.html" %} 
    48  
    49 <div id="worksheet-list-controls"> 
     52    <div id="search-area"> 
     53        <form action="." method="GET"> 
     54            <input type="hidden" value="{{ typ if not pub else 'pub' }}" name="typ" /> 
     55            <input id="search-worksheets" size="20" value="{{ search if search else "" }}" name="search" /> 
     56            <button class="add_new_worksheet_menu" id="search-worksheets-button" type="submit">Search Worksheets</button> 
     57        </form> 
     58    </div> 
     59</div>        
     60<div id="worksheet-list-controls" class="controls"> 
    5061    {% if not pub %} 
    5162    <div class="action-buttons"> 
    5263        {% if typ == 'archive' %} 
    INPUT: 
    8192 
    8293<table cellspacing="0" cellpadding="0" id="worksheet-list"> 
    8394    <thead> 
    84       <tr> 
    85         {% if not pub %} 
    86         <td class="checkbox"> 
    87             <input id="controlbox" onClick="set_worksheet_list_checks();" class="entry" type="checkbox" /> 
    88         </td> 
    89         {% else %} 
    90         <td><a class="listcontrol" href=".?sort=rating">Rating</a></td> 
    91         {% endif %} 
     95        <tr> 
     96            {% if not pub %} 
     97            <td class="checkbox"> 
     98                <input id="controlbox" onClick="set_worksheet_list_checks();" class="entry" type="checkbox" /> 
     99            </td> 
     100            {% else %} 
     101            <td><a class="listcontrol" href=".?sort=rating">Rating</a></td> 
     102            {% endif %} 
    92103 
    93         <td> 
    94             <a class="listcontrol" href=".?typ={{ typ }}&sort=name{{ '' if sort != 'name' or reverse else '&reverse=True' }}"> 
    95                 {{ worksheet_heading }} 
    96             </a> 
    97         </td> 
    98          
    99         <td> 
    100             <a class="listcontrol" href=".?typ={{ typ }}&sort=owner{{ '' if sort != 'owner' or reverse else '&reverse=True' }}"> 
    101                 Owner {{ '' if pub else ' / Collaborators' }} 
    102             </a> 
    103         </td> 
     104            <td> 
     105                <a class="listcontrol" href=".?typ={{ typ }}&sort=name{{ '' if sort != 'name' or reverse else '&reverse=True' }}"> 
     106                    {{ worksheet_heading }} 
     107                </a> 
     108            </td> 
     109             
     110            <td> 
     111                <a class="listcontrol" href=".?typ={{ typ }}&sort=owner{{ '' if sort != 'owner' or reverse else '&reverse=True' }}"> 
     112                    Owner {{ '' if pub else ' / Collaborators' }} 
     113                </a> 
     114            </td> 
    104115 
    105         <td> 
    106             <a class="listcontrol" href=".?typ={{ typ }}&{{ '' if sort != 'last_edited' or reverse else 'reverse=True' }}"> 
    107                 Last Edited 
    108             </a> 
    109         </td> 
    110       </tr> 
     116            <td> 
     117                <a class="listcontrol" href=".?typ={{ typ }}{{ '' if sort != 'last_edited' or reverse else 'reverse&=True' }}"> 
     118                    Last Edited 
     119                </a> 
     120            </td> 
     121        </tr> 
    111122    </thead> 
    112123    <tbody> 
    113124        {% if not worksheets %} 
    114125        {% if pub %} 
    115126        <tr> 
    116             <td colspan="5" style="padding:20px;text-align:center"> 
     127            <td colspan="5"> 
    117128                There are no published worksheets. 
    118129            </td> 
    119130        </tr> 
    120131        {% elif typ == 'active' %} 
    121132        <tr> 
    122             <td colspan="5" style="padding:20px;text-align:center"> 
     133            <td colspan="5"> 
    123134                Welcome to Sage! You can <a href="/new_worksheet">create a new worksheet</a>, 
    124135                view <a href="/pub/">published worksheets</a>, or read the 
    125136                <a href="/help" target="_new">documentation</a>. 
    INPUT: 
    145156                {% else %} 
    146157                 
    147158                <input type="checkbox" unchecked id="{{ name|css_escape }}" /> 
    148                     {# I'm removing this select since it is a massive performance killer and these  
    149                     serve no real purpose at all.  Plus google docs got rid of the analogous menu. 
    150                     <select onchange="go_option(this);" class="worksheet_edit"> 
    151                         <option value="" title="File options" selected>File</option> 
    152                         <option value="list_rename_worksheet('{{ name }}','{{ worksheet.name() }}');" title="Change the name of this worksheet."> 
    153                             Rename... 
    154                         </option>             
    155                         <option value="list_edit_worksheet('{{ name }}');" title="Open this worksheet and edit it">Edit</option> 
    156                         <option value="list_copy_worksheet('{{ name }}');" title="Copy this worksheet">Copy Worksheet</option> 
    157                         <option value="list_share_worksheet('{{ name }}');" title="Share this worksheet with others">Collaborate</option> 
    158                         <option value="list_publish_worksheet('{{ name }}');" title="Publish this worksheet on the internet">Publish</option> 
    159                         <option value="list_revisions_of_worksheet('{{ name }}');" title="See all revisions of this worksheet">Revisions</option> 
    160                     </select> 
    161                     #}       
    162                     {% endif %} 
    163                 </td> 
     159                {# I'm removing this select since it is a massive performance killer and these  
     160                serve no real purpose at all.  Plus google docs got rid of the analogous menu. 
     161                <select onchange="go_option(this);" class="worksheet_edit"> 
     162                    <option value="" title="File options" selected>File</option> 
     163                    <option value="list_rename_worksheet('{{ name }}','{{ worksheet.name() }}');" title="Change the name of this worksheet."> 
     164                        Rename... 
     165                    </option>             
     166                    <option value="list_edit_worksheet('{{ name }}');" title="Open this worksheet and edit it">Edit</option> 
     167                    <option value="list_copy_worksheet('{{ name }}');" title="Copy this worksheet">Copy Worksheet</option> 
     168                    <option value="list_share_worksheet('{{ name }}');" title="Share this worksheet with others">Collaborate</option> 
     169                    <option value="list_publish_worksheet('{{ name }}');" title="Publish this worksheet on the internet">Publish</option> 
     170                    <option value="list_revisions_of_worksheet('{{ name }}');" title="See all revisions of this worksheet">Revisions</option> 
     171                </select> 
     172                #}       
     173                {% endif %} 
     174            </td> 
    164175 
    165                 <td class="worksheet_link"> 
    166                     <a title="{{ worksheet.name() | escape }}" id="name-{{ name|css_escape }}" class="worksheetname" href="/home/{{ name }}"> 
    167                         {% if worksheet.compute_process_has_been_started() %}(running) {% endif %} 
    168                         {{ worksheet.truncated_name(50) | escape}} 
    169                     </a> 
    170                      
    171                     {% if not pub and worksheet.is_published() %}(Published){% endif %} 
    172                 </td> 
    173                 <td class="owner_collab"> 
     176            <td class="worksheet_link"> 
     177                <a title="{{ worksheet.name() | escape }}" id="name-{{ name|css_escape }}" class="worksheetname" href="/home/{{ name }}"> 
     178                    {% if worksheet.compute_process_has_been_started() %}(running) {% endif %} 
     179                    {{ worksheet.truncated_name(50) | escape}} 
     180                </a> 
     181                 
     182                {% if not pub and worksheet.is_published() %}(Published){% endif %} 
     183            </td> 
     184            <td class="owner_collab"> 
    174185 
    175                     {% if not pub %} 
    176                     {{ worksheet.owner() }} 
    177                     {% else %} 
    178                     {{worksheet.worksheet_that_was_published().owner()}} 
    179                     {% endif %} 
    180                      
    181                     {% if not pub and typ != 'trash' %} 
     186                {% if not pub %} 
     187                {{ worksheet.owner() }} 
     188                {% else %} 
     189                {{worksheet.worksheet_that_was_published().owner()}} 
     190                {% endif %} 
     191                 
     192                {% if not pub and typ != 'trash' %} 
    182193 
    183                     {% set shared = False %} 
     194                {% set shared = False %} 
    184195 
    185                     {% if worksheet.collaborator_names() %} 
    186                     / {{ worksheet.collaborator_names(5) }} 
    187                     {% set shared = True %} 
    188                     {% endif %} 
     196                {% if worksheet.collaborator_names() %} 
     197                / {{ worksheet.collaborator_names(5) }} 
     198                {% set shared = True %} 
     199                {% endif %} 
    189200 
    190                     {% if worksheet.viewer_names() %} 
    191                     / {{ worksheet.viewer_names(5) }} 
    192                     {% set shared = True %} 
    193                     {% endif %} 
     201                {% if worksheet.viewer_names() %} 
     202                / {{ worksheet.viewer_names(5) }} 
     203                {% set shared = True %} 
     204                {% endif %} 
    194205 
    195                     {% if (worksheet.owner() != username) or username == 'admin' %} 
    196                     {% set shared = False %} 
    197                     {% endif %} 
    198                      
    199                     {% if shared %} 
    200                     <a class="share" href="/home/{{ worksheet.filename() }}/share">Add or Delete</a> 
    201                     {% else %} 
    202                     <a class="share" href="/home/{{ worksheet.filename() }}/share">Share now</a> 
    203                     {% endif %} 
     206                {% if (worksheet.owner() != username) or username == 'admin' %} 
     207                {% set shared = False %} 
     208                {% endif %} 
     209                 
     210                {% if shared %} 
     211                <a class="share" href="/home/{{ worksheet.filename() }}/share">Add or Delete</a> 
     212                {% else %} 
     213                <a class="share" href="/home/{{ worksheet.filename() }}/share">Share now</a> 
     214                {% endif %} 
    204215 
    205                     {% if worksheet.has_published_version() %} 
    206                     <a href="/home/{{ worksheet.published_version().filename() }}"> 
    207                         (published) 
    208                     </a> 
    209                     {% endif %} 
    210                      
    211                     {% endif %} 
    212                 </td> 
    213                 <td> 
    214                     {{ worksheet.html_time_since_last_edited() }} 
    215                 </td> 
    216             </tr> 
    217             {% endfor %} 
    218             {% endif %} 
    219         </tbody> 
    220     </table> 
    221     {% endblock %} 
     216                {% if worksheet.has_published_version() %} 
     217                <a href="/home/{{ worksheet.published_version().filename() }}"> 
     218                    (published) 
     219                </a> 
     220                {% endif %} 
     221                 
     222                {% endif %} 
     223            </td> 
     224            <td> 
     225                {{ worksheet.html_time_since_last_edited() }} 
     226            </td> 
     227        </tr> 
     228        {% endfor %} 
     229        {% endif %} 
     230    </tbody> 
     231</table> 
     232{% endblock %} 
  • sagenb/data/sage/html/yes_no.html

    diff --git a/sagenb/data/sage/html/yes_no.html b/sagenb/data/sage/html/yes_no.html
    a b  
    44 
    55{% block body %} 
    66<table align=center border=1 cellpadding=20 bgcolor="efefef"> 
    7 <tr><td> 
    8 {{ message }} 
    9 <br><br> 
    10 <font size=+3><a href="yes">Yes</a> or <a href="no">No</a>?</font> 
    11 </td></tr> 
     7  <tr><td> 
     8      {{ message }} 
     9      <br><br> 
     10      <font size=+3><a href="yes">Yes</a> or <a href="no">No</a>?</font> 
     11  </td></tr> 
    1212</table> 
    1313{% endblock %} 
  • new file sagenb/data/sage/js/master.js

    diff --git a/sagenb/data/sage/js/master.js b/sagenb/data/sage/js/master.js
    new file mode 100644
    - +  
     1$(window).load(function () { 
     2    body = $('body'), body_id = body.attr('id'); 
     3    if (body_id === 'worksheet-listing-page') { 
     4        checkForGearsInstalled(); 
     5    } 
     6 
     7    if (body.hasClass('worksheet-online')) { 
     8        initialize_the_notebook(); 
     9    } 
     10}); 
  • sagenb/notebook/cell.py

    diff --git a/sagenb/notebook/cell.py b/sagenb/notebook/cell.py
    a b TRACEBACK = 'Traceback (most recent call 
    3939# we don't get several of these combined in one. 
    4040re_cell = re.compile('"cell://.*?"') 
    4141re_cell_2 = re.compile("'cell://.*?'")   # same, but with single quotes 
     42# Matches script blocks 
     43re_script = re.compile(r'<script[^>]*?>.*?</script>', re.DOTALL | re.I) 
    4244 
    4345JEDITABLE_TINYMCE = True 
    4446 
    import errno, hashlib, time 
    4850from sphinx.application import Sphinx 
    4951_SAGE_INTROSPECT = None 
    5052 
     53 
    5154class Cell_generic: 
    5255    def is_interactive_cell(self): 
    5356        """ 
    class Cell_generic: 
    7982        """ 
    8083        raise NotImplementedError 
    8184 
    82     def html_new_cell_before(self): 
    83         """ 
    84         Returns the HTML code for inserting a new cell before self. 
    85  
    86         EXAMPLES:: 
    87  
    88             sage: C = sagenb.notebook.cell.Cell(0, '2+3', '5', None) 
    89             sage: print C.html_new_cell_before() 
    90             <div class="insert_new_cell" id="insert_new_cell_before0">... 
    91         """ 
    92         return """<div class="insert_new_cell" id="insert_new_cell_before%(id)s"> 
    93                  </div> 
    94 <script type="text/javascript"> 
    95 $("#insert_new_cell_before%(id)s").plainclick(function(e) {insert_new_cell_before(%(id)s);}); 
    96 $("#insert_new_cell_before%(id)s").shiftclick(function(e) {insert_new_text_cell_before(%(id)s);}); 
    97 </script>"""%{'id': self.id()} 
    98  
    99     def html_new_cell_after(self): 
    100         """ 
    101         Returns the HTML code for inserting a new cell after self. 
    102  
    103         EXAMPLES:: 
    104  
    105             sage: C = sagenb.notebook.cell.Cell(0, '2+3', '5', None) 
    106             sage: print C.html_new_cell_after() 
    107             <div class="insert_new_cell" id="insert_new_cell_after0">... 
    108         """ 
    109         return """<div class="insert_new_cell" id="insert_new_cell_after%(id)s"> 
    110                  </div> 
    111 <script type="text/javascript"> 
    112 $("#insert_new_cell_after%(id)s").plainclick(function(e) {insert_new_cell_after(%(id)s);}); 
    113 $("#insert_new_cell_after%(id)s").shiftclick(function(e) {insert_new_text_cell_after(%(id)s);}); 
    114 </script>"""%{'id': self.id()} 
    115  
    116  
    11785class TextCell(Cell_generic): 
    11886    def __init__(self, id, text, worksheet): 
    11987        """ 
    class TextCell(Cell_generic): 
    202170        """ 
    203171        return self.__worksheet 
    204172 
    205     def html(self, ncols=0, do_print=False, do_math_parse=True, editing=False): 
     173    def html(self, wrap=None, div_wrap=True, do_print=False, do_math_parse=True, editing=False): 
    206174        """ 
    207175        Returns an HTML version of self as a string. 
    208176 
    209177        INPUT: 
    210178 
     179        - ``wrap`` -- number of columns to wrap at (not used) 
     180 
     181        - ``div_wrap`` -- whether to wrap in a div (not used) 
     182         
    211183        - ``do_math_parse`` - bool (default: True) 
    212184          If True, call math_parse (defined in cell.py) 
    213185          on the html. 
    214186 
     187        - ``do_print`` - bool (default: False) 
     188          If True, display for printing 
     189 
     190        - ``editing`` - bool (default: False) 
     191          If True, # TODO: figure out what this does 
     192 
    215193        EXAMPLES:: 
    216194 
    217195            sage: C = sagenb.notebook.cell.TextCell(0, '2+3', None) 
    218196            sage: C.html() 
    219             '...<div class="text_cell" id="cell_text_0">2+3...' 
     197            u'...text_cell...2+3...' 
    220198            sage: C.set_input_text("$2+3$") 
    221199            sage: C.html(do_math_parse=True) 
    222             '...<div class="text_cell" id="cell_text_0"><span class="math">2+3</span>...' 
     200            u'...text_cell...class="math"...2+3...' 
    223201        """ 
    224         s = '<span id="cell_outer_%s">'%self.__id 
    225  
    226         if not do_print: 
    227             s += self.html_new_cell_before() 
    228  
    229         s += """<div class="text_cell" id="cell_text_%s">%s</div>"""%( 
    230             self.__id, 
    231             self.html_inner(ncols=ncols, do_print=do_print, do_math_parse=do_math_parse, editing=editing)) 
    232  
    233         if JEDITABLE_TINYMCE and hasattr(self.worksheet(),'is_published') and not self.worksheet().is_published() and not self.worksheet().docbrowser() and not do_print: 
    234  
    235             try: 
    236                 z = ((self.__text).decode('utf-8')).encode('ascii', 'xmlcharrefreplace') 
    237             except Exception, msg: 
    238                 print msg 
    239                 # better to get the worksheet at all than to get a blank screen and nothing. 
    240                 z = self.__text 
    241  
    242             s += """<script>$("#cell_text_%s").unbind('dblclick').editable(function(value,settings) { 
    243 evaluate_text_cell_input(%s,value,settings); 
    244 return(value); 
    245 }, { 
    246       tooltip   : "", 
    247       placeholder : "", 
    248 //      type   : 'textarea', 
    249       type   : 'mce', 
    250       onblur : 'ignore', 
    251       select : false, 
    252       submit : 'Save changes', 
    253       cancel : 'Cancel changes', 
    254       event  : "dblclick", 
    255       style  : "inherit", 
    256       data   : %r 
    257   }); 
    258 </script>"""%(self.__id,self.__id, z) 
    259  
    260  
    261         if editing and not do_print: 
    262             s += """<script>$("#cell_text_%s").trigger('dblclick');</script>"""%self.__id 
    263  
    264         s += '</span>' 
    265         return s 
    266  
    267     def html_inner(self,ncols=0, do_print=False, do_math_parse=True, editing=False): 
    268         """ 
    269         Returns an HTML version of the content of self as a string. 
    270  
    271         INPUT: 
    272  
    273         - ``do_math_parse`` - bool (default: True) 
    274           If True, call math_parse (defined in cell.py) 
    275           on the html. 
    276  
    277         EXAMPLES:: 
    278  
    279             sage: C = sagenb.notebook.cell.TextCell(0, '2+3', None) 
    280             sage: C.html_inner() 
    281             '2+3...' 
    282             sage: C.set_input_text("$2+3$") 
    283             sage: C.html_inner(do_math_parse=True) 
    284             '<span class="math">2+3</span>...' 
    285         """ 
    286         t = self.__text 
    287         if do_math_parse: 
    288             # Do dollar sign math parsing 
    289             try: 
    290                 t = math_parse(t) 
    291             except Exception, msg: 
    292                 # Since there is no guarantee the user's input/output 
    293                 # is in any way valid, and we don't want to stop the 
    294                 # server process (which is doing this work). 
    295                 pass 
    296         s = """%s"""%t 
    297         return s 
     202        from template import template 
     203        return template(os.path.join('html', 'notebook', 'text_cell.html'), 
     204                        cell = self, wrap = wrap, do_print = do_print, 
     205                        do_math_parse = do_math_parse, editing = editing, 
     206                        div_wrap=div_wrap) 
    298207 
    299208 
    300209    def plain_text(self, prompts=False): 
    class Cell(Cell_generic): 
    13811290            sage: W = nb.create_new_worksheet('Test', 'sage') 
    13821291            sage: C = sagenb.notebook.cell.Cell(0, '2+3', '5', W) 
    13831292            sage: C.process_cell_urls('"cell://foobar"') 
    1384             '/home/sage/0/cells/0/foobar?0"' 
     1293            '/home/sage/0/cells/0/foobar?0' 
    13851294        """ 
    1386         end = '?%d"'%self.version() 
     1295        end = '?%d' % self.version() 
    13871296        begin = self.url_to_self() 
    13881297        for s in re_cell.findall(urls) + re_cell_2.findall(urls): 
    13891298            urls = urls.replace(s,begin + s[7:-1] + end) 
    class Cell(Cell_generic): 
    14931402        # Everything not wrapped in <html> ... </html> should be 
    14941403        # escaped and word wrapped. 
    14951404        t = '' 
     1405 
    14961406        while len(s) > 0: 
    14971407            i = s.find('<html>') 
    14981408            if i == -1: 
    class Cell(Cell_generic): 
    15101420        # be evaluated twice.  They are only evaluated in the wrapped 
    15111421        # version of the output. 
    15121422        if ncols == 0: 
    1513             while True: 
    1514                 i = t.lower().find('<script>') 
    1515                 if i == -1: break 
    1516                 j = t[i:].lower().find('</script>') 
    1517                 if j == -1: break 
    1518                 t = t[:i] + t[i+j+len('</script>'):] 
    1519  
     1423            t = re_script.sub('', t) 
    15201424        return t 
    15211425 
    15221426 
    class Cell(Cell_generic): 
    18021706        TODO: Remove this hack (:meth:`doc_html`) 
    18031707        """ 
    18041708        self.evaluate() 
    1805         if wrap is None: 
    1806             wrap = self.notebook().conf()['word_wrap_cols'] 
    1807         evaluated = self.evaluated() 
    1808         if evaluated: 
    1809             cls = 'cell_evaluated' 
    1810         else: 
    1811             cls = 'cell_not_evaluated' 
    1812  
    1813         html_in  = self.html_in(do_print=do_print) 
    1814         introspect = "<div id='introspect_div_%s' class='introspection'></div>"%self.id() 
    1815         #html_out = self.html_out(wrap, do_print=do_print) 
    1816         html_out = self.html() 
    1817         s = html_out 
    1818         if div_wrap: 
    1819             s = '\n\n<div id="cell_outer_%s" class="cell_visible"><div id="cell_%s" class="%s">'%(self.id(), self.id(), cls) + s + '</div></div>' 
    1820         return s 
     1709        return self.html(wrap, div_wrap, do_print) 
    18211710 
    18221711    def html(self, wrap=None, div_wrap=True, do_print=False): 
    18231712        r""" 
    class Cell(Cell_generic): 
    18251714 
    18261715        INPUT: 
    18271716 
    1828         - ``wrap`` - None or an integer stating column position to wrap lines. Defaults to 
    1829           configuration if not given. 
     1717        - ``wrap`` - None or an integer stating column position to 
     1718          wrap lines. Defaults to configuration if not given. 
    18301719 
    18311720        - ``div_wrap`` - a boolean stating whether to wrap ``div``. 
    18321721 
    class Cell(Cell_generic): 
    18351724 
    18361725        EXAMPLES:: 
    18371726 
    1838             sage: nb = sagenb.notebook.notebook.Notebook(tmp_dir()+'.sagenb') 
     1727            sage: nb = sagenb.notebook.notebook.load_notebook(tmp_dir()+'.sagenb') 
    18391728            sage: nb.add_user('sage','sage','sage@sagemath.org',force=True) 
    18401729            sage: W = nb.create_new_worksheet('Test', 'sage') 
    18411730            sage: C = sagenb.notebook.cell.Cell(0, '2+3', '5', W) 
    18421731            sage: C.html() 
    1843             '\n\n<div id="cell_outer_0" cl...</div>' 
     1732            u'...cell_outer_0...2+3...5...' 
    18441733        """ 
    1845         if do_print: 
    1846             wrap = 68 
    1847             div_wrap = 68 
    1848         key = (wrap,div_wrap,do_print) 
     1734        from template import template 
    18491735 
    18501736        if wrap is None: 
    18511737            wrap = self.notebook().conf()['word_wrap_cols'] 
    1852         evaluated = self.evaluated() 
    1853         if evaluated or do_print: 
    1854             cls = 'cell_evaluated' 
    1855         else: 
    1856             cls = 'cell_not_evaluated' 
    1857  
    1858         html_in  = self.html_in(do_print=do_print) 
    1859         introspect = "<div id='introspect_div_%s' class='introspection'></div>"%self.id() 
    1860         html_out = self.html_out(wrap, do_print=do_print) 
    1861  
    1862         if 'hideall' in self.percent_directives(): 
    1863             s = html_out 
    1864         else: 
    1865             s = html_in + introspect + html_out 
    1866  
    1867         if div_wrap: 
    1868             s = '\n\n<div id="cell_outer_%s" class="cell_visible"><div id="cell_%s" class="%s">'%(self.id(), self.id(), cls) + s + '</div></div>' 
    1869  
    1870         #self._html_cache[key] = s 
    1871         return s 
    1872  
    1873     def html_in(self, do_print=False, ncols=80): 
    1874         """ 
    1875         Returns the HTML code for the input of this cell. 
    1876  
    1877         EXAMPLES:: 
    1878  
    1879             sage: C = sagenb.notebook.cell.Cell(0, '2+3', '5', None) 
    1880             sage: print C.html_in() 
    1881             <div class="insert_new_cell" id="insert_new_cell_before0"...</a> 
    1882         """ 
    1883         s = '' 
    1884         id = self.__id 
    1885         t = self.__in.rstrip() 
    1886  
    1887         cls = "cell_input_hide" if 'hide' in self.percent_directives() else "cell_input" 
    1888  
    1889         if not do_print: 
    1890             s += self.html_new_cell_before() 
    1891  
    1892         r = max(1, number_of_rows(t.strip(), ncols)) 
    1893  
    1894         if do_print: 
    1895             if 'hide' in self.percent_directives(): 
    1896                 return '' 
    1897  
    1898             tt = escape(t).replace('\n','<br>').replace('  ',' &nbsp;') + '&nbsp;' 
    1899             s += '<div class="cell_input_print">%s</div>'%tt 
    1900         else: 
    1901             s += """ 
    1902                <textarea class="%s" rows=%s cols=%s 
    1903                   id         = 'cell_input_%s' 
    1904                   onKeyPress = 'return input_keypress(%s,event);' 
    1905                   onKeyDown  = 'return input_keydown(%s,event);' 
    1906                   onKeyUp    = 'return input_keyup(%s, event);' 
    1907                   onBlur     = 'cell_blur(%s); return true;' 
    1908                   onFocus    = 'cell_focused(this,%s); return true;' 
    1909                >%s</textarea> 
    1910             """%(cls, r, ncols, id, id, id, id, id, id, t) 
    1911  
    1912         if not do_print: 
    1913            s+= '<a href="javascript:evaluate_cell(%s,0)" class="eval_button" id="eval_button%s" alt="Click here or press shift-return to evaluate">evaluate</a>'%(id,id) 
    1914  
    1915         t = escape(t)+" " 
    1916  
    1917         return s 
    1918  
     1738             
     1739        return template(os.path.join('html', 'notebook', 'cell.html'), 
     1740                        cell=self, wrap=wrap, 
     1741                        div_wrap=div_wrap, do_print=do_print) 
    19191742 
    19201743    def url_to_self(self): 
    19211744        """ 
    class Cell(Cell_generic): 
    20871910            files  = ('&nbsp'*3).join(files) 
    20881911        return images + files 
    20891912 
    2090     def html_out(self, ncols=0, do_print=False): 
    2091         r""" 
    2092         Returns the HTML for self's output. 
    2093  
    2094         INPUT: 
    2095  
    2096         - ``do_print`` -- a boolean stating whether to output HTML 
    2097           for print 
    2098  
    2099         - ``ncols`` -- the number of columns 
    2100  
    2101         EXAMPLES:: 
    2102  
    2103             sage: nb = sagenb.notebook.notebook.Notebook(tmp_dir()+'.sagenb') 
    2104             sage: nb.add_user('sage','sage','sage@sagemath.org',force=True) 
    2105             sage: W = nb.create_new_worksheet('Test', 'sage') 
    2106             sage: C = sagenb.notebook.cell.Cell(0, '2+3', '5', W) 
    2107             sage: C.html_out() 
    2108             '\n...<div class="cell_output_div">\n...</div>' 
    2109         """ 
    2110         if do_print and self.cell_output_type() == 'hidden': 
    2111             return '<pre>\n</pre>' 
    2112  
    2113         out_nowrap = self.output_text(0, html=True) 
    2114  
    2115         out_html = self.output_html() 
    2116         if self.introspect(): 
    2117             out_wrap = out_nowrap 
    2118         else: 
    2119             out_wrap = self.output_text(ncols, html=True) 
    2120  
    2121         typ = self.cell_output_type() 
    2122  
    2123         if self.computing(): 
    2124             cls = "cell_div_output_running" 
    2125         else: 
    2126             cls = 'cell_div_output_' + typ 
    2127  
    2128         top = '<div class="%s" id="cell_div_output_%s">'%( 
    2129                          cls, self.__id) 
    2130  
    2131         if do_print: 
    2132             prnt = "print_" 
    2133         else: 
    2134             prnt = "" 
    2135  
    2136         out_wrap   = '<div class="cell_output_%s%s" id="cell_output_%s">%s</div>'%( 
    2137             prnt, typ, self.__id, out_wrap) 
    2138         if not do_print: 
    2139             out_nowrap = '<div class="cell_output_%snowrap_%s" id="cell_output_nowrap_%s">%s</div>'%( 
    2140                 prnt, typ, self.__id, out_nowrap) 
    2141         out_html   = '<div class="cell_output_html_%s" id="cell_output_html_%s">%s </div>'%( 
    2142             typ, self.__id, out_html) 
    2143  
    2144         if do_print: 
    2145             out = out_wrap + out_html 
    2146         else: 
    2147             out = out_wrap + out_nowrap + out_html 
    2148  
    2149         s = top + out + '</div>' 
    2150  
    2151         r = '' 
    2152         r += '&nbsp;'*(7-len(r)) 
    2153         tbl = """ 
    2154                <div class="cell_output_div"> 
    2155                <table class="cell_output_box"><tr> 
    2156                <td class="cell_number" id="cell_number_%s" %s> 
    2157                  %s 
    2158                </td> 
    2159                <td class="output_cell">%s</td></tr></table></div>"""%( 
    2160                    self.__id, 
    2161                    '' if do_print else 'onClick="cycle_cell_output_type(%s);"'%self.__id, 
    2162                    r, s) 
    2163  
    2164         return tbl 
    2165  
    2166  
    2167  
    21681913######## 
    21691914 
    21701915def format_exception(s0, ncols): 
  • sagenb/notebook/challenge.py

    diff --git a/sagenb/notebook/challenge.py b/sagenb/notebook/challenge.py
    a b class reCAPTCHAChallenge(AbstractChallen 
    443443            sage: nb = n.Notebook(tmp) 
    444444            sage: chal = reCAPTCHAChallenge(nb.conf(), remote_ip = 'localhost') 
    445445            sage: chal.html() 
    446             '<script type="text/javascript">...</script>' 
     446            u'...recaptcha...' 
    447447            sage: chal.html('incorrect-captcha-sol') 
    448             '<script...incorrect-captcha-sol...</script>' 
     448            u'...incorrect-captcha-sol...' 
    449449 
    450450        """ 
    451451        error_param = '' 
  • sagenb/notebook/js.py

    diff --git a/sagenb/notebook/js.py b/sagenb/notebook/js.py
    a b which is inserted to the head of the not 
    1414interesting Javascript code is contained under 
    1515``data/sage/js/notebook_lib.js``. 
    1616""" 
    17  
    18 import os 
    19 from sagenb.misc.misc import SAGE_URL  
    20 from compress.JavaScriptCompressor import JavaScriptCompressor 
    21 import keyboards 
    22  
    2317########################################################################### 
    2418#       Copyright (C) 2006 William Stein <wstein@gmail.com> 
    2519#                     2006 Tom Boothby <boothby@u.washington.edu> 
    2620# 
    2721#   Released under the *modified* BSD license. 
    28 #     Tom wrote in email to me at wstein@gmail.com on March 2, 2008: "You have my permission 
    29 #     to change the license on anything I've contributed to the notebook, to whatever suits you." 
     22#     Tom wrote in email to me at wstein@gmail.com on March 2, 2008: 
     23#     "You have my permission to change the license on anything I've 
     24#     contributed to the notebook, to whatever suits you." 
    3025# 
    3126########################################################################### 
    3227 
     28import os 
     29import keyboards 
     30from template import template 
     31from sagenb.misc.misc import SAGE_URL 
     32from compress.JavaScriptCompressor import JavaScriptCompressor 
     33 
     34# Debug mode?  If sagenb lives under SAGE_ROOT/, we minify and cache 
     35# the Notebook JS library. 
     36try: 
     37    from sage.misc.misc import SAGE_ROOT 
     38    from pkg_resources import Requirement, working_set 
     39    sagenb_path = working_set.find(Requirement.parse('sagenb')).location 
     40    debug_mode = not SAGE_ROOT in os.path.realpath(sagenb_path) 
     41except AttributeError, ImportError: 
     42    debug_mode = False 
     43 
    3344 
    3445_cache_javascript = None 
    3546def javascript(): 
    def javascript(): 
    6071    if _cache_javascript is not None: 
    6172        return _cache_javascript 
    6273 
    63     from template import template 
    6474    s = template(os.path.join('js', 'notebook_lib.js'), 
    6575                 SAGE_URL=SAGE_URL, 
    6676                 KEY_CODES=keyhandler.all_tests()) 
    def javascript(): 
    7181    # Evil" clause in the license.  Does that prevent us from 
    7282    # distributing it (i.e., it adds an extra condition to the 
    7383    # software)?  See http://www.crockford.com/javascript/jsmin.py.txt 
    74     s = JavaScriptCompressor().getPacked(s) 
     84    global debug_mode 
     85    if debug_mode: 
     86        return s 
     87 
     88    s = JavaScriptCompressor().getPacked(s.encode('utf-8')) 
    7589    _cache_javascript = s 
     90 
    7691    return s 
    7792 
    7893 
    79  
    8094class JSKeyHandler: 
    8195    """ 
    8296    This class is used to make javascript functions to check  
  • sagenb/notebook/notebook.py

    diff --git a/sagenb/notebook/notebook.py b/sagenb/notebook/notebook.py
    a b import keyboards # keyboard layouts 
    4343import server_conf  # server configuration 
    4444import user_conf    # user configuration 
    4545import user         # users 
    46 from   template import template 
     46from   template import template, prettify_time_ago 
    4747 
    4848 
    4949try: 
    class Notebook(object): 
    11781178 
    11791179 
    11801180    ########################################################## 
    1181     # Importing and exporting worksheets to a plain text format 
    1182     ########################################################## 
    1183  
    1184     def plain_text_worksheet_html(self, filename, prompts=True): 
    1185         """ 
    1186         Return HTML containing the plain text version of a worksheet. 
    1187  
    1188         INPUT: 
    1189  
    1190         - ``filename`` - a string; filename of a worksheet 
    1191  
    1192         - ``prompts`` - a bool (default: True); whether to format the 
    1193           text for inclusion in docstrings 
    1194  
    1195         OUTPUT: 
    1196  
    1197         - a string - the worksheet's HTML representation 
    1198         """ 
    1199         worksheet = self.get_worksheet_with_filename(filename) 
    1200         text = escape(worksheet.plain_text(prompts = prompts)) 
    1201         return template(os.path.join("html", "notebook", "plain_text_worksheet.html"), 
    1202                         worksheet_name = worksheet.name(), 
    1203                         worksheet_plain_text = text) 
    1204  
    1205     ########################################################## 
    12061181    # Server configuration 
    12071182    ########################################################## 
    12081183    def conf(self): 
    class Notebook(object): 
    12471222    ########################################################## 
    12481223    # Worksheet HTML generation 
    12491224    ########################################################## 
    1250     def worksheet_html(self, filename, do_print=False): 
    1251         r""" 
    1252         Return the HTML for a given worksheet. 
    1253  
    1254         INPUT: 
    1255  
    1256         - ``filename`` - a string; the worksheet's filename 
    1257  
    1258         - ``do_print`` - a bool (default: False); whether this is a 
    1259           printed worksheet 
    1260  
    1261         OUTPUT: 
    1262  
    1263         - a string - the worksheet rendered as HTML 
    1264  
    1265         EXAMPLES:: 
    1266  
    1267             sage: nb = sagenb.notebook.notebook.load_notebook(tmp_dir()+'.sagenb') 
    1268             sage: W = nb.create_new_worksheet('Test', 'admin') 
    1269             sage: nb.worksheet_html(W.filename()) 
    1270             '...<!D...Test...cell_id_list=[1]...</body>...</html>' 
    1271         """ 
    1272         worksheet = self.get_worksheet_with_filename(filename) 
    1273         return template(os.path.join("html", "notebook", "worksheet.html"), 
    1274                         worksheet_name = worksheet.name(), 
    1275                  worksheet_html = worksheet.html(include_title=False, do_print=do_print), 
    1276                         do_print = do_print) 
    1277  
    1278  
    1279  
    12801225    def worksheet_list_for_public(self, username, sort='last_edited', reverse=False, search=None): 
    12811226        W = [x for x in self.__worksheets.itervalues() if x.is_published() and not x.is_trashed(user)] 
    12821227 
    class Notebook(object): 
    13241269            '\n\n{{{id=1|\n\n///\n}}}' 
    13251270            sage: W.save_snapshot('admin') 
    13261271            sage: nb.html_worksheet_revision_list('admin', W) 
    1327             '...Revision...Last Edited...seconds...ago...' 
     1272            u'...Revision...Last Edited...ago...' 
    13281273        """ 
    13291274        data = worksheet.snapshot_data()  # pairs ('how long ago', key) 
    13301275 
    13311276        return template(os.path.join("html", "notebook", "worksheet_revision_list.html"), 
    13321277                        data = data, worksheet = worksheet, 
    13331278                        worksheet_filename = worksheet.filename(), 
    1334                         username = username, JSMATH = JSMATH, 
    1335                         JEDITABLE_TINYMCE = JEDITABLE_TINYMCE) 
     1279                        username = username) 
    13361280 
    13371281 
    13381282    def html_specific_revision(self, username, ws, rev): 
    class Notebook(object): 
    13521296        - a string - the revision rendered as HTML 
    13531297        """ 
    13541298        t = time.time() - float(rev[:-4]) 
    1355         time_ago = worksheet.convert_seconds_to_meaningful_time_span(t) 
     1299        time_ago = prettify_time_ago(t) 
    13561300 
    13571301        filename = ws.get_snapshot_text_filename(rev) 
    13581302        txt = bz2.decompress(open(filename).read()) 
    13591303        W = self.scratch_worksheet() 
    13601304        W.delete_cells_directory() 
    13611305        W.edit_save(txt) 
    1362         body_worksheet_html = W.html_worksheet_body(do_print=True, publish=True) 
    13631306 
    13641307        data = ws.snapshot_data()  # pairs ('how long ago', key) 
    13651308        prev_rev = None 
    class Notebook(object): 
    13731316                break 
    13741317 
    13751318        return template(os.path.join("html", "notebook", "specific_revision.html"), 
    1376                         worksheet = ws, worksheet_filename = ws.filename(), 
     1319                        worksheet = ws, 
    13771320                        username = username, rev = rev, prev_rev = prev_rev, 
    1378                         next_rev = next_rev, time_ago = time_ago, 
    1379                         body_worksheet_html = body_worksheet_html, 
    1380                         JSMATH = JSMATH, JEDITABLE_TINYMCE = JEDITABLE_TINYMCE) 
     1321                        next_rev = next_rev, time_ago = time_ago) 
    13811322 
    13821323    def html_share(self, worksheet, username): 
    13831324        r""" 
    class Notebook(object): 
    13981339            sage: nb = sagenb.notebook.notebook.Notebook(tmp_dir()+'.sagenb') 
    13991340            sage: W = nb.create_new_worksheet('Test', 'admin') 
    14001341            sage: nb.html_share(W, 'admin') 
    1401             '...currently shared...add or remove collaborators...' 
     1342            u'...currently shared...add or remove collaborators...' 
    14021343        """ 
    14031344        U = self.users() 
    14041345        other_users = [x for x, u in U.iteritems() if not u.is_guest() and not u.username() in [username, 'pub', '_sage_']] 
    class Notebook(object): 
    14071348        return template(os.path.join("html", "notebook", "worksheet_share.html"), 
    14081349                        worksheet = worksheet, 
    14091350                        worksheet_filename = worksheet.filename(), 
    1410                         username = username, other_users = other_users, 
    1411                         user_is_admin = self.user(username).is_admin(), 
    1412                         JSMATH = JSMATH, JEDITABLE_TINYMCE = JEDITABLE_TINYMCE) 
    1413  
     1351                        username = username, other_users = other_users) 
     1352     
    14141353    def html_download_or_delete_datafile(self, ws, username, filename): 
    14151354        r""" 
    14161355        Return the HTML for the download or delete datafile page. 
    class Notebook(object): 
    14321371            sage: nb = sagenb.notebook.notebook.Notebook(tmp_dir()+'.sagenb') 
    14331372            sage: W = nb.create_new_worksheet('Test', 'admin') 
    14341373            sage: nb.html_download_or_delete_datafile(W, 'admin', 'bar') 
    1435             '...Data file: bar...DATA is a special variable...uploaded...' 
     1374            u'...Data file: bar...DATA is a special variable...uploaded...' 
    14361375        """ 
    1437         path = "/home/%s/data/%s"%(ws.filename(), filename) 
    1438  
    1439         worksheets = self.get_worksheets_with_viewer(username) 
    1440         active_worksheets = [worksheet for worksheet in worksheets if worksheet.is_active(username)] 
    1441         sort_worksheet_list(active_worksheets, 'name', False) 
    1442  
    14431376        ext = os.path.splitext(filename)[1].lower() 
    14441377        file_is_image, file_is_text = False, False 
    14451378        text_file_content = "" 
    class Notebook(object): 
    14531386        return template(os.path.join("html", "notebook", "download_or_delete_datafile.html"), 
    14541387                        worksheet = ws, worksheet_filename = ws.filename(), 
    14551388                        username = username, 
    1456                         active_worksheets = active_worksheets, 
    1457                         filename_ = filename, path = path, 
     1389                        filename_ = filename, 
    14581390                        file_is_image = file_is_image, 
    14591391                        file_is_text = file_is_text, 
    1460                         text_file_content = text_file_content, 
    1461                         JSMATH = JSMATH, JEDITABLE_TINYMCE = JEDITABLE_TINYMCE) 
     1392                        text_file_content = text_file_content) 
    14621393 
    14631394 
    14641395    ########################################################## 
    14651396    # Accessing all worksheets with certain properties. 
    14661397    ########################################################## 
     1398    def active_worksheets_for(self, username): 
     1399        return [ws for ws in self.get_worksheets_with_viewer(username) if ws.is_active(username)] 
     1400     
    14671401    def get_all_worksheets(self): 
    14681402        return [x for x in self.__worksheets.itervalues() if not x.owner() in ['_sage_', 'pub']] 
    14691403 
    class Notebook(object): 
    15431477    ########################################################### 
    15441478    # HTML -- generate most html related to the whole notebook page 
    15451479    ########################################################### 
    1546     def html_debug_window(self): 
    1547         r""" 
    1548         Return the HTML for the debug window. 
    1549  
    1550         OUTPUT: 
    1551  
    1552         - a string - the debug window rendered as HTML 
    1553  
    1554         EXAMPLES:: 
    1555  
    1556             sage: nb = sagenb.notebook.notebook.Notebook(tmp_dir()+'.sagenb') 
    1557             sage: nb.html_debug_window() 
    1558             "\n<div class='debug_window'>...</div>" 
    1559         """ 
    1560         return template(os.path.join("html", "notebook", "debug_window.html")) 
    1561  
    1562  
    15631480    def html_plain_text_window(self, worksheet, username): 
    15641481        r""" 
    15651482        Return HTML for the window that displays a plain text version 
    class Notebook(object): 
    15801497            sage: nb = sagenb.notebook.notebook.Notebook(tmp_dir()+'.sagenb') 
    15811498            sage: W = nb.create_new_worksheet('Test', 'admin') 
    15821499            sage: nb.html_plain_text_window(W, 'admin') 
    1583             '...pre class="plaintext"...cell_intext...textfield...' 
     1500            u'...pre class="plaintext"...cell_intext...textfield...' 
    15841501        """ 
    15851502        plain_text = worksheet.plain_text(prompts=True, banner=False) 
    15861503        plain_text = escape(plain_text).strip() 
    class Notebook(object): 
    16101527            sage: nb = sagenb.notebook.notebook.Notebook(tmp_dir()+'.sagenb') 
    16111528            sage: W = nb.create_new_worksheet('Test', 'admin') 
    16121529            sage: nb.html_edit_window(W, 'admin') 
    1613             '...textarea class="plaintextedit"...{{{id=1|...//...}}}...' 
     1530            u'...textarea class="plaintextedit"...{{{id=1|...//...}}}...' 
    16141531        """ 
    1615         text = worksheet.edit_text() 
    1616         text = escape(text) 
    1617         n_lines = text.count("\n")+1 
    16181532 
    16191533        return template(os.path.join("html", "notebook", "edit_window.html"), 
    16201534                        worksheet = worksheet, 
    16211535                        worksheet_filename = worksheet.filename(), 
    1622                         username = username, text = text, n_lines = n_lines, 
    1623                         JSMATH = JSMATH, JEDITABLE_TINYMCE = JEDITABLE_TINYMCE) 
     1536                        username = username) 
    16241537 
    16251538    def html_beforepublish_window(self, worksheet, username): 
    16261539        r""" 
    class Notebook(object): 
    16421555            sage: nb = sagenb.notebook.notebook.Notebook(tmp_dir()+'.sagenb') 
    16431556            sage: W = nb.create_new_worksheet('Test', 'admin') 
    16441557            sage: nb.html_beforepublish_window(W, 'admin') 
    1645             '...want to publish this worksheet?...re-publish when changes...' 
     1558            u'...want to publish this worksheet?...re-publish when changes...' 
    16461559        """ 
    16471560        msg = """You can publish your worksheet to the Internet, where anyone will be able to access and view it online. 
    16481561        Your worksheet will be assigned a unique address (URL) that you can send to your friends and colleagues.<br/><br/> 
    class Notebook(object): 
    17081621            sage: nb = sagenb.notebook.notebook.Notebook(tmp_dir()+'.sagenb') 
    17091622            sage: W = nb.create_new_worksheet('Test', 'admin') 
    17101623            sage: nb.html_upload_data_window(W, 'admin') 
    1711             '...Upload or Create Data File...Browse...url...name of a new...' 
     1624            u'...Upload or Create Data File...Browse...url...name of a new...' 
    17121625        """ 
    17131626        return template(os.path.join("html", "notebook", "upload_data_window.html"), 
    1714                         worksheet = ws, worksheet_filename = ws.filename(), 
    1715                         username = username, 
    1716                         JSMATH = JSMATH, JEDITABLE_TINYMCE = JEDITABLE_TINYMCE) 
     1627                        worksheet = ws, username = username) 
    17171628 
    1718     def html(self, worksheet_filename=None, username='guest', show_debug=False, admin=False): 
     1629    def html(self, worksheet_filename=None, username='guest', show_debug=False, 
     1630             admin=False, do_print=False): 
    17191631        r""" 
    17201632        Return the HTML for a worksheet's index page. 
    17211633 
    class Notebook(object): 
    17381650            sage: nb = sagenb.notebook.notebook.Notebook(tmp_dir()+'.sagenb') 
    17391651            sage: W = nb.create_new_worksheet('Test', 'admin') 
    17401652            sage: nb.html(W.filename(), 'admin') 
    1741             '...Test...cell_input...plainclick...state_number...worksheet_locked=false...' 
     1653            u'...Test...cell_input...plainclick...state_number...' 
    17421654        """ 
    17431655        if worksheet_filename is None or worksheet_filename == '': 
    17441656            worksheet_filename = None 
    class Notebook(object): 
    17491661            except KeyError: 
    17501662                W = None 
    17511663 
    1752         template_page = os.path.join("html", "notebook", "index.html") 
     1664        template_page = os.path.join("html", "notebook", "worksheet_page.html") 
    17531665        if W.docbrowser(): 
    17541666            template_page = os.path.join("html", "notebook", "doc_page.html") 
     1667        elif do_print: 
     1668            template_page = os.path.join('html', 'notebook', 'print_worksheet.html') 
     1669        elif W.is_published() or self.user_is_guest(username): 
     1670            template_page = os.path.join('html', 'notebook', 'guest_worksheet_page.html') 
    17551671 
    17561672        return template(template_page, worksheet = W, 
    1757                         worksheet_filename = W.filename(), 
    1758                         worksheet_html = W.html(), notebook = self, 
    1759                         username = username, show_debug = show_debug, 
    1760                         JSMATH = JSMATH, JEDITABLE_TINYMCE = JEDITABLE_TINYMCE) 
     1673                        notebook = self, do_print=do_print, 
     1674                        username = username, show_debug = show_debug) 
    17611675 
    17621676#################################################################### 
    17631677 
    def make_path_relative(dir): 
    19941908# Misc 
    19951909########################################################## 
    19961910 
    1997 def clean_name(name): 
    1998     return ''.join([x if (x.isalnum() or x == '_') else '_' for x in name]) 
    19991911 
    20001912def sort_worksheet_list(v, sort, reverse): 
    20011913    """ 
  • sagenb/notebook/template.py

    diff --git a/sagenb/notebook/template.py b/sagenb/notebook/template.py
    a b AUTHORS: 
    1717 
    1818import jinja 
    1919 
    20 from jinja.filters import stringfilter 
     20from jinja.filters import stringfilter, simplefilter 
    2121 
    2222import os, re, sys 
    2323 
    2424from sagenb.misc.misc import SAGE_VERSION, DATA 
     25from sagenb.notebook.cell import number_of_rows 
     26from sagenb.notebook.jsmath import math_parse 
    2527 
    2628 
    2729TEMPLATE_PATH = os.path.join(DATA, 'sage') 
    def css_escape(string): 
    4143 
    4244    EXAMPLES:: 
    4345 
    44         sage: from sagenb.notebook.template import contained_in, env, css_escape 
     46        sage: from sagenb.notebook.template import env, css_escape 
    4547        sage: escaper = css_escape() 
    4648        sage: print(escaper(env, {}, '12abcd')) 
    4749        12abcd 
    def css_escape(string): 
    7173    """ 
    7274    return css_illegal_re.sub('-', string) 
    7375 
    74 def contained_in(container): 
     76def prettify_time_ago(t): 
    7577    """ 
    76     Given a container, returns a function which takes an environment, 
    77     context, and value and returns True if that value is in the 
    78     container and False otherwise.  This is registered and used as a 
    79     test in the templates. 
     78    Converts seconds to a meaningful string. 
     79 
     80    INPUT 
     81 
     82    - t -- time in seconds 
     83 
     84    """ 
     85    if t < 60: 
     86        s = int(t) 
     87        if s == 1: 
     88            return "1 second" 
     89        return "%d seconds"%s 
     90    if t < 3600: 
     91        m = int(t/60) 
     92        if m == 1: 
     93            return "1 minute" 
     94        return "%d minutes"%m 
     95    if t < 3600*24: 
     96        h = int(t/3600) 
     97        if h == 1: 
     98            return "1 hour" 
     99        return "%d hours"%h 
     100    d = int(t/(3600*24)) 
     101    if d == 1: 
     102        return "1 day" 
     103    return "%d days"%d 
     104 
     105def clean_name(name): 
     106    """ 
     107    Converts a string to a safe/clean name by converting non-alphanumeric characters to underscores. 
    80108 
    81109    INPUT: 
    82110 
    83     - ``container`` - a container, e.g., a list or dictionary 
     111    - name -- a string 
    84112 
    85113    EXAMPLES:: 
    86114 
    87         sage: from sagenb.notebook.template import contained_in 
    88         sage: f = contained_in([1,2,3]) 
    89         sage: f(None, None, 2) 
    90         True 
    91         sage: f(None, None, 4) 
    92         False 
     115        sage: from sagenb.notebook.template import clean_name 
     116        sage: print clean_name('this!is@bad+string') 
     117        this_is_bad_string 
    93118    """ 
    94     def wrapped(env, context, value): 
    95         return value in container 
    96     return wrapped 
    97  
     119    return ''.join([x if x.isalnum() else '_' for x in name]) 
    98120 
    99121env.filters['css_escape'] = css_escape 
    100 env.tests['contained_in'] = contained_in 
    101  
    102 #A dictionary containing the default context 
    103 #The values in this dictionary will be updated 
    104 #by the 
    105 default_context = {'sitename': 'Sage Notebook', 
    106                    'sage_version': SAGE_VERSION} 
     122env.filters['number_of_rows'] = simplefilter(number_of_rows) 
     123env.filters['clean_name'] = stringfilter(clean_name) 
     124env.filters['prettify_time_ago'] = simplefilter(prettify_time_ago) 
     125env.filters['math_parse'] = stringfilter(math_parse) 
     126env.filters['max'] = simplefilter(max) 
    107127 
    108128def template(filename, **user_context): 
    109129    """ 
    def template(filename, **user_context): 
    126146 
    127147        sage: from sagenb.notebook.template import template 
    128148        sage: s = template(os.path.join('html', 'yes_no.html')); type(s) 
    129         <type 'str'> 
     149        <type 'unicode'> 
    130150        sage: 'Yes' in s 
    131151        True 
    132  
    133         sage: from sagenb.notebook.template import template 
    134152        sage: u = unicode('Are Gröbner bases awesome?','utf-8') 
    135153        sage: s = template(os.path.join('html', 'yes_no.html'), message=u) 
    136         sage: 'Gr\xc3\xb6bner' in s 
     154        sage: u'Gr\xf6bner' in s 
    137155        True 
    138156    """ 
     157    from sagenb.notebook.notebook import JSMATH, JEDITABLE_TINYMCE 
     158    from twist import notebook 
     159    #A dictionary containing the default context 
     160    default_context = {'sitename': 'Sage Notebook', 
     161                       'sage_version': SAGE_VERSION, 
     162                       'JSMATH': JSMATH, 
     163                       'JEDITABLE_TINYMCE': JEDITABLE_TINYMCE, 
     164                       'conf': notebook.conf() if notebook else None} 
    139165    try: 
    140166        tmpl = env.get_template(filename) 
    141167    except jinja.exceptions.TemplateNotFound: 
    def template(filename, **user_context): 
    143169    context = dict(default_context) 
    144170    context.update(user_context) 
    145171    r = tmpl.render(**context) 
    146     return r.encode('utf-8') 
     172    return r 
  • sagenb/notebook/twist.py

    diff --git a/sagenb/notebook/twist.py b/sagenb/notebook/twist.py
    a b def message(msg, cont='/'): 
    135135    return template(os.path.join('html', 'error_message.html'), 
    136136                    **template_dict) 
    137137 
     138class Response(http.Response): 
     139    """ 
     140    An adapter for ``twisted.web2.http.Response`` that automatically 
     141    encodes its stream into UTF-8. 
     142 
     143    INPUT: 
     144 
     145    - code -- HTTP status code for the response 
     146 
     147    - headers -- headers to be sent 
     148 
     149    - stream -- content body to send 
     150    """ 
     151    def __init__(self, code=None, headers=None, stream=None): 
     152        if stream is not None: 
     153            if isinstance(stream, unicode): 
     154                stream = stream.encode('utf-8', 'ignore') 
     155        super(Response, self).__init__(code, headers, stream) 
     156 
    138157def HTMLResponse(*args, **kwds): 
    139158    """ 
    140159    Returns an HTMLResponse object whose 'Content-Type' header has been set 
    def HTMLResponse(*args, **kwds): 
    148167        <Headers: Raw: {'content-type': ['text/html; charset=utf-8']} Parsed: {'content-type': <RecalcNeeded>}> 
    149168 
    150169    """ 
    151     response = http.Response(*args, **kwds) 
     170    response = Response(*args, **kwds) 
    152171    response.headers.addRawHeader('Content-Type', 'text/html; charset=utf-8') 
    153172    return response 
    154173 
    class SettingsPage(resource.PostableReso 
    10081027 
    10091028        td['admin'] = nu.is_admin() 
    10101029 
    1011         s = template(os.path.join('html', 'account_settings.html'), **td) 
     1030        s = template(os.path.join('html', 'settings', 'account_settings.html'), **td) 
    10121031        return HTMLResponse(stream = s) 
    10131032 
    10141033 
    class NotebookSettingsPage(resource.Post 
    10231042 
    10241043        template_dict = {} 
    10251044        template_dict['auto_table'] = notebook.conf().html_table(updated) 
    1026         s = template(os.path.join('html', 'notebook_settings.html'), 
     1045        template_dict['admin'] = notebook.user(self.username).is_admin() 
     1046        template_dict['username'] = self.username 
     1047        s = template(os.path.join('html', 'settings', 'notebook_settings.html'), 
    10271048                     **template_dict) 
    1028         return http.Response(stream = s) 
     1049        return HTMLResponse(stream = s) 
    10291050 
    10301051 
    10311052######################################################## 
    class Worksheet_cell_list(WorksheetResou 
    10381059    """ 
    10391060    def render(self, ctx): 
    10401061        W = self.worksheet 
    1041         v = encode_list([W.state_number(), W.html_cell_list()]) 
     1062        # TODO: Send and actually use the body's HTML. 
     1063        v = encode_list([W.state_number(), '']) 
     1064#        v = encode_list([W.state_number(), W.html_cell_list()]) 
    10421065        return HTMLResponse(stream=v) 
    10431066 
    10441067 
    class Worksheet_publish(WorksheetResourc 
    13241347class Worksheet_rating_info(WorksheetResource, resource.Resource): 
    13251348    def render(self, ctx): 
    13261349        s = self.worksheet.html_ratings_info() 
    1327         return HTMLResponse(stream=message(''' 
    1328         <h2 align=center>Ratings for %s</h2> 
    1329         <h3 align=center><a href='/home/%s'>Go to the worksheet.</a> 
    1330         <br><br> 
    1331         <table width=70%%align=center border=1 cellpadding=10 cellspacing=0> 
    1332         <tr bgcolor="#7799bb"><td width=30em>User</td><td width=10em align=center>Rating</td><td width=10em align=center width=60em>Comment</td></tr> 
    1333         %s 
    1334         </table> 
    1335         <br><br> 
    1336         '''%(self.worksheet.name(), self.worksheet.filename(), s))) 
    1337  
     1350        return HTMLResponse(stream=s) 
    13381351 
    13391352class Worksheet_rate(WorksheetResource, resource.Resource): 
    13401353    def render(self, ctx): 
    class Worksheet_interrupt(WorksheetResou 
    14391452        s = self.worksheet.interrupt() 
    14401453        return HTMLResponse(stream='ok' if s else 'failed') 
    14411454 
    1442 class Worksheet_plain(WorksheetResource, resource.Resource): 
    1443     def render(self, ctx): 
    1444         s = notebook.plain_text_worksheet_html(self.name) 
    1445         return HTMLResponse(stream=s) 
    1446  
    14471455class Worksheet_hide_all(WorksheetResource, resource.Resource): 
    14481456    def render(self, ctx): 
    14491457        self.worksheet.hide_all() 
    class Worksheet_delete_all_output(Worksh 
    14661474 
    14671475class Worksheet_print(WorksheetResource, resource.Resource): 
    14681476    def render(self, ctx): 
    1469         s = notebook.worksheet_html(self.name, do_print=True) 
     1477        s = notebook.html(self.name, do_print=True) 
    14701478        return HTMLResponse(stream=s) 
    14711479 
    14721480 
    class Main_css(resource.Resource): 
    18041812    def render(self, ctx): 
    18051813        s = css.css() 
    18061814        gzip_handler(ctx) 
    1807         response = http.Response(stream=s) 
     1815        response = Response(stream=s) 
    18081816        response.headers.addRawHeader('Content-Type', 'text/css; charset=utf-8') 
    18091817        return response 
    18101818 
    1811 class Reset_css(resource.Resource): 
    1812     def render(self, ctx): 
    1813         s = template(os.path.join('css', 'reset.css')) 
    1814         gzip_handler(ctx) 
    1815         return http.Response(stream=s) 
    1816  
    18171819class CSS(resource.Resource): 
    18181820    addSlash = True 
    18191821 
    class CSS(resource.Resource): 
    18251827        return static.File(os.path.join(css_path, name)) 
    18261828 
    18271829setattr(CSS, 'child_main.css', Main_css()) 
    1828 setattr(CSS, 'child_reset.css', Reset_css()) 
    18291830 
    18301831############################ 
    18311832 
    class JSMath_js(resource.Resource): 
    18421843                     jsmath_macros = jsmath_macros, 
    18431844                     jsmath_image_fonts = jsmath_image_fonts) 
    18441845 
    1845         return http.Response(stream=s) 
     1846        return Response(stream=s) 
    18461847 
    18471848class Main_js(resource.Resource): 
    18481849    def render(self, ctx): 
    18491850        gzip_handler(ctx) 
    18501851        s = js.javascript() 
    1851         return http.Response(stream=s) 
     1852        return Response(stream=s) 
    18521853 
    18531854class Keyboard_js_specific(resource.Resource): 
    18541855    def __init__(self, browser_os): 
    class Keyboard_js_specific(resource.Reso 
    18561857 
    18571858    def render(self, ctx): 
    18581859        gzip_handler(ctx) 
    1859         return http.Response(stream = self.s) 
     1860        return Response(stream = self.s) 
    18601861 
    18611862class Keyboard_js(resource.Resource): 
    18621863    def childFactory(self, request, browser_os): 
    class RegistrationPage(resource.Postable 
    21662167        # VALIDATE OVERALL. 
    21672168        if empty == required: 
    21682169            # All required fields are empty.  Not really an error. 
    2169             form = template(os.path.join('html', 'registration.html'), 
     2170            form = template(os.path.join('html', 'accounts', 'registration.html'), 
    21702171                            **empty_form_dict) 
    21712172            return HTMLResponse(stream = form) 
    21722173        elif validated != required: 
    class RegistrationPage(resource.Postable 
    21742175            errors = len(required) - len(validated) 
    21752176            template_dict['error'] = 'E ' if errors == 1 else 'Es ' 
    21762177 
    2177             form = template(os.path.join('html', 'registration.html'), 
     2178            form = template(os.path.join('html', 'accounts', 'registration.html'), 
    21782179                            **template_dict) 
    21792180            return HTMLResponse(stream = form) 
    21802181 
    class RegistrationPage(resource.Postable 
    21852186            template_dict['username_taken'] = True 
    21862187            template_dict['error'] = 'E ' 
    21872188 
    2188             form = template(os.path.join('html', 'registration.html'), 
     2189            form = template(os.path.join('html', 'accounts', 'registration.html'), 
    21892190                            **template_dict) 
    21902191            return HTMLResponse(stream = form) 
    21912192 
    class ForgotPassPage(resource.Resource): 
    22662267 
    22672268            return HTMLResponse(stream=message("A new password has been sent to your e-mail address.", '/')) 
    22682269        else: 
    2269             s = template(os.path.join('html', 'account_recovery.html')) 
     2270            s = template(os.path.join('html', 'accounts', 'account_recovery.html')) 
    22702271        return HTMLResponse(stream=s) 
    22712272 
    22722273class ListOfUsers(resource.Resource): 
    class ListOfUsers(resource.Resource): 
    23032304        users = sorted(notebook.valid_login_names()) 
    23042305        del users[users.index('admin')] 
    23052306        template_dict['users'] = [notebook.user(i) for i in users] 
    2306         return HTMLResponse(stream = template(os.path.join('html', 'user_management.html'), **template_dict)) 
     2307        template_dict['admin'] = notebook.user(self.username).is_admin() 
     2308        template_dict['username'] = self.username 
     2309        return HTMLResponse(stream = template(os.path.join('html', 'settings', 'user_management.html'), **template_dict)) 
    23072310 
    23082311class AdminAddUser(resource.PostableResource): 
    2309     def __init__(self, userdb): 
    2310         self.userdb = userdb 
     2312    def __init__(self, username): 
     2313        self.username = username 
    23112314 
    23122315    def render(self, request): 
    2313  
     2316        template_dict = {'admin': notebook.user(self.username).is_admin(), 
     2317                         'username': self.username} 
    23142318        if 'username' in request.args: 
    23152319            username = request.args['username'][0] 
    23162320            if not is_valid_username(username): 
    2317                 return HTMLResponse(stream=template(os.path.join('html', 'admin_add_user.html'), error='username_invalid', username=username)) 
     2321                return HTMLResponse(stream=template(os.path.join('html', 'settings', 'admin_add_user.html'), 
     2322                                                    error='username_invalid', username=username, **template_dict)) 
    23182323 
    23192324            from random import choice 
    23202325            import string 
    23212326            chara = string.letters + string.digits 
    23222327            password = ''.join([choice(chara) for i in range(8)]) 
    23232328            if username in notebook.usernames(): 
    2324                 return HTMLResponse(stream=template(os.path.join('html', 'admin_add_user.html'), error='username_taken', username=username)) 
     2329                return HTMLResponse(stream=template(os.path.join('html', 'settings', 'admin_add_user.html'), 
     2330                                                    error='username_taken', username_input=username, **template_dict)) 
    23252331            notebook.add_user(username, password, '', force=True) 
    2326             return HTMLResponse(stream=message('The temporary password for the new user <em>%s</em> is <em>%s</em>' % (username, password), '/adduser')) 
     2332            return HTMLResponse(stream=message('The temporary password for the new user <em>%s</em> is <em>%s</em>' % 
     2333                                               (username, password), '/adduser')) 
    23272334        else: 
    2328             return HTMLResponse(stream=template(os.path.join('html', 'admin_add_user.html'))) 
     2335             
     2336            return HTMLResponse(stream=template(os.path.join('html', 'settings', 'admin_add_user.html'), **template_dict)) 
    23292337 
    23302338class InvalidPage(resource.Resource): 
    23312339    addSlash = True 
    class UserToplevel(Toplevel): 
    24812489    # better call userchildFactory it in the base class (Toplevel)! 
    24822490    def userchildFactory(self, request, name): 
    24832491        try: 
    2484             return UserToplevel.__dict__['userchild_%s'%name](username = self.username) 
    2485         except KeyError: 
     2492            return getattr(self.__class__, 'userchild_%s' % name )(username = self.username) 
     2493        except AttributeError: 
    24862494            pass 
    24872495 
    24882496    userchild_doc = Doc 
    setattr(UserToplevel, 'userchild_downloa 
    25242532 
    25252533class AdminToplevel(UserToplevel): 
    25262534    addSlash = True 
    2527  
     2535     
    25282536    userchild_home = WorksheetsAdmin 
    2529     child_users = ListOfUsers 
    2530     child_adduser = AdminAddUser 
    2531     child_notebooksettings = NotebookSettingsPage 
     2537    userchild_users = ListOfUsers 
     2538    userchild_adduser = AdminAddUser 
     2539    userchild_notebooksettings = NotebookSettingsPage 
    25322540 
    25332541def user_type(username): 
    25342542    # one of admin, guest, user 
  • sagenb/notebook/worksheet.py

    diff --git a/sagenb/notebook/worksheet.py b/sagenb/notebook/worksheet.py
    a b import sagenb.misc.support as support 
    4444 
    4545# Imports specifically relevant to the sage notebook 
    4646from   cell import Cell, TextCell 
    47 from template import template 
     47from template import template, clean_name, prettify_time_ago 
    4848 
    4949# Set some constants that will be used for regular expressions below. 
    5050whitespace = re.compile('\s')  # Match any whitespace character 
    def worksheet_filename(name, owner): 
    111111        sage: sagenb.notebook.worksheet.worksheet_filename('Example#%&! work\\sheet 3', 'sage10') 
    112112        'sage10/Example_____work_sheet_3' 
    113113    """ 
    114     return os.path.join(owner, _notebook.clean_name(name)) 
     114    return os.path.join(owner, clean_name(name)) 
    115115 
    116116def Worksheet_from_basic(obj, notebook_worksheet_directory): 
    117117    """ 
    class Worksheet(object): 
    11851185                del self.__published_version 
    11861186                raise ValueError 
    11871187        except AttributeError: 
    1188             raise ValueError, "no published version" 
     1188            raise ValueError("no published version") 
    11891189 
    11901190    def set_worksheet_that_was_published(self, W): 
    11911191        """ 
    class Worksheet(object): 
    12451245            [('hilbert', 3, 'this is great'), ('riemann', 0, 'this lacks content')] 
    12461246        """ 
    12471247        r = self.ratings() 
     1248        x = int(x) 
    12481249        for i in range(len(r)): 
    12491250            if r[i][0] == username: 
    12501251                r[i] = (username, x, comment) 
    class Worksheet(object): 
    13201321            sage: W.rate(0, 'this lacks content', 'riemann') 
    13211322            sage: W.rate(3, 'this is great', 'hilbert') 
    13221323            sage: W.html_ratings_info() 
    1323             '<tr><td>hilbert</td><td align=center>3</td><td>this is great</td></tr>\n<tr><td>riemann</td><td align=center>0</td><td>this lacks content</td></tr>' 
     1324            u'...hilbert...3...this is great...this lacks content...' 
    13241325        """ 
    1325         ratings = self.ratings() 
    1326         lines = [] 
    1327         for z in sorted(ratings): 
    1328             if len(z) == 2: 
    1329                 person, rating = z 
    1330                 comment = '' 
    1331             else: 
    1332                 person, rating, comment = z 
    1333             lines.append('<tr><td>%s</td><td align=center>%s</td><td>%s</td></tr>'%( 
    1334                 person, rating, '&nbsp;' if not comment else comment)) 
    1335         return '\n'.join(lines) 
     1326        return template(os.path.join('html', 'worksheet', 'ratings_info.html'), 
     1327                        worksheet = self) 
    13361328 
    13371329    def rating(self): 
    13381330        """ 
    class Worksheet(object): 
    19731965        filenames = os.listdir(self.snapshot_directory()) 
    19741966        filenames.sort() 
    19751967        t = time.time() 
    1976         v = [(convert_seconds_to_meaningful_time_span(t - float(os.path.splitext(x)[0]))+ self._saved_by_info(x), x)  \ 
     1968        v = [(prettify_time_ago(t - float(os.path.splitext(x)[0]))+ self._saved_by_info(x), x)  \ 
    19771969             for x in filenames] 
    19781970        self.__snapshot_data = v 
    19791971        return v 
    class Worksheet(object): 
    22692261                print msg 
    22702262        return cells_html 
    22712263 
    2272     def html(self, include_title=True, do_print=False, 
    2273              confirm_before_leave=False, read_only=False): 
     2264    def html(self, do_print=False, publish=False): 
    22742265        r""" 
    22752266        INPUT: 
    22762267 
    class Worksheet(object): 
    22872278            sage: nb = sagenb.notebook.notebook.Notebook(tmp_dir()+'.sagenb') 
    22882279            sage: W = nb.create_new_worksheet('Test', 'admin') 
    22892280            sage: W.html() 
    2290             '\n\n\n<div class="cell_input_active" id="cell_resizer"></div>\n\n<div class="worksheet_cell_list" id...' 
     2281            u'...cell_input_active...worksheet_cell_list...cell_1...cell_output_html_1...' 
    22912282        """ 
    2292         return template(os.path.join("html", "worksheet", "worksheet.html"), 
    2293                         published = self.is_published(), 
    2294                         do_print = do_print, confirm_before_leave = confirm_before_leave, 
    2295                         cells_html = self.html_cell_list(do_print=do_print), 
    2296                         cell_id_list = self.cell_id_list(), 
    2297                         state_number = self.state_number()) 
     2283        return template(os.path.join("html", "notebook", "worksheet.html"), 
     2284                        do_print=do_print, publish=publish, worksheet=self) 
    22982285 
    22992286    def truncated_name(self, max=30): 
    23002287        name = self.name() 
    class Worksheet(object): 
    23112298    def set_is_doc_worksheet(self, value): 
    23122299        self.__is_doc_worksheet = value 
    23132300 
    2314     def html_save_discard_buttons(self): 
    2315         r""" 
    2316         OUTPUT: 
    2317  
    2318         - string -- the HTML for the save, discard, etc. buttons 
    2319  
    2320         EXAMPLES:: 
    2321  
    2322             sage: nb = sagenb.notebook.notebook.Notebook(tmp_dir()+'.sagenb') 
    2323             sage: W = nb.create_new_worksheet('Test', 'admin') 
    2324             sage: W.html_save_discard_buttons() 
    2325             '\n\n<button name="button_save" title="Save changes" onClick="save_worksheet();">Save<...' 
    2326         """ 
    2327         return template(os.path.join("html", "worksheet", "save_discard_buttons.html"), 
    2328                         doc_worksheet = self.is_doc_worksheet()) 
    2329  
    2330     def html_share_publish_buttons(self, select=None, backwards=False): 
    2331         r""" 
    2332         INPUT: 
    2333  
    2334         - select - a boolean 
    2335  
    2336         - backwards - a boolean 
    2337  
    2338         OUTPUT: 
    2339  
    2340         - string -- the HTML for the share, publish, etc. buttons 
    2341  
    2342         EXAMPLES:: 
    2343  
    2344             sage: nb = sagenb.notebook.notebook.Notebook(tmp_dir()+'.sagenb') 
    2345             sage: W = nb.create_new_worksheet('Test', 'admin') 
    2346             sage: W.html_share_publish_buttons() 
    2347             '...Print...Worksheet...Edit...Undo...Share...Publish...' 
    2348         """ 
    2349         return template(os.path.join("html", "worksheet", "share_publish_buttons.html"), 
    2350                         worksheet = self, select = select, backwards = backwards) 
    2351  
    2352     def html_menu(self): 
    2353         r""" 
    2354         OUTPUT: 
    2355  
    2356         - string -- the HTML for the menus of the worksheet 
    2357  
    2358         EXAMPLES:: 
    2359  
    2360             sage: nb = sagenb.notebook.notebook.Notebook(tmp_dir()+'.sagenb') 
    2361             sage: W = nb.create_new_worksheet('Test', 'admin') 
    2362             sage: W.html_menu() 
    2363             '...File...Action...Data...pretty_print...' 
    2364         """ 
    2365         return template(os.path.join("html", "worksheet", "menu.html"), 
    2366                         name = _notebook.clean_name(self.name()), 
    2367                         filename_ = self.filename(), data = sorted(self.attached_data_files()), 
    2368                         systems_enumerated = enumerate(self.notebook().systems()), 
    2369                         system_names = self.notebook().system_names(), 
    2370                         current_system_index = self.system_index(), 
    2371                         pretty_print = self.pretty_print(), 
    2372                         doc_worksheet = self.is_doc_worksheet()) 
    2373  
    2374     def html_worksheet_body(self, do_print, publish=False): 
    2375         r""" 
    2376         INPUT: 
    2377  
    2378         - publish - a boolean stating whether the worksheet is published 
    2379  
    2380         - do_print - a boolean 
    2381  
    2382         OUTPUT: 
    2383  
    2384         - string -- the HTML for the File menu of the worksheet 
    2385  
    2386         EXAMPLES:: 
    2387  
    2388             sage: nb = sagenb.notebook.notebook.Notebook(tmp_dir()+'.sagenb') 
    2389             sage: W = nb.create_new_worksheet('Test', 'admin') 
    2390             sage: W.html_worksheet_body(false) 
    2391             '\n\n<div class="cell_input_active" id="cell_resizer"></div>\n\n<div class="worksheet_cell_list" id...' 
    2392         """ 
    2393         published = self.is_published() or publish 
    2394         ncols = self.notebook().conf()['word_wrap_cols'] 
    2395         cells_html = "" 
    2396         for cell in self.cell_list(): 
    2397             cells_html += cell.html(ncols, do_print=do_print) + '\n' 
    2398  
    2399         return template(os.path.join("html", "worksheet", "worksheet_body.html"), 
    2400                         cells_html = cells_html, 
    2401                         published = published, 
    2402                         do_print = do_print) 
    2403  
    24042301 
    24052302    ########################################################## 
    24062303    # Last edited 
    class Worksheet(object): 
    24462343            sage: W.last_to_edit() 
    24472344            'john' 
    24482345            sage: W.date_edited() 
    2449             time.struct_time(tm_year=2009, tm_mon=10, tm_mday=8, tm_hour=12, tm_min=23, tm_sec=20, tm_wday=3, tm_yday=281, tm_isdst=1) 
     2346            time.struct_time(tm_year=2009, tm_mon=10, tm_mday=..., tm_hour=..., tm_min=23, tm_sec=20, tm_wday=..., tm_yday=..., tm_isdst=...) 
    24502347            sage: t = W.time_since_last_edited() # just test that call works 
    24512348        """ 
    24522349        username = str(username); tm = float(tm) 
    class Worksheet(object): 
    25152412 
    25162413    def html_time_since_last_edited(self): 
    25172414        t = self.time_since_last_edited() 
    2518         tm = convert_seconds_to_meaningful_time_span(t) 
     2415        tm = prettify_time_ago(t) 
    25192416        return template(os.path.join("html", "worksheet", "time_since_last_edited.html"), 
    25202417                        last_editor = self.last_to_edit(), 
    25212418                        time = tm) 
    from sagenb.notebook.all import * 
    37463643 
    37473644        EXAMPLES: First, we set up a new notebook and worksheet.:: 
    37483645 
    3749             sage: nb = sagenb.notebook.notebook.Notebook(tmp_dir()+'.sagenb') 
     3646            sage: nb = sagenb.notebook.notebook.load_notebook(tmp_dir()+'.sagenb') 
    37503647            sage: nb.add_user('sage','sage','sage@sagemath.org',force=True) 
    37513648            sage: W = nb.create_new_worksheet('Test', 'sage') 
    37523649 
    def next_available_id(v): 
    41194016    return i 
    41204017 
    41214018 
    4122 def convert_seconds_to_meaningful_time_span(t): 
    4123     if t < 60: 
    4124         s = int(t) 
    4125         if s == 1: 
    4126             return "1 second" 
    4127         return "%d seconds"%s 
    4128     if t < 3600: 
    4129         m = int(t/60) 
    4130         if m == 1: 
    4131             return "1 minute" 
    4132         return "%d minutes"%m 
    4133     if t < 3600*24: 
    4134         h = int(t/3600) 
    4135         if h == 1: 
    4136             return "1 hour" 
    4137         return "%d hours"%h 
    4138     d = int(t/(3600*24)) 
    4139     if d == 1: 
    4140         return "1 day" 
    4141     return "%d days"%d 
    4142  
    4143  
    41444019def convert_time_to_string(t): 
    41454020    return time.strftime('%B %d, %Y %I:%M %p', time.localtime(float(t))) 
    41464021 
  • sagenb/testing/HTMLTestRunner.py

    diff --git a/sagenb/testing/HTMLTestRunner.py b/sagenb/testing/HTMLTestRunner.py
    a b class HTMLTestRunner(object): 
    347347    results. 
    348348    """ 
    349349    def __init__(self, stream=sys.stdout, verbosity=1, title=None, 
    350                  description=None): 
     350                 description=None, **extra_args): 
    351351        """ 
    352352        Initialize variables. 
    353353        """ 
    class HTMLTestRunner(object): 
    355355        self.verbosity = verbosity 
    356356        self.title = title 
    357357        self.description = description 
     358        self.extra_args = extra_args 
    358359 
    359360        # Set up Pygments syntax highlighting. 
    360361        self.formatter = get_formatter_by_name('html', noclasses=True, 
    class HTMLTestRunner(object): 
    407408        template_dict['title'] = jinja2.escape(self.title) 
    408409        template_dict['description'] = jinja2.escape(self.description) 
    409410        template_dict['sagenb_version'] = SAGENB_VERSION 
     411        template_dict['environment'] = self.extra_args.get('environment') 
    410412        template_dict['start_time'] = str(self.start_time)[:19] 
    411413        template_dict['stop_time'] = str(self.stop_time)[:19] 
    412414        template_dict['elapsed_time'] = self.elapsed_time 
  • sagenb/testing/notebook_test_case.py

    diff --git a/sagenb/testing/notebook_test_case.py b/sagenb/testing/notebook_test_case.py
    a b Notebook Test Case 
    55This contains the base class for all SageNB test cases. 
    66""" 
    77 
    8 from selenium.selenium import selenium 
     8import copy 
     9import os 
     10import pexpect 
     11import re 
     12import shutil 
     13import signal 
     14import subprocess 
     15import tempfile 
     16import time 
    917import unittest 
    1018 
    11 import os, subprocess, pexpect, shutil, time, re, tempfile, signal 
     19from selenium.selenium import selenium 
     20 
     21# Default options. 
     22NB_OPTIONS = { 
     23    'address': 'localhost',   # Should *not* be left empty. 
     24    'directory': '',          # Set automatically if empty.  Must end 
     25                              # in '.sagenb'. 
     26    'open_viewer': False, 
     27    'port': 8000, 
     28    'secure': False 
     29} 
     30SEL_OPTIONS = { 
     31    'server_host': 'localhost', 
     32    'server_port': 4444, 
     33    'environment': '*firefox3 /usr/bin/firefox', 
     34    'browser_url': ''         # Set automatically if empty. 
     35} 
     36 
     37# This is for Google Chrome, which caches '/new_worksheet', for some 
     38# reason. 
     39CACHE_SKIP = 0 
     40 
     41KEY_CODES = { 
     42    'tab': 9, 
     43    'enter': 10, 
     44    'shift': 16 
     45} 
     46 
    1247 
    1348class NotebookTestCase(unittest.TestCase): 
    1449    """ 
    1550    Base class for SageNB test cases. Contains multiple utility 
    1651    functions, and sets up fixtures. 
    1752    """ 
    18     tags = ('seleniumtest',)  
     53    tags = ('seleniumtest',) 
     54 
     55    def cleanup(self): 
     56        nb_dir = self.nb_options['directory'] 
     57 
     58        if os.path.exists(nb_dir): 
     59            twistd_pid_path = os.path.join(nb_dir, 'twistd.pid') 
     60            if os.path.exists(twistd_pid_path): 
     61                twistd_pid_fd = open(twistd_pid_path, 'r') 
     62                twistd_pid = int(twistd_pid_fd.read()) 
     63                try: 
     64                    os.kill(twistd_pid, signal.SIGTERM) 
     65                    os.kill(twistd_pid, signal.SIGKILL) 
     66                except OSError: 
     67                    pass 
     68                twistd_pid_fd.close() 
     69            shutil.rmtree(nb_dir, ignore_errors=True) 
     70 
    1971    def setUp(self): 
    2072        """ 
    2173        Makes sure that the tests start from a fresh slate, and starts 
    2274        the server. 
    2375        """ 
    24         self.temp_dir = os.path.join(tempfile.gettempdir(), 'sagenb_tests') 
    25         if os.path.exists(self.temp_dir + '.sagenb'): 
    26             twistd_pid_path = os.path.join(self.temp_dir + '.sagenb', 'twistd.pid') 
    27             if os.path.exists(twistd_pid_path): 
    28                 twistd_pid = int(open(twistd_pid_path, 'r').read()) 
    29                 try: 
    30                     os.kill(twistd_pid, signal.SIGTERM) 
    31                     os.kill(twistd_pid, signal.SIGKILL) 
    32                 except OSError: 
    33                     pass 
    34             shutil.rmtree(self.temp_dir + '.sagenb') 
    35         os.mkdir(self.temp_dir + '.sagenb') 
    36         self.verification_errors = [] 
     76        self.nb_options = copy.deepcopy(NB_OPTIONS) 
     77        self.nb_options['directory'] = (self.nb_options['directory'] or 
     78                                        os.path.join(tempfile.gettempdir(), 
     79                                                     'sagenb_tests.sagenb')) 
     80        self.sel_options = copy.deepcopy(SEL_OPTIONS) 
     81 
     82        self.cleanup() 
     83        os.mkdir(self.nb_options['directory']) 
    3784        self.start_notebook(initial=True) 
    38         self.selenium = selenium("localhost", 4444, "*firefox3 /usr/bin/firefox", "http://localhost:%d" % self.sagenb_port) 
     85 
     86        self.selenium = selenium(self.sel_options['server_host'], 
     87                                 self.sel_options['server_port'], 
     88                                 self.sel_options['environment'], 
     89                                 self.sel_options['browser_url']) 
    3990        self.selenium.start() 
    4091        self.selenium.open("/") 
    41              
     92 
    4293    def start_notebook(self, initial=False): 
    4394        """ 
    44         Starts the Sage notebook.  If initial is True, then it expects to have to enter 
    45         the initial password twice. 
     95        Starts the Sage notebook.  If initial is True, then it expects 
     96        to have to enter the initial password twice. 
    4697        """ 
    4798        self._p = pexpect.spawn(self._sage_startup_command()) 
    4899        if initial: 
    49100            self._p.sendline("asdfasdf") 
    50101            self._p.sendline("asdfasdf") 
    51102 
    52         port_re = re.compile(r'http://localhost:(\d+)') 
     103        port_re = re.compile(r'http(?:s)?://' + self.nb_options['address'] + 
     104                             r':(\d+)') 
    53105 
    54106        line = self._p.readline() 
    55107        while not port_re.search(line): 
    56108            line = self._p.readline() 
    57          
    58         self.sagenb_port = int(port_re.search(line).group(1)) 
     109 
     110        m = port_re.search(line) 
     111        self.sel_options['browser_url'] = (self.sel_options['browser_url'] or 
     112                                           m.group(0)) 
     113        self.sagenb_port = int(m.group(1)) 
     114 
    59115        self._p.expect("Starting factory") 
    60          
     116 
    61117    def _sage_startup_command(self): 
    62118        """ 
    63119        Command to send to pexpect to start the notebook. 
    64120        """ 
    65         return 'sage -c "notebook(open_viewer=False, directory=\'%s\', port=8000)"'\ 
    66             % self.temp_dir 
     121        return 'sage -c "notebook(**%r)"' % self.nb_options 
    67122 
    68123    def focus_cell(self, id): 
    69124        """ 
    class NotebookTestCase(unittest.TestCase 
    71126        """ 
    72127        sel = self.selenium 
    73128        sel.focus("cell_input_%s" % id) 
    74      
     129 
    75130    def eval_cell(self, id, text, timeout=20000, output=True): 
    76131        """ 
    77132        Evaluates the cell id with input text text. 
    class NotebookTestCase(unittest.TestCase 
    81136        sel = self.selenium 
    82137        id = str(id) 
    83138        sel.type("cell_input_"+id, text) 
    84         self.shift_enter("cell_input_"+id) 
     139        self.evaluate(id) 
    85140        self.wait_for_no_active_cells() 
    86141        if output: 
    87142            return self.get_cell_output(id) 
    88143 
     144    def evaluate(self, id): 
     145        """ 
     146        Triggers evaluation of a given cell. 
     147        """ 
     148#        self.shift_enter("cell_input_"+id) 
     149        self.selenium.get_eval('window.evaluate_cell(%s, 0);' % id) 
     150 
    89151    def _get_cell_output_type(self, id, type='nowrap'): 
    90152        out = '' 
    91153        try: 
    92             out =  self.selenium.get_eval("window.document.getElementById('cell_output_%s_%s').innerHTML"%(type, id)).strip() 
     154            out =  self.selenium.get_eval("window.document.getElementById('cell_output_%s_%s').innerHTML" % (type, id)).strip() 
    93155        except: 
    94156            pass 
    95157        return out 
    class NotebookTestCase(unittest.TestCase 
    102164        out = self._get_cell_output_type(id, 'nowrap') 
    103165        if out == '': 
    104166            out = self._get_cell_output_type(id, 'html') 
    105              
     167 
     168        # Browser contortions. TODO: Simplify this with regular 
     169        # expressions. 
    106170        preshrunk = '<pre class="shrunk">' 
    107         if out.startswith(preshrunk): 
     171        PREshrunk = '<PRE class="shrunk">' 
     172        PREshrunk2 = '<PRE class=shrunk>' 
     173 
     174        if out.startswith(preshrunk) or out.startswith(PREshrunk): 
    108175            out = out[len(preshrunk):-6] 
     176        if out.startswith(PREshrunk2): 
     177            out = out[len(PREshrunk2):-6] 
     178 
    109179        out = out.strip() 
    110180        return out 
    111     
     181 
    112182    def wait_for_no_active_cells(self, timeout=20000): 
    113183        """ 
    114         Tells Selenium to wait until they're are no active cells on the worksheet. 
     184        Tells Selenium to wait until they're are no active cells on 
     185        the worksheet. 
    115186        """ 
    116187        self.selenium.wait_for_condition("selenium.browserbot.getCurrentWindow().active_cell_list.length == 0", "%s"%timeout) 
    117188 
    class NotebookTestCase(unittest.TestCase 
    119190        """ 
    120191        Presses enter in the element ``locator``. 
    121192        """ 
     193#        self.selenium.focus(locator) 
    122194        self.selenium.key_press(locator, '13') 
    123          
     195#        self.selenium.key_press_native(KEY_CODES['enter']) 
     196 
    124197    def shift_enter(self, locator): 
    125198        """ 
    126199        Presses shift-enter in the element ``locator``.   For example, 
    127200        self.shift_enter('cell_input_0') 
    128201        """ 
    129202        sel = self.selenium 
     203#        self.selenium.focus(locator) 
    130204        sel.shift_key_down() 
     205#        sel.key_down_native(KEY_CODES['shift']) 
    131206        self.enter(locator) 
    132207        sel.shift_key_up() 
     208#        sel.key_up_native(KEY_CODES['shift']) 
    133209 
    134210    def tab(self, locator): 
    135211        """ 
    136212        Presses tab in the element ``locator``. 
    137213        """ 
    138214        self.selenium.focus(locator) 
    139         self.selenium.key_press_native(9) 
    140          
     215        self.selenium.key_press_native(KEY_CODES['tab']) 
     216 
     217    def introspect(self, id): 
     218        """ 
     219        Evaluates introspection in the given cell. 
     220        """ 
     221#        self.tab('cell_input_%s' % id) 
     222        self.selenium.get_eval('window.set_cursor_position(window.get_cell(%s), 100);' % id) 
     223        self.selenium.get_eval('window.evaluate_cell_introspection(%s, null, null);' % id) 
     224 
    141225    def save_and_quit(self): 
    142226        """ 
    143227        Save and close the current worksheet and wait until we 
    class NotebookTestCase(unittest.TestCase 
    145229        """ 
    146230        sel = self.selenium 
    147231        sel.click("//button[@name='button_save' and @onclick='save_worksheet_and_close();']") 
    148         self.wait_for_title('Active Worksheets') 
    149232        sel.wait_for_page_to_load("30000") 
     233        self.wait_for_title('Active Worksheets -- Sage') 
    150234 
    151235    def wait_for_title(self, title): 
    152236        """ 
    153         Tells Selenium to wait until the title of the page has changed to 
    154         title since it doesn't recognize many of the page reloads in the Sage 
    155         notebook. 
     237        Tells Selenium to wait until the title of the page has changed 
     238        to title since it doesn't recognize many of the page reloads 
     239        in the Sage notebook. 
    156240        """ 
    157         self.selenium.wait_for_condition('selenium.browserbot.getCurrentWindow().document.title == "%s"'%title, 30000) 
     241        self.selenium.wait_for_condition('selenium.browserbot.getCurrentWindow().document.title.replace(/^\s+|\s+$/g, "") == "%s"'%title, 30000) 
    158242 
    159243    def rename_worksheet(self, new_title): 
    160244        """ 
    class NotebookTestCase(unittest.TestCase 
    162246        """ 
    163247        sel = self.selenium 
    164248        sel.click("worksheet_title") 
    165         # Note: These locators also detect modal prompts that have been hidden, but not deleted. 
     249        # Note: These locators also detect modal prompts that have 
     250        # been hidden, but not deleted. 
    166251        sel.type('//div[contains(@class,"modal-prompt")]//input[@type="text"]', new_title) 
    167252        sel.click('//div[contains(@class, "modal-prompt")]/form/div[@class="button-div"]/button[@type="submit"]') 
    168253        sel.wait_for_condition('selenium.browserbot.getCurrentWindow().$("#worksheet_title").text() == "%s"' % new_title, 5000) 
    class NotebookTestCase(unittest.TestCase 
    170255    def register_user(self, username, password='asdfasdf'): 
    171256        """ 
    172257        Registers a new user for the Sage notebook. 
    173          
     258 
    174259        This assumes that you're at the login page. 
    175260        """ 
    176261        sel = self.selenium 
    177262        sel.click("id=register-link") 
    178263        sel.wait_for_page_to_load(30000) 
    179         self.wait_for_title("Sign up") 
     264        self.wait_for_title("Sign up -- Sage") 
    180265 
    181266        sel.type("username", username) 
    182267        sel.type("password", password) 
    183268        sel.type("retype_password", password) 
    184269        sel.click("id=create-account-button") 
    185270        sel.wait_for_page_to_load(30000) 
    186         self.wait_for_title('Sign in') 
    187         self.assertTrue(sel.is_text_present('regexp:Congratulations ')) 
     271        self.wait_for_title('Sign in -- Sage') 
     272        self.assertTrue(sel.is_text_present('regexp:Congratulations')) 
    188273 
    189274    def login_as(self, username, password='asdfasdf'): 
    190275        """ 
    class NotebookTestCase(unittest.TestCase 
    208293        self.password = None 
    209294 
    210295        sel = self.selenium 
    211         sel.click("//a[@href='/logout']") 
     296        sel.click("link=Sign out") 
    212297        sel.wait_for_page_to_load("30000") 
    213298 
    214299    def go_home(self): 
    class NotebookTestCase(unittest.TestCase 
    222307 
    223308    def create_new_worksheet(self, title = "My New Worksheet"): 
    224309        sel = self.selenium 
    225         sel.open('/new_worksheet') 
     310        self.go_home() 
     311 
     312        global CACHE_SKIP 
     313        CACHE_SKIP += 1 
     314        sel.open('/new_worksheet?%d' % CACHE_SKIP) 
    226315        sel.wait_for_page_to_load("30000") 
    227316        self.assert_(sel.is_element_present('//a[@id="worksheet_title" and contains(text(),"Untitled")]')) 
    228317        sel.type('//div[contains(@class,"modal-prompt")]//input[@type="text"]', title) 
    class NotebookTestCase(unittest.TestCase 
    231320 
    232321    def open_worksheet_with_title(self, title): 
    233322        """ 
    234         Open the worksheet with the given title, starting at  
     323        Open the worksheet with the given title, starting at 
    235324        worksheet list.  This assumes the list contains the title. 
    236325        """ 
    237326        self.go_home() 
    class NotebookTestCase(unittest.TestCase 
    248337        sel = self.selenium 
    249338        sel.click("link=Publish") 
    250339        sel.wait_for_page_to_load("30000") 
    251         sel.click("//input[@value='Yes']") 
     340        sel.click("//button[text()='Yes']") 
    252341        sel.wait_for_page_to_load("30000") 
    253342        sel.click("link=Worksheet") 
    254343        sel.wait_for_page_to_load("30000") 
    class NotebookTestCase(unittest.TestCase 
    261350        sel = self.selenium 
    262351        sel.click("link=Publish") 
    263352        sel.wait_for_page_to_load("30000") 
    264         sel.click("//input[@value='Re-publish worksheet']") 
     353        sel.click("//button[text()='Re-publish worksheet']") 
    265354        sel.wait_for_page_to_load("30000") 
    266355        sel.click("link=Worksheet") 
    267356        sel.wait_for_page_to_load("30000") 
    class NotebookTestCase(unittest.TestCase 
    272361        """ 
    273362        sel = self.selenium 
    274363        sel.open('/pub') 
    275         sel.wait_for_page_to_load("30000")         
     364        sel.wait_for_page_to_load("30000") 
    276365 
    277366    def goto_published_worksheet(self, id): 
    278367        """ 
    class NotebookTestCase(unittest.TestCase 
    283372        sel.click("link=Published") 
    284373        sel.wait_for_page_to_load("30000") 
    285374        sel.click("name-pub-"+id) 
    286         sel.wait_for_condition('selenium.browserbot.getCurrentWindow().worksheet_filename == "%s"'%('pub/'+id), 30000)         
     375        sel.wait_for_condition('selenium.browserbot.getCurrentWindow().worksheet_filename == "%s"'%('pub/'+id), 30000) 
    287376 
    288377    def open_worksheet_with_name(self, name): 
    289378        """ 
    290         Opens the worksheet with the given name. Assumes that client is at list page. 
     379        Opens the worksheet with the given name. Assumes that client 
     380        is at list page. 
    291381        """ 
    292382        sel = self.selenium 
    293383        self.wait_in_window('return this.$("a.worksheetname").attr("title").indexOf("{0}") != -1'.format(name), 
    class NotebookTestCase(unittest.TestCase 
    313403        browser window. Use ``this`` to access the browser window. 
    314404        """ 
    315405        self.selenium.wait_for_condition('(function(){ %s }).apply(selenium.browserbot.getCurrentWindow())' 
    316                                          % string, 
    317                                          timeout) 
     406                                         % string, timeout) 
    318407 
    319408    def stop_notebook(self): 
    320409        """ 
    class NotebookTestCase(unittest.TestCase 
    323412        self._p.sendline(chr(3)+chr(3)) 
    324413        self._p.kill(signal.SIGKILL) 
    325414        self._p = None 
    326          
     415 
    327416    def tearDown(self): 
    328417        """ 
    329418        Stops the notebook and cleans up. 
    330419        """ 
    331420        self.stop_notebook() 
    332         try: 
    333             shutil.rmtree(self.temp_dir + '.sagenb') 
    334         except OSError: 
    335             pass 
     421        self.cleanup() 
    336422        self.selenium.stop() 
  • sagenb/testing/run_tests.py

    diff --git a/sagenb/testing/run_tests.py b/sagenb/testing/run_tests.py
    a b Functions for running SageNB tests. This 
    77 
    88NOTE: 
    99 
    10 Selenium tests assume a Selenium server is running on port 4444. The 
     10The SageNB tests tests assume a Selenium server or Grid hub is running 
     11with the options given in :mod:`sagenb.testing.notebook_test_case` or 
     12set by :func:`setup_tests`. 
     13 
     14 
    1115Selenium server can be downloaded from the Selenium `download page 
    1216<http://seleniumhq.org/download/>`_ as part of the Selenium RC package 
    13 and can be run with `java -jar selenium-server.jar`. 
     17and can be run with `java -jar selenium-server.jar`.  To set up 
     18Selenium Grid, please visit its `home page 
     19<http://selenium-grid.seleniumhq.org/>`_ for instructions. 
    1420 
    1521TODO: 
    1622 
    TODO: 
    2329# of the possibility of incompatible libraries and binaries with 
    2430# those of the user's browser (e.g., Python, etc.) 
    2531 
    26 from subprocess import Popen 
    27 import unittest, os 
     32import unittest 
    2833 
     34import notebook_test_case 
    2935from sagenb.misc.misc import browser 
     36from tests import test_accounts, test_worksheet, test_worksheet_list 
    3037 
    31 from tests import test_accounts, test_worksheet, test_worksheet_list 
     38CASES = { 
     39    'TestAccounts': test_accounts, 
     40    'TestWorksheet': test_worksheet, 
     41    'TestWorksheetList': test_worksheet_list 
     42    } 
    3243 
    3344all_tests = unittest.TestSuite((test_accounts.suite, 
    3445                               test_worksheet.suite, 
    3546                               test_worksheet_list.suite)) 
    3647 
    37 def run_tests(): 
     48 
     49def setup_tests(address='localhost', secure=False, 
     50                environment='*firefox3 /usr/bin/firefox'): 
    3851    """ 
    39     Runs all SageNB tests. This assumes that a Selenium server is running on port 4444. 
     52    Sets selected options for SageNB Selenium tests. 
     53 
     54    INPUT: 
     55 
     56    - ``address`` - a string (default: 'localhost'); address of the 
     57      network interface at which the notebook server listens.  Do not 
     58      leave this empty; see :mod:`sagenb.testing.notebook_test_case` 
     59      for details. 
     60 
     61    - ``secure`` - a boolean (default: False); whether to launch a 
     62      secure notebook server.  Note: Browser security warnings will 
     63      yield failed tests.  To work around these in Firefox, close all 
     64      windows, create a new profile (e.g., `firefox -P selenium`), 
     65      browse to a secure notebook server, accept the certificate, and 
     66      quit.  Then launch the Selenium server with, e.g., 
     67 
     68        java -jar selenium-server -firefoxProfileTemplate $HOME/selenium/firefox 
     69 
     70      and run the tests.  A minimal profile template directory can 
     71      contain just the files `cert8.db` and `cert_override.txt`. 
     72 
     73    - ``environment`` - a string (default: '*firefox3 
     74      /usr/bin/firefox'); the browser environment in which to run the 
     75      tests.  The path is optional.  However, for the Selenium server 
     76      to have complete control over the launched browser, it's best to 
     77      give the full path to the browser *executable* (i.e., not a 
     78      shell script). 
     79 
     80      Possible environments include '*chrome', '*firefox', 
     81      '*firefox3', '*googlechrome', '*iexplore', '*opera', '*safari'. 
     82 
     83    EXAMPLES:: 
     84 
     85        sage: import sagenb.testing.run_tests as rt               # not tested 
     86        sage: env = '*firefox3 /usr/lib64/firefox-3.5.6/firefox'  # not tested 
     87        sage: rt.setup_tests('localhost', True, env)              # not tested 
     88        sage: rt.run_any()                                        # not tested 
     89        sage: rt.setup_tests('localhost', True, '*opera')         # not tested 
     90        sage: rt.run_and_report()                                 # not tested 
    4091    """ 
    41     unittest.TextTestRunner(verbosity=2).run(all_tests) 
     92    # TODO: Add a directory option for parallel testing. 
     93    notebook_test_case.NB_OPTIONS['address'] = address 
     94    notebook_test_case.NB_OPTIONS['secure'] = secure 
     95    notebook_test_case.SEL_OPTIONS['environment'] = environment 
    4296 
    43 def run_test(suite): 
     97 
     98def run_any(tests=all_tests, make_report=False, **kwargs): 
    4499    """ 
    45     Runs a test suite. This assumes that a Selenium server is running on port 4444. 
     100    Creates and runs an ad hoc test suite from a test name, case, 
     101    suite, or a mixed list thereof.  If no matching tests are found, 
     102    no tests are run. 
     103 
     104    INPUT: 
     105 
     106    - ``tests`` - a string, :class:`unittest.TestCase`, 
     107      :class:`unittest.TestSuite`, or a mixed list thereof.  Strings 
     108      can be test names, with or without the prefix 'test_'. 
     109 
     110    - ``make_report`` - a boolean (default: False); whether to 
     111      generate a HTML report of the test results. 
     112 
     113    - ``kwargs`` - a dictionary; additional keyword options to pass to 
     114      :func:`run_suite` or :func:`run_and_report`. 
     115 
     116    EXAMPLES:: 
     117 
     118        sage: import sagenb.testing.run_tests as rt              # not tested 
     119        sage: rt.run_any('simple_evaluation', make_report=True)  # not tested 
     120        sage: rt.run_any(['4088', 'test_3711'], verbosity=1)     # not tested 
     121        sage: rt.run_any('foo', False)                           # not tested 
     122        sage: rt.run_any(rt.test_accounts.TestAccounts)          # not tested 
     123        sage: rt.run_any(make_report=True)                       # not tested 
    46124    """ 
    47     unittest.TextTestRunner(verbosity=2).run(suite) 
    48      
     125    import inspect 
     126    from_name = unittest.TestLoader().loadTestsFromName 
     127    from_case = unittest.TestLoader().loadTestsFromTestCase 
     128 
     129    if not isinstance(tests, list): 
     130        tests = [tests] 
     131 
     132    alist = [] 
     133    for t in tests: 
     134        if isinstance(t, str): 
     135            if not t.startswith('test_'): 
     136                t = 'test_' + t 
     137            for c in CASES: 
     138                try: 
     139                    alist.append(from_name(c + '.' + t, module = CASES[c])) 
     140                except AttributeError: 
     141                    pass 
     142        elif inspect.isclass(t) and issubclass(t, unittest.TestCase): 
     143            alist.append(from_case(t)) 
     144        elif isinstance(t, unittest.TestSuite): 
     145            alist.append(t) 
     146 
     147    if alist: 
     148        suite = unittest.TestSuite(alist) 
     149        tot = suite.countTestCases() 
     150 
     151        environment = notebook_test_case.SEL_OPTIONS['environment'] 
     152        print 'Running %d test%s in environment %s...' % (tot, '' if tot == 1 else 's', environment) 
     153 
     154        if make_report: 
     155            run_and_report(suite, environment = environment, **kwargs) 
     156        else: 
     157            run_suite(suite, **kwargs) 
     158 
     159 
     160def run_suite(suite=all_tests, verbosity=2): 
     161    """ 
     162    Runs a test suite. 
     163 
     164    For the SageNB test suite, this assumes a Selenium server or Grid 
     165    hub is running with the options given in 
     166    :mod:`sagenb.testing.notebook_test_case` or set by 
     167    :func:`setup_tests` 
     168 
     169    INPUT: 
     170 
     171    - ``suite`` - a TestSuite instance (default: all_tests); the test 
     172      suite to run 
     173 
     174    - ``verbosity`` - an integer (default: 2); how verbosely to report 
     175      instantaneous test results 
     176 
     177    EXAMPLES:: 
     178 
     179        sage: import sagenb.testing.run_tests as rt               # not tested 
     180        sage: rt.run_suite()                                      # not tested 
     181        sage: rt.run_suite(rt.test_worksheet.suite, verbosity=1)  # not tested 
     182    """ 
     183    unittest.TextTestRunner(verbosity=verbosity).run(suite) 
     184 
     185 
    49186def run_and_report(suite=all_tests, verbosity=2, report_filename='report.html', 
    50187                   title='Sage Notebook Tests', 
    51188                   description='Selenium test results', 
    52                    open_viewer=True): 
     189                   open_viewer=True, **kwargs): 
    53190    """ 
    54191    Runs a test suite and generates a HTML report with the outcome 
    55192    (pass, fail, or error) and output, including any tracebacks, for 
    56     each test, plus overall statistics.  This assumes that a Selenium 
    57     server is running on port 4444. 
     193    each test, plus overall statistics. 
     194 
     195    For the SageNB test suite, this assumes a Selenium server or Grid 
     196    hub is running with the options given in 
     197    :mod:`sagenb.testing.notebook_test_case` or set by 
     198    :func:`setup_tests`. 
    58199 
    59200    INPUT: 
    60201 
    def run_and_report(suite=all_tests, verb 
    75216 
    76217    - ``open_viewer`` - a boolean (default: True); whether to open 
    77218      the report in a web browser 
     219 
     220    - ``kwargs`` - a dictionary; extra keyword arguments passed to the 
     221      test runner's constructor 
     222 
     223    EXAMPLES:: 
     224 
     225        sage: import sagenb.testing.run_tests as rt             # not tested 
     226        sage: rt.run_and_report()                               # not tested 
     227        sage: rt.run_and_report(report_filename='test1.html')   # not tested 
     228        sage: rt.run_and_report(rt.test_accounts.suite)         # not tested 
    78229    """ 
    79230    from HTMLTestRunner import HTMLTestRunner 
    80231 
    81232    report_fd = open(report_filename, 'w') 
    82233    runner = HTMLTestRunner(verbosity = verbosity, stream = report_fd, 
    83                             title = title, description = description) 
     234                            title = title, description = description, 
     235                            **kwargs) 
    84236    runner.run(suite) 
    85237 
    86238    if open_viewer: 
    87         Popen(browser() + ' ' + os.path.abspath(report_filename), shell=True) 
     239        import os, subprocess 
     240        subprocess.Popen(browser() + ' ' + os.path.abspath(report_filename), 
     241                         shell=True) 
    88242 
    89243 
    90244if __name__ == '__main__': 
    91     run_tests() 
    92  
    93  
    94  
    95  
    96  
    97  
     245    run_suite() 
  • sagenb/testing/tests/test_accounts.py

    diff --git a/sagenb/testing/tests/test_accounts.py b/sagenb/testing/tests/test_accounts.py
    a b AUTHORS: 
    66 
    77- Mike Hansen (?) -- initial revision 
    88 
    9 - Tim Dumol (Oct. 28, 2009) -- made the tests work again. Separated this out. 
     9- Tim Dumol (Oct. 28, 2009) -- made the tests work again. Separated 
     10  this out. 
    1011""" 
    1112import unittest 
    1213 
    from sagenb.testing.notebook_test_case i 
    1415 
    1516class TestAccounts(NotebookTestCase): 
    1617    def _sage_startup_command(self): 
    17         return 'sage -c "notebook(open_viewer=False, directory=\'%s\', accounts=True)"'\ 
    18             % self.temp_dir 
     18        self.nb_options['accounts'] = True 
     19        return super(TestAccounts, self)._sage_startup_command() 
     20 
     21    def setUp(self): 
     22        super(TestAccounts, self).setUp() 
     23        self.register_user('mike') 
     24        self.register_user('chris') 
    1925 
    2026    def test_3960(self): 
    2127        """ 
    2228        Tests to make sure that Trac ticket #3960 is actually fixed. 
    2329        """ 
    2430        sel = self.selenium 
    25          
    26         self.register_user('mike') 
    27         self.register_user('chris') 
    2831 
    2932        self.login_as('mike') 
    3033        self.create_new_worksheet() 
    class TestAccounts(NotebookTestCase): 
    3437 
    3538        self.login_as('chris') 
    3639        self.goto_published_worksheet(0) 
    37          
     40 
    3841        sel.click("link=Edit a copy.") 
    3942        # Simply waiting for the page to load fails with slow computers. 
    40         self.wait_in_window('return this.location == "http://localhost:%d/home/chris/0/"' 
    41                            % self.sagenb_port, 30000) 
     43#        self.wait_in_window('return this.location == "%s/home/chris/0/"' % 
     44#                            self.sel_options['browser_url'], 30000) 
    4245        sel.wait_for_page_to_load(30000) 
     46 
    4347        self.wait_in_window('return this.$.trim(this.$("#cell_output_nowrap_1").text()) == 4', 30000) 
    4448 
    45         self.assertEqual(sel.get_location(), 'http://localhost:%d/home/chris/0/' % self.sagenb_port) 
     49        self.assertEqual(sel.get_location(), '%s/home/chris/0/' % 
     50                         self.sel_options['browser_url']) 
    4651        self.assertEqual(self.get_cell_output(1), '4') 
    47         self.assert_(sel.is_text_present('by chris'), 'chris does not own the worksheet') 
     52        self.assert_(sel.is_text_present('by chris'), 
     53                     'chris does not own the worksheet') 
    4854 
    4955    def test_4088(self): 
    5056        """ 
    51         Check to see that the 'Welcome to Sage!' message is not visible on the 
    52         published worksheets screen when there are no worksheets. 
     57        Check to see that the 'Welcome to Sage!' message is not 
     58        visible on the published worksheets screen when there are no 
     59        worksheets. 
    5360        """ 
    5461        sel = self.selenium 
    5562 
    56         self.login_as('admin') 
     63        self.login_as('mike') 
    5764        sel.click("link=Published") 
    5865        sel.wait_for_page_to_load("30000") 
    5966 
    60         self.assert_(not sel.is_text_present('Welcome to Sage!'), 'welcome message is still present') 
    61  
     67        self.assert_(not sel.is_text_present('Welcome to Sage!'), 
     68                     'welcome message is still present') 
    6269 
    6370    def test_4050(self): 
    6471        """ 
    6572        Tests to make sure that Trac ticket #4050 is actually fixed. 
    6673        """ 
    6774        sel = self.selenium 
    68          
    69         self.register_user('mike') 
    70         self.register_user('chris') 
    7175 
    7276        self.login_as('mike') 
    7377        self.create_new_worksheet() 
    class TestAccounts(NotebookTestCase): 
    8084        self.login_as('chris') 
    8185        sel.click("name-mike-0") 
    8286        sel.wait_for_page_to_load("30000")